struct iio_context * network_create_context(const char *host) { struct addrinfo hints, *res; struct iio_context *ctx; struct iio_context_pdata *pdata; size_t i, len; int fd, ret; char *description; #ifdef _WIN32 WSADATA wsaData; ret = WSAStartup(MAKEWORD(2, 0), &wsaData); if (ret < 0) { ERROR("WSAStartup failed with error %i\n", ret); errno = -ret; return NULL; } #endif memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; #ifdef HAVE_AVAHI if (!host) { char addr_str[AVAHI_ADDRESS_STR_MAX]; char port_str[6]; AvahiAddress address; uint16_t port = IIOD_PORT; memset(&address, 0, sizeof(address)); ret = discover_host(&address, &port); if (ret < 0) { DEBUG("Unable to find host: %s\n", strerror(-ret)); errno = -ret; return NULL; } avahi_address_snprint(addr_str, sizeof(addr_str), &address); snprintf(port_str, sizeof(port_str), "%hu", port); ret = getaddrinfo(addr_str, port_str, &hints, &res); } else #endif { ret = getaddrinfo(host, IIOD_PORT_STR, &hints, &res); } if (ret) { ERROR("Unable to find host: %s\n", gai_strerror(ret)); #ifndef _WIN32 if (ret != EAI_SYSTEM) errno = ret; #endif return NULL; } fd = create_socket(res); if (fd < 0) { errno = fd; goto err_free_addrinfo; } pdata = calloc(1, sizeof(*pdata)); if (!pdata) { errno = ENOMEM; goto err_close_socket; } pdata->fd = fd; pdata->addrinfo = res; pdata->lock = iio_mutex_create(); if (!pdata->lock) { errno = ENOMEM; goto err_free_pdata; } pdata->iiod_client = iiod_client_new(pdata, pdata->lock, &network_iiod_client_ops); if (!pdata->iiod_client) goto err_destroy_mutex; DEBUG("Creating context...\n"); ctx = iiod_client_create_context(pdata->iiod_client, fd); if (!ctx) goto err_destroy_iiod_client; /* Override the name and low-level functions of the XML context * with those corresponding to the network context */ ctx->name = "network"; ctx->ops = &network_ops; ctx->pdata = pdata; #ifdef HAVE_IPV6 len = INET6_ADDRSTRLEN + IF_NAMESIZE + 2; #else len = INET_ADDRSTRLEN + 1; #endif description = malloc(len); if (!description) { ret = -ENOMEM; goto err_network_shutdown; } description[0] = '\0'; #ifdef HAVE_IPV6 if (res->ai_family == AF_INET6) { struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr; char *ptr; inet_ntop(AF_INET6, &in->sin6_addr, description, INET6_ADDRSTRLEN); ptr = if_indextoname(in->sin6_scope_id, description + strlen(description) + 1); if (!ptr) { ret = -errno; ERROR("Unable to lookup interface of IPv6 address\n"); goto err_free_description; } *(ptr - 1) = '%'; } #endif if (res->ai_family == AF_INET) { struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr; #if (!_WIN32 || _WIN32_WINNT >= 0x600) inet_ntop(AF_INET, &in->sin_addr, description, INET_ADDRSTRLEN); #else char *tmp = inet_ntoa(in->sin_addr); strncpy(description, tmp, len); #endif } for (i = 0; i < ctx->nb_devices; i++) { struct iio_device *dev = ctx->devices[i]; dev->pdata = calloc(1, sizeof(*dev->pdata)); if (!dev->pdata) { ret = -ENOMEM; goto err_free_description; } dev->pdata->fd = -1; #ifdef WITH_NETWORK_GET_BUFFER dev->pdata->memfd = -1; #endif dev->pdata->lock = iio_mutex_create(); if (!dev->pdata->lock) { ret = -ENOMEM; goto err_free_description; } } ret = iio_context_init(ctx); if (ret < 0) goto err_free_description; if (ctx->description) { size_t desc_len = strlen(description); size_t new_size = desc_len + strlen(ctx->description) + 2; char *ptr, *new_description = realloc(description, new_size); if (!new_description) { ret = -ENOMEM; goto err_free_description; } ptr = strrchr(new_description, '\0'); snprintf(ptr, new_size - desc_len, " %s", ctx->description); free(ctx->description); ctx->description = new_description; } else { ctx->description = description; } iiod_client_set_timeout(pdata->iiod_client, fd, calculate_remote_timeout(DEFAULT_TIMEOUT_MS)); return ctx; err_free_description: free(description); err_network_shutdown: iio_context_destroy(ctx); errno = -ret; return NULL; err_destroy_iiod_client: iiod_client_destroy(pdata->iiod_client); err_destroy_mutex: iio_mutex_destroy(pdata->lock); err_free_pdata: free(pdata); err_close_socket: close(fd); err_free_addrinfo: freeaddrinfo(res); return NULL; }
static struct iio_context * iio_create_xml_context_helper(xmlDoc *doc) { unsigned int i; xmlNode *root, *n; xmlAttr *attr; int err = ENOMEM; struct iio_context *ctx = calloc(1, sizeof(*ctx)); if (!ctx) goto err_set_errno; ctx->name = "xml"; ctx->ops = &xml_ops; root = xmlDocGetRootElement(doc); if (strcmp((char *) root->name, "context")) { ERROR("Unrecognized XML file\n"); err = EINVAL; goto err_free_ctx; } for (attr = root->properties; attr; attr = attr->next) { if (!strcmp((char *) attr->name, "description")) ctx->description = _strdup( (char *) attr->children->content); else if (strcmp((char *) attr->name, "name")) WARNING("Unknown parameter \'%s\' in <context>\n", (char *) attr->children->content); } for (n = root->children; n; n = n->next) { struct iio_device **devs, *dev; if (strcmp((char *) n->name, "device")) { if (strcmp((char *) n->name, "text")) WARNING("Unknown children \'%s\' in " "<context>\n", n->name); continue; } dev = create_device(ctx, n); if (!dev) { ERROR("Unable to create device\n"); goto err_free_devices; } devs = realloc(ctx->devices, (1 + ctx->nb_devices) * sizeof(struct iio_device *)); if (!devs) { ERROR("Unable to allocate memory\n"); free(dev); goto err_free_devices; } devs[ctx->nb_devices++] = dev; ctx->devices = devs; } err = iio_context_init(ctx); if (err) goto err_free_devices; return ctx; err_free_devices: for (i = 0; i < ctx->nb_devices; i++) free_device(ctx->devices[i]); if (ctx->nb_devices) free(ctx->devices); err_free_ctx: free(ctx); err_set_errno: errno = err; return NULL; }