static int network_set_timeout(struct iio_context *ctx, unsigned int timeout) { int ret = set_socket_timeout(ctx->pdata->fd, timeout); if (!ret) { timeout = calculate_remote_timeout(timeout); ret = set_remote_timeout(ctx, timeout); } if (ret < 0) { char buf[1024]; iio_strerror(-ret, buf, sizeof(buf)); WARNING("Unable to set R/W timeout: %s\n", buf); } else { ctx->rw_timeout_ms = timeout; } return ret; }
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; }