diff --git a/dns_sd.c b/dns_sd.c index 2d37fc5b0..6032a2c44 100644 --- a/dns_sd.c +++ b/dns_sd.c @@ -40,7 +40,8 @@ static void dnssd_free_discovery_data(struct dns_sd_discovery_data *d) } /* Some functions for handling common linked list operations */ -static void dnssd_remove_node(struct dns_sd_discovery_data **ddata, int n) +static void dnssd_remove_node(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata, int n) { struct dns_sd_discovery_data *d, *ndata, *ldata, *tdata; int i; @@ -81,10 +82,10 @@ struct iio_scan_backend_context { struct addrinfo *res; }; -static int dnssd_fill_context_info(struct iio_context_info *info, - char *hostname, char *addr_str, int port) +static int dnssd_fill_context_info(const struct iio_context_params *params, + struct iio_context_info *info, + char *hostname, char *addr_str, int port) { - const struct iio_context_params *params = &default_params; struct iio_context *ctx; char uri[sizeof("ip:") + MAXHOSTNAMELEN + sizeof (":65535") + 1]; char description[255], *p; @@ -168,7 +169,8 @@ void dnssd_context_scan_free(struct iio_scan_backend_context *ctx) * This is sort of silly, but we have seen non-iio devices advertised * and discovered on the network. Oh well.... */ -void port_knock_discovery_data(struct dns_sd_discovery_data **ddata) +void port_knock_discovery_data(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata) { struct dns_sd_discovery_data *d, *ndata; int i, ret; @@ -216,7 +218,7 @@ void port_knock_discovery_data(struct dns_sd_discovery_data **ddata) if (found) { i++; } else { - dnssd_remove_node(&d, i); + dnssd_remove_node(params, &d, i); } } iio_mutex_unlock(d->lock); @@ -225,7 +227,8 @@ void port_knock_discovery_data(struct dns_sd_discovery_data **ddata) return; } -void remove_dup_discovery_data(struct dns_sd_discovery_data **ddata) +void remove_dup_discovery_data(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata) { struct dns_sd_discovery_data *d, *ndata, *mdata; int i, j; @@ -245,7 +248,7 @@ void remove_dup_discovery_data(struct dns_sd_discovery_data **ddata) !strcmp(mdata->addr_str, ndata->addr_str)){ IIO_DEBUG("Removing duplicate in list: '%s'\n", ndata->hostname); - dnssd_remove_node(&d, j); + dnssd_remove_node(params, &d, j); } j++; } @@ -259,11 +262,12 @@ void remove_dup_discovery_data(struct dns_sd_discovery_data **ddata) int dnssd_context_scan(struct iio_scan_backend_context *ctx, struct iio_scan_result *scan_result) { + const struct iio_context_params *params = get_default_params(); struct iio_context_info **info; struct dns_sd_discovery_data *ddata, *ndata; int ret = 0; - ret = dnssd_find_hosts(&ddata); + ret = dnssd_find_hosts(params, &ddata); /* if we return an error when no devices are found, then other scans will fail */ if (ret == -ENXIO) { @@ -282,7 +286,7 @@ int dnssd_context_scan(struct iio_scan_backend_context *ctx, break; } - ret = dnssd_fill_context_info(*info, + ret = dnssd_fill_context_info(params, *info, ndata->hostname, ndata->addr_str,ndata->port); if (ret < 0) { IIO_DEBUG("Failed to add %s (%s) err: %d\n", ndata->hostname, ndata->addr_str, ret); @@ -291,16 +295,17 @@ int dnssd_context_scan(struct iio_scan_backend_context *ctx, } fail: - dnssd_free_all_discovery_data(ddata); + dnssd_free_all_discovery_data(params, ddata); return ret; } -int dnssd_discover_host(char *addr_str, size_t addr_len, uint16_t *port) +int dnssd_discover_host(const struct iio_context_params *params, char *addr_str, + size_t addr_len, uint16_t *port) { struct dns_sd_discovery_data *ddata; int ret = 0; - ret = dnssd_find_hosts(&ddata); + ret = dnssd_find_hosts(params, &ddata); if (ret < 0) goto host_fail; @@ -311,14 +316,15 @@ int dnssd_discover_host(char *addr_str, size_t addr_len, uint16_t *port) } host_fail: - dnssd_free_all_discovery_data(ddata); + dnssd_free_all_discovery_data(params, ddata); /* negative error codes, 0 for no data */ return ret; } -void dnssd_free_all_discovery_data(struct dns_sd_discovery_data *d) +void dnssd_free_all_discovery_data(const struct iio_context_params *params, + struct dns_sd_discovery_data *d) { while (d) - dnssd_remove_node(&d, 0); + dnssd_remove_node(params, &d, 0); } diff --git a/dns_sd.h b/dns_sd.h index 3fb370b34..b7b8e7e2f 100644 --- a/dns_sd.h +++ b/dns_sd.h @@ -35,6 +35,7 @@ struct addrinfo; struct AvahiSimplePoll; struct AvahiAddress; +struct iio_context_params; /* Common structure which all dns_sd_[*] files fill out * Anything that is dynamically allocated (malloc) needs to be managed @@ -50,6 +51,10 @@ struct dns_sd_discovery_data { struct dns_sd_discovery_data *next; }; +struct dns_sd_cb_data { + struct dns_sd_discovery_data *d; + const struct iio_context_params *params; +}; /* This functions is implemented in network.c, but used in dns_sd.c */ @@ -60,25 +65,31 @@ int create_socket(const struct addrinfo *addrinfo); */ /* Resolves all IIO hosts on the available networks, and passes back a linked list */ -int dnssd_find_hosts(struct dns_sd_discovery_data ** ddata); +int dnssd_find_hosts(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata); /* Deallocates complete list of discovery data */ -void dnssd_free_all_discovery_data(struct dns_sd_discovery_data *d); +void dnssd_free_all_discovery_data(const struct iio_context_params *params, + struct dns_sd_discovery_data *d); /* These functions are common, and found in dns_sd.c, but are used in the * dns_sd_[*].c implementations or network.c */ /* Passed back the first (random) IIOD service resolved by DNS DS. */ -int dnssd_discover_host(char *addr_str, size_t addr_len, uint16_t *port); +int dnssd_discover_host(const struct iio_context_params *params, + char *addr_str, size_t addr_len, uint16_t *port); /* remove duplicates from the list */ -void remove_dup_discovery_data(struct dns_sd_discovery_data **ddata); +void remove_dup_discovery_data(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata); /* port knocks */ -void port_knock_discovery_data(struct dns_sd_discovery_data **ddata); +void port_knock_discovery_data(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata); /* Use dnssd to resolve a given hostname */ -int dnssd_resolve_host(const char *hostname, char *ip_addr, const int addr_len); +int dnssd_resolve_host(const struct iio_context_params *params, + const char *hostname, char *ip_addr, const int addr_len); #endif /* __IIO_DNS_SD_H */ diff --git a/dns_sd_avahi.c b/dns_sd_avahi.c index c8d917726..15eeb50cc 100644 --- a/dns_sd_avahi.c +++ b/dns_sd_avahi.c @@ -50,11 +50,13 @@ static struct dns_sd_discovery_data *new_discovery_data(void) return d; } -static void avahi_process_resolved(struct dns_sd_discovery_data *ddata, +static void avahi_process_resolved(struct dns_sd_cb_data *adata, const AvahiAddress *addr, const char *host_name, const uint16_t port) { + struct dns_sd_discovery_data *ddata = adata->d; + /* Avahi is multi-threaded, so lock the list */ iio_mutex_lock(ddata->lock); ddata->resolved++; @@ -106,7 +108,7 @@ static void __avahi_resolver_cb(AvahiServiceResolver *resolver, AvahiLookupResultFlags flags, void *d) { - struct dns_sd_discovery_data *ddata = d; + struct dns_sd_cb_data *adata = d; AvahiClient *client; int err; @@ -126,7 +128,7 @@ static void __avahi_resolver_cb(AvahiServiceResolver *resolver, avahi_strerror(err)); break; case AVAHI_RESOLVER_FOUND: { - avahi_process_resolved(ddata, address, host_name, port); + avahi_process_resolved(adata, address, host_name, port); IIO_DEBUG("Avahi Resolver : service '%s' of type '%s' in domain '%s':\n", name, type, domain); break; @@ -144,7 +146,8 @@ static void avahi_host_resolver(AvahiHostNameResolver *resolver, AvahiLookupResultFlags flags, void *d) { - struct dns_sd_discovery_data *ddata = d; + struct dns_sd_cb_data *adata = d; + struct dns_sd_discovery_data *ddata = adata->d; AvahiClient *client; int err; @@ -157,7 +160,7 @@ static void avahi_host_resolver(AvahiHostNameResolver *resolver, host_name, avahi_strerror(err)); break; case AVAHI_RESOLVER_FOUND: - avahi_process_resolved(ddata, address, host_name, IIOD_PORT); + avahi_process_resolved(adata, address, host_name, IIOD_PORT); break; } @@ -175,7 +178,8 @@ static void __avahi_browser_cb(AvahiServiceBrowser *browser, AvahiLookupResultFlags flags, void *d) { - struct dns_sd_discovery_data *ddata = (struct dns_sd_discovery_data *) d; + struct dns_sd_cb_data *adata = d; + struct dns_sd_discovery_data *ddata = adata->d; struct AvahiClient *client = avahi_service_browser_get_client(browser); unsigned int i; struct timespec ts; @@ -199,7 +203,7 @@ static void __avahi_browser_cb(AvahiServiceBrowser *browser, if(!avahi_service_resolver_new(client, iface, proto, name, type, domain, AVAHI_PROTO_UNSPEC, 0, - __avahi_resolver_cb, d)) { + __avahi_resolver_cb, adata)) { IIO_ERROR("Failed to resolve service '%s\n", name); } else { iio_mutex_lock(ddata->lock); @@ -233,9 +237,11 @@ static void __avahi_browser_cb(AvahiServiceBrowser *browser, * The returned value is zero on success, negative error code on failure. */ -int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) +int dnssd_find_hosts(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata) { struct dns_sd_discovery_data *d; + struct dns_sd_cb_data adata; AvahiClient *client; AvahiServiceBrowser *browser; int ret = 0; @@ -244,16 +250,19 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) if (!d) return -ENOMEM; + adata.params = params; + adata.d = d; + d->lock = iio_mutex_create(); if (!d->lock) { - dnssd_free_all_discovery_data(d); + dnssd_free_all_discovery_data(params, d); return -ENOMEM; } d->poll = avahi_simple_poll_new(); if (!d->poll) { iio_mutex_destroy(d->lock); - dnssd_free_all_discovery_data(d); + dnssd_free_all_discovery_data(params, d); return -ENOMEM; } @@ -268,7 +277,7 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) browser = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_iio._tcp", NULL, 0, - __avahi_browser_cb, d); + __avahi_browser_cb, &adata); if (!browser) { ret = avahi_client_errno(client); IIO_ERROR("Unable to create Avahi DNS-SD browser: %s\n", @@ -280,8 +289,8 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) avahi_simple_poll_loop(d->poll); if (d->resolved) { - port_knock_discovery_data(&d); - remove_dup_discovery_data(&d); + port_knock_discovery_data(params, &d); + remove_dup_discovery_data(params, &d); } else ret = -ENXIO; @@ -296,10 +305,11 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) return ret; } -static void avahi_resolve_host(struct dns_sd_discovery_data *d, +static void avahi_resolve_host(struct dns_sd_cb_data *adata, const char *hostname, const AvahiProtocol proto) { + struct dns_sd_discovery_data *d = adata->d; AvahiClient *client; AvahiHostNameResolver *resolver; int ret; @@ -315,8 +325,9 @@ static void avahi_resolve_host(struct dns_sd_discovery_data *d, goto err_free_poll; } - resolver = avahi_host_name_resolver_new(client, AVAHI_IF_UNSPEC, proto, hostname, proto, 0, - avahi_host_resolver, d); + resolver = avahi_host_name_resolver_new(client, AVAHI_IF_UNSPEC, proto, + hostname, proto, 0, + avahi_host_resolver, adata); if (!resolver) { ret = avahi_client_errno(client); IIO_ERROR("Unable to create Avahi DNS-SD browser: %s\n", @@ -333,11 +344,13 @@ static void avahi_resolve_host(struct dns_sd_discovery_data *d, avahi_simple_poll_free(d->poll); } -int dnssd_resolve_host(const char *hostname, +int dnssd_resolve_host(const struct iio_context_params *params, + const char *hostname, char *ip_addr, const int addr_len) { struct dns_sd_discovery_data *d; + struct dns_sd_cb_data adata; int ret = 0; if (!hostname || hostname[0] == '\0') @@ -352,6 +365,10 @@ int dnssd_resolve_host(const char *hostname, ret = -ENOMEM; goto err_free_data; } + + adata.params = params; + adata.d = d; + /* * The reason not to use AVAHI_PROTO_UNSPEC is that avahi sometimes resolves the host * to an ipv6 link local address which is not suitable to be used by connect. In fact, @@ -359,14 +376,14 @@ int dnssd_resolve_host(const char *hostname, * might really want to use ipv6 and have their environment correctly configured. Hence, * we try to resolve both in ipv4 and ipv6... */ - avahi_resolve_host(d, hostname, AVAHI_PROTO_INET); + avahi_resolve_host(&adata, hostname, AVAHI_PROTO_INET); #ifdef HAVE_IPV6 - avahi_resolve_host(d, hostname, AVAHI_PROTO_INET6); + avahi_resolve_host(&adata, hostname, AVAHI_PROTO_INET6); #endif if (d->resolved) { - port_knock_discovery_data(&d); - remove_dup_discovery_data(&d); + port_knock_discovery_data(params, &d); + remove_dup_discovery_data(params, &d); } else { ret = -ENXIO; goto err_mutex_destroy; @@ -383,6 +400,6 @@ int dnssd_resolve_host(const char *hostname, err_mutex_destroy: iio_mutex_destroy(d->lock); err_free_data: - dnssd_free_all_discovery_data(d); + dnssd_free_all_discovery_data(params, d); return ret; } diff --git a/dns_sd_bonjour.c b/dns_sd_bonjour.c index 18779836f..50fadc643 100644 --- a/dns_sd_bonjour.c +++ b/dns_sd_bonjour.c @@ -27,7 +27,9 @@ static void __cfnet_browser_cb(CFNetServiceBrowserRef browser, void *info) { const CFNetServiceRef netService = (CFNetServiceRef)domainOrService; - struct dns_sd_discovery_data *dd = info; + struct dns_sd_cb_data *bdata = info; + struct dns_sd_discovery_data *dd = bdata->d; + const struct iio_context_params *params = bdata->params; char address_v4[DNS_SD_ADDRESS_STR_MAX+1] = ""; char address_v6[DNS_SD_ADDRESS_STR_MAX+1] = ""; char hostname[MAXHOSTNAMELEN]; @@ -160,11 +162,13 @@ static void __cfnet_browser_cb(CFNetServiceBrowserRef browser, CFNetServiceBrowserStopSearch(browser, &anError); } -int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) +int dnssd_find_hosts(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata) { CFNetServiceClientContext clientContext = { 0 }; CFNetServiceBrowserRef serviceBrowser; struct dns_sd_discovery_data *d; + struct dns_sd_cb_data bdata; CFRunLoopRunResult runRes; CFRunLoopRef runLoop; CFStringRef type; @@ -181,18 +185,21 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) d->lock = iio_mutex_create(); if (!d->lock) { - dnssd_free_all_discovery_data(d); + dnssd_free_all_discovery_data(params, d); return -ENOMEM; } - clientContext.info = d; + bdata.d = d; + bdata.params = params; + + clientContext.info = &bdata; serviceBrowser = CFNetServiceBrowserCreate(kCFAllocatorDefault, __cfnet_browser_cb, &clientContext); if (serviceBrowser == NULL) { IIO_ERROR("DNS SD: Failed to create service browser.\n"); - dnssd_free_all_discovery_data(d); + dnssd_free_all_discovery_data(params, d); ret = -ENOMEM; goto exit; } @@ -236,8 +243,8 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) } } - port_knock_discovery_data(&d); - remove_dup_discovery_data(&d); + port_knock_discovery_data(params, &d); + remove_dup_discovery_data(params, &d); *ddata = d; } @@ -253,7 +260,8 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) return ret; } -int dnssd_resolve_host(const char *hostname, char *ip_addr, const int addr_len) +int dnssd_resolve_host(const struct iio_context_params *params, + const char *hostname, char *ip_addr, const int addr_len) { return -ENOENT; } diff --git a/dns_sd_windows.c b/dns_sd_windows.c index 08917e36e..6318bfdcd 100644 --- a/dns_sd_windows.c +++ b/dns_sd_windows.c @@ -133,7 +133,8 @@ static int query_callback(int sock, const struct sockaddr *from, size_t addrlen, size_t length, void *user_data) { - struct dns_sd_discovery_data *dd = user_data; + struct dns_sd_cb_data *cb_data = user_data; + struct dns_sd_discovery_data *dd = cb_data->d; char addrbuffer[64]; char servicebuffer[64]; char namebuffer[256]; @@ -183,13 +184,15 @@ static int query_callback(int sock, const struct sockaddr *from, size_t addrlen, return 0; } -int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) +int dnssd_find_hosts(const struct iio_context_params *params, + struct dns_sd_discovery_data **ddata) { WORD versionWanted = MAKEWORD(1, 1); WSADATA wsaData; const char service[] = "_iio._tcp.local"; size_t records, capacity = 2048; unsigned int i, isock, num_sockets; + struct dns_sd_cb_data cb_data; void *buffer; int sockets[32]; int transaction_id[32]; @@ -235,6 +238,9 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) transaction_id[isock] = ret; } + cb_data.d = *ddata; + cb_data.params = params; + /* This is a simple implementation that loops for 10 seconds or as long as we get replies * A real world implementation would probably use select, poll or similar syscall to wait * until data is available on a socket and then read it */ @@ -250,7 +256,7 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) records += mdns_query_recv(sockets[isock], buffer, capacity, - query_callback, *ddata, + query_callback, &cb_data, transaction_id[isock]); } } while (records); @@ -274,7 +280,8 @@ int dnssd_find_hosts(struct dns_sd_discovery_data **ddata) return ret; } -int dnssd_resolve_host(const char *hostname, char *ip_addr, const int addr_len) +int dnssd_resolve_host(const struct iio_context_params *params, + const char *hostname, char *ip_addr, const int addr_len) { return -ENOENT; } diff --git a/network.c b/network.c index 409a5a483..94db03bd2 100644 --- a/network.c +++ b/network.c @@ -1031,7 +1031,7 @@ struct iio_context * network_create_context(const struct iio_context_params *par char port_str[6]; uint16_t port = IIOD_PORT; - ret = dnssd_discover_host(addr_str, sizeof(addr_str), &port); + ret = dnssd_discover_host(params, addr_str, sizeof(addr_str), &port); if (ret < 0) { char buf[1024]; iio_strerror(-ret, buf, sizeof(buf)); @@ -1061,7 +1061,7 @@ struct iio_context * network_create_context(const struct iio_context_params *par IIO_DEBUG("'getaddrinfo()' failed: %s. Trying dnssd as a last resort...\n", gai_strerror(ret)); - ret = dnssd_resolve_host(host, addr_str, sizeof(addr_str)); + ret = dnssd_resolve_host(params, host, addr_str, sizeof(addr_str)); if (ret) { char buf[256];