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))); } }
static void _buddy_icon_record_cb(AvahiRecordBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata) { BonjourBuddy *buddy = userdata; AvahiBuddyImplData *idata = buddy->mdns_impl_data; switch (event) { case AVAHI_BROWSER_CACHE_EXHAUSTED: case AVAHI_BROWSER_ALL_FOR_NOW: /* Ignore these "meta" informational events */ return; case AVAHI_BROWSER_NEW: bonjour_buddy_got_buddy_icon(buddy, rdata, size); break; case AVAHI_BROWSER_REMOVE: case AVAHI_BROWSER_FAILURE: purple_debug_error("bonjour", "Error retrieving buddy icon record: %s\n", avahi_strerror(avahi_client_errno(avahi_record_browser_get_client(b)))); break; } /* Stop listening */ avahi_record_browser_free(b); if (idata->buddy_icon_rec_browser == b) { idata->buddy_icon_rec_browser = NULL; } }
static void resolve_callback( AvahiRecordBrowser *r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, uint16_t clazz, uint16_t *domain, const void *rdata, size_t size, AvahiLookupResultFlags flags, AVAHI_GCC_UNUSED void* userdata) { assert(r); /* Called whenever a service has been resolved successfully or timed out */ switch (event) { case AVAHI_RESOLVER_FAILURE: fprintf(stderr, "(Resolver) Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(avahi_record_browser_get_client(r)))); break; case AVAHI_RESOLVER_FOUND: { char /*a[AVAHI_ADDRESS_STR_MAX], */ *t; fprintf(stderr, "Service '%s'':\n", name); /* avahi_address_snprint(a, sizeof(a), address); t = avahi_string_list_to_string(txt); fprintf(stderr, "\t%s:%u (%s)\n" "\tTXT=%s\n" "\tcookie is %u\n" "\tis_local: %i\n" "\tour_own: %i\n" "\twide_area: %i\n" "\tmulticast: %i\n" "\tcached: %i\n", host_name, port, a, t, avahi_string_list_get_service_cookie(txt), !!(flags & AVAHI_LOOKUP_RESULT_LOCAL), !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN), !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA), !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST), !!(flags & AVAHI_LOOKUP_RESULT_CACHED)); */ avahi_free(t); } default: fprintf(stderr, "Unknown avahi resolvers event\n"); } avahi_record_browser_free(r); }
void QxtMDNS::cancelLookup() { if (qxt_d().recordbrowser != NULL) avahi_record_browser_free(qxt_d().recordbrowser); if (qxt_d().client != NULL) avahi_client_free(qxt_d().client); deleteLater(); }
static void browse_record_callback(AvahiRecordBrowser *b, AvahiIfIndex intf, AvahiProtocol proto, AvahiBrowserEvent event, const char *hostname, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata) { struct mdns_record_browser *rb_data; AvahiAddress addr; char address[AVAHI_ADDRESS_STR_MAX]; int family; int ret; rb_data = (struct mdns_record_browser *)userdata; if (event == AVAHI_BROWSER_CACHE_EXHAUSTED) DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s, proto %d): no more results (CACHE_EXHAUSTED)\n", hostname, proto); else if (event == AVAHI_BROWSER_ALL_FOR_NOW) DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s, proto %d): no more results (ALL_FOR_NOW)\n", hostname, proto); else if (event == AVAHI_BROWSER_FAILURE) DPRINTF(E_LOG, L_MDNS, "Avahi Record Browser (%s, proto %d) failure: %s\n", hostname, proto, MDNSERR); else if (event == AVAHI_BROWSER_REMOVE) return; // Not handled - record browser lifetime too short for this to happen if (event != AVAHI_BROWSER_NEW) goto out_free_record_browser; ret = avahi_address_make(&addr, proto, rdata, size); // Not an avahi function despite the name if (ret < 0) return; family = avahi_proto_to_af(proto); avahi_address_snprint(address, sizeof(address), &addr); // Avahi will sometimes give us link-local addresses in 169.254.0.0/16 or // fe80::/10, which (most of the time) are useless // - see also https://lists.freedesktop.org/archives/avahi/2012-September/002183.html if ((proto == AVAHI_PROTO_INET && is_v4ll(&addr.data.ipv4)) || (proto == AVAHI_PROTO_INET6 && is_v6ll(&addr.data.ipv6))) { DPRINTF(E_WARN, L_MDNS, "Ignoring announcement from %s, address %s is link-local\n", hostname, address); return; } DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s, proto %d): NEW record %s for service type '%s'\n", hostname, proto, address, rb_data->mb->type); // Execute callback (mb->cb) with all the data rb_data->mb->cb(rb_data->name, rb_data->mb->type, rb_data->domain, hostname, family, address, rb_data->port, &rb_data->txt_kv); // Stop record browser out_free_record_browser: keyval_clear(&rb_data->txt_kv); free(rb_data->name); free(rb_data->domain); free(rb_data); avahi_record_browser_free(b); }
void _mdns_delete_buddy(BonjourBuddy *buddy) { AvahiBuddyImplData *idata = buddy->mdns_impl_data; g_return_if_fail(idata != NULL); if (idata->buddy_icon_rec_browser != NULL) avahi_record_browser_free(idata->buddy_icon_rec_browser); if (idata->resolver != NULL) avahi_service_resolver_free(idata->resolver); g_free(idata); buddy->mdns_impl_data = NULL; }
JNIEXPORT jlong JNICALL Java_avahi4j_RecordBrowser_releaseBrowser(JNIEnv *e, jobject t, jlong ptr){ dprint("[LOG] Entering %s\n", __PRETTY_FUNCTION__); struct avahi4j_record_browser *browser = (struct avahi4j_record_browser *) (uintptr_t) ptr; int result; result = avahi_record_browser_free(browser->browser); if(browser->browserObject) (*e)->DeleteGlobalRef(e, browser->browserObject); XFREE(browser); CHECK_N_RET(avahi_record_browser_free, result); }
void avahi_client_free(AvahiClient *client) { assert(client); if (client->bus) /* Disconnect in advance, so that the free() functions won't * issue needless server calls */ #ifdef HAVE_DBUS_CONNECTION_CLOSE dbus_connection_close(client->bus); #else dbus_connection_disconnect(client->bus); #endif while (client->groups) avahi_entry_group_free(client->groups); while (client->domain_browsers) avahi_domain_browser_free(client->domain_browsers); while (client->service_browsers) avahi_service_browser_free(client->service_browsers); while (client->service_type_browsers) avahi_service_type_browser_free(client->service_type_browsers); while (client->service_resolvers) avahi_service_resolver_free(client->service_resolvers); while (client->host_name_resolvers) avahi_host_name_resolver_free(client->host_name_resolvers); while (client->address_resolvers) avahi_address_resolver_free(client->address_resolvers); while (client->record_browsers) avahi_record_browser_free(client->record_browsers); if (client->bus) dbus_connection_unref(client->bus); avahi_free(client->version_string); avahi_free(client->host_name); avahi_free(client->host_name_fqdn); avahi_free(client->domain_name); avahi_free(client); }
void _mdns_delete_buddy(BonjourBuddy *buddy) { AvahiBuddyImplData *idata = buddy->mdns_impl_data; g_return_if_fail(idata != NULL); if (idata->buddy_icon_rec_browser != NULL) avahi_record_browser_free(idata->buddy_icon_rec_browser); while(idata->resolvers != NULL) { AvahiSvcResolverData *rd = idata->resolvers->data; _cleanup_resolver_data(rd); idata->resolvers = g_slist_delete_link(idata->resolvers, idata->resolvers); } g_free(idata); buddy->mdns_impl_data = NULL; }
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); }
static void browse_record_callback_v6(AvahiRecordBrowser *b, AvahiIfIndex intf, AvahiProtocol proto, AvahiBrowserEvent event, const char *hostname, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata) { char address[INET6_ADDRSTRLEN + IF_NAMESIZE + 1]; char ifname[IF_NAMESIZE]; struct in6_addr addr; struct mdns_record_browser *rb_data; int ll; int len; int ret; rb_data = (struct mdns_record_browser *)userdata; switch (event) { case AVAHI_BROWSER_NEW: if (size != sizeof(addr.s6_addr)) { DPRINTF(E_WARN, L_MDNS, "Got RR type AAAA size %ld (should be %ld)\n", (long)size, (long)sizeof(addr.s6_addr)); return; } memcpy(&addr.s6_addr, rdata, sizeof(addr.s6_addr)); ll = is_v6ll(&addr); if (ll && !(rb_data->mb->flags & MDNS_WANT_V6LL)) { DPRINTF(E_DBG, L_MDNS, "Discarding IPv6 LL, not interested (service %s)\n", rb_data->name); return; } else if (!ll && !(rb_data->mb->flags & MDNS_WANT_V6)) { DPRINTF(E_DBG, L_MDNS, "Discarding IPv6, not interested (service %s)\n", rb_data->name); return; } if (!inet_ntop(AF_INET6, &addr.s6_addr, address, sizeof(address))) { DPRINTF(E_LOG, L_MDNS, "Could not print IPv6 address: %s\n", strerror(errno)); return; } if (ll) { if (!if_indextoname(intf, ifname)) { DPRINTF(E_LOG, L_MDNS, "Could not map interface index %d to a name\n", intf); return; } len = strlen(address); ret = snprintf(address + len, sizeof(address) - len, "%%%s", ifname); if ((ret < 0) || (ret > sizeof(address) - len)) { DPRINTF(E_LOG, L_MDNS, "Buffer too short for scoped IPv6 LL\n"); return; } } DPRINTF(E_DBG, L_MDNS, "Service %s, hostname %s resolved to %s\n", rb_data->name, hostname, address); /* Execute callback (mb->cb) with all the data */ rb_data->mb->cb(rb_data->name, rb_data->mb->type, rb_data->domain, hostname, AF_INET6, address, rb_data->port, &rb_data->txt_kv); /* Got a suitable address, stop record browser */ break; case AVAHI_BROWSER_REMOVE: /* Not handled - record browser lifetime too short for this to happen */ return; case AVAHI_BROWSER_CACHE_EXHAUSTED: case AVAHI_BROWSER_ALL_FOR_NOW: DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s v6): no more results (%s)\n", hostname, (event == AVAHI_BROWSER_CACHE_EXHAUSTED) ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; case AVAHI_BROWSER_FAILURE: DPRINTF(E_LOG, L_MDNS, "Avahi Record Browser (%s v6) failure: %s\n", hostname, avahi_strerror(avahi_client_errno(avahi_record_browser_get_client(b)))); break; } /* Cleanup when done/error */ keyval_clear(&rb_data->txt_kv); free(rb_data->name); free(rb_data->domain); free(rb_data); avahi_record_browser_free(b); }
static void browse_record_callback_v4(AvahiRecordBrowser *b, AvahiIfIndex intf, AvahiProtocol proto, AvahiBrowserEvent event, const char *hostname, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata) { char address[INET_ADDRSTRLEN]; struct in_addr addr; struct mdns_record_browser *rb_data; int ll; rb_data = (struct mdns_record_browser *)userdata; switch (event) { case AVAHI_BROWSER_NEW: if (size != sizeof(addr.s_addr)) { DPRINTF(E_WARN, L_MDNS, "Got RR type A size %ld (should be %ld)\n", (long)size, (long)sizeof(addr.s_addr)); return; } memcpy(&addr.s_addr, rdata, sizeof(addr.s_addr)); ll = is_v4ll(&addr); if (ll && !(rb_data->mb->flags & MDNS_WANT_V4LL)) { DPRINTF(E_DBG, L_MDNS, "Discarding IPv4 LL, not interested (service %s)\n", rb_data->name); return; } else if (!ll && !(rb_data->mb->flags & MDNS_WANT_V4)) { DPRINTF(E_DBG, L_MDNS, "Discarding IPv4, not interested (service %s)\n", rb_data->name); return; } if (!inet_ntop(AF_INET, &addr.s_addr, address, sizeof(address))) { DPRINTF(E_LOG, L_MDNS, "Could not print IPv4 address: %s\n", strerror(errno)); return; } DPRINTF(E_DBG, L_MDNS, "Service %s, hostname %s resolved to %s\n", rb_data->name, hostname, address); /* Execute callback (mb->cb) with all the data */ rb_data->mb->cb(rb_data->name, rb_data->mb->type, rb_data->domain, hostname, AF_INET, address, rb_data->port, &rb_data->txt_kv); /* Got a suitable address, stop record browser */ break; case AVAHI_BROWSER_REMOVE: /* Not handled - record browser lifetime too short for this to happen */ return; case AVAHI_BROWSER_CACHE_EXHAUSTED: case AVAHI_BROWSER_ALL_FOR_NOW: DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s v4): no more results (%s)\n", hostname, (event == AVAHI_BROWSER_CACHE_EXHAUSTED) ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; case AVAHI_BROWSER_FAILURE: DPRINTF(E_LOG, L_MDNS, "Avahi Record Browser (%s v4) failure: %s\n", hostname, avahi_strerror(avahi_client_errno(avahi_record_browser_get_client(b)))); break; } keyval_clear(&rb_data->txt_kv); free(rb_data->name); free(rb_data->domain); free(rb_data); avahi_record_browser_free(b); }
AvahiRecordBrowser* avahi_record_browser_new( AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, uint16_t clazz, uint16_t type, AvahiLookupFlags flags, AvahiRecordBrowserCallback callback, void *userdata) { AvahiRecordBrowser *b = NULL; DBusMessage *message = NULL, *reply = NULL; DBusError error; char *path; int32_t i_protocol, i_interface; uint32_t u_flags; assert(client); assert(name); assert(callback); dbus_error_init(&error); if (!avahi_client_is_connected(client)) { avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE); goto fail; } if (!(b = avahi_new(AvahiRecordBrowser, 1))) { avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } b->client = client; b->callback = callback; b->userdata = userdata; b->path = NULL; b->name = NULL; b->clazz = clazz; b->type = type; b->interface = interface; b->protocol = protocol; AVAHI_LLIST_PREPEND(AvahiRecordBrowser, record_browsers, client->record_browsers, b); if (!(b->name = avahi_strdup(name))) { avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "RecordBrowserNew"))) { avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } i_interface = (int32_t) interface; i_protocol = (int32_t) protocol; u_flags = (uint32_t) flags; if (!dbus_message_append_args( message, DBUS_TYPE_INT32, &i_interface, DBUS_TYPE_INT32, &i_protocol, DBUS_TYPE_STRING, &name, DBUS_TYPE_UINT16, &clazz, DBUS_TYPE_UINT16, &type, DBUS_TYPE_UINT32, &u_flags, DBUS_TYPE_INVALID)) { avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) || dbus_error_is_set(&error)) { avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); goto fail; } if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) || dbus_error_is_set(&error) || !path) { avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); goto fail; } if (!(b->path = avahi_strdup(path))) { /* FIXME: We don't remove the object on the server side */ avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } dbus_message_unref(message); dbus_message_unref(reply); return b; fail: if (dbus_error_is_set(&error)) { avahi_client_set_dbus_error(client, &error); dbus_error_free(&error); } if (b) avahi_record_browser_free(b); if (message) dbus_message_unref(message); if (reply) dbus_message_unref(reply); return NULL; }