diff options
Diffstat (limited to 'iiod/iiod.c')
-rw-r--r-- | iiod/iiod.c | 471 |
1 files changed, 0 insertions, 471 deletions
diff --git a/iiod/iiod.c b/iiod/iiod.c deleted file mode 100644 index 9d38426..0000000 --- a/iiod/iiod.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * libiio - Library for interfacing industrial I/O (IIO) devices - * - * Copyright (C) 2014 Analog Devices, Inc. - * Author: Paul Cercueil <paul.cercueil@analog.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * */ - -#include "../debug.h" -#include "../iio.h" -#include "../iio-config.h" -#include "ops.h" -#include "thread-pool.h" - -#include <arpa/inet.h> -#include <errno.h> -#include <fcntl.h> -#include <getopt.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <poll.h> -#include <pthread.h> -#include <signal.h> -#include <stdbool.h> -#include <string.h> -#include <sys/eventfd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <unistd.h> - -#ifdef HAVE_AVAHI -#include <avahi-common/simple-watch.h> -#include <avahi-client/client.h> -#include <avahi-client/publish.h> -#endif - -#define MY_NAME "iiod" - -#define IIOD_PORT 30431 - -struct client_data { - int fd; - bool debug; - struct iio_context *ctx; -}; - -bool server_demux; - -struct thread_pool *main_thread_pool; - - -static struct sockaddr_in sockaddr = { - .sin_family = AF_INET, -#if __BYTE_ORDER == __LITTLE_ENDIAN - .sin_addr.s_addr = __bswap_constant_32(INADDR_ANY), - .sin_port = __bswap_constant_16(IIOD_PORT), -#else - .sin_addr.s_addr = INADDR_ANY, - .sin_port = IIOD_PORT, -#endif -}; - -#ifdef HAVE_IPV6 -static struct sockaddr_in6 sockaddr6 = { - .sin6_family = AF_INET6, - .sin6_addr = IN6ADDR_ANY_INIT, -#if __BYTE_ORDER == __LITTLE_ENDIAN - .sin6_port = __bswap_constant_16(IIOD_PORT), -#else - .sin6_port = IIOD_PORT, -#endif -}; -#endif /* HAVE_IPV6 */ - -static const struct option options[] = { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"debug", no_argument, 0, 'd'}, - {"demux", no_argument, 0, 'D'}, - {"interactive", no_argument, 0, 'i'}, - {"aio", no_argument, 0, 'a'}, - {"ffs", required_argument, 0, 'F'}, - {"nb-pipes", required_argument, 0, 'n'}, - {0, 0, 0, 0}, -}; - -static const char *options_descriptions[] = { - "Show this help and quit.", - "Display the version of this program.", - "Use alternative (incompatible) debug interface.", - "Demux channels directly on the server.", - "Run " MY_NAME " in the controlling terminal.", - "Use asynchronous I/O.", - "Use the given FunctionFS mountpoint to serve over USB", - "Specify the number of USB pipes (ep couples) to use", -}; - -#ifdef HAVE_AVAHI -static AvahiSimplePoll *avahi_poll; -static AvahiClient *avahi_client; - -static void __avahi_group_cb(AvahiEntryGroup *group, - AvahiEntryGroupState state, void *d) -{ -} - -static void __avahi_client_cb(AvahiClient *client, - AvahiClientState state, void *d) -{ - AvahiEntryGroup *group; - - if (state != AVAHI_CLIENT_S_RUNNING) - return; - - group = avahi_entry_group_new(client, __avahi_group_cb, NULL); - - if (group && !avahi_entry_group_add_service(group, - AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, - 0, "iio", "_iio._tcp", NULL, NULL, IIOD_PORT, NULL)) { - avahi_entry_group_commit(group); - INFO("Registered to ZeroConf server %s\n", - avahi_client_get_version_string(client)); - } - - /* NOTE: group is freed by avahi_client_free */ -} - -static int start_avahi(void) -{ - int ret = ENOMEM; - - avahi_poll = avahi_simple_poll_new(); - if (!avahi_poll) - return -ENOMEM; - - avahi_client = avahi_client_new(avahi_simple_poll_get(avahi_poll), - 0, __avahi_client_cb, NULL, &ret); - if (!avahi_client) { - avahi_simple_poll_free(avahi_poll); - return -ret; - } - - return 0; -} - -static void stop_avahi(void) -{ - avahi_client_free(avahi_client); - avahi_simple_poll_free(avahi_poll); -} -#endif /* HAVE_AVAHI */ - - -static void usage(void) -{ - unsigned int i; - - printf("Usage:\n\t" MY_NAME " [OPTIONS ...]\n\nOptions:\n"); - for (i = 0; options[i].name; i++) - printf("\t-%c, --%s\n\t\t\t%s\n", - options[i].val, options[i].name, - options_descriptions[i]); -} - -static void client_thd(struct thread_pool *pool, void *d) -{ - struct client_data *cdata = d; - - interpreter(cdata->ctx, cdata->fd, cdata->fd, cdata->debug, - true, false, pool); - - INFO("Client exited\n"); - close(cdata->fd); - free(cdata); -} - -static void set_handler(int signal, void (*handler)(int)) -{ - struct sigaction sig; - sigaction(signal, NULL, &sig); - sig.sa_handler = handler; - sigaction(signal, &sig, NULL); -} - -static void sig_handler(int sig) -{ - thread_pool_stop(main_thread_pool); -} - -static int main_interactive(struct iio_context *ctx, bool verbose, bool use_aio) -{ - int flags; - - if (!use_aio) { - flags = fcntl(STDIN_FILENO, F_GETFL); - fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); - flags = fcntl(STDOUT_FILENO, F_GETFL); - fcntl(STDOUT_FILENO, F_SETFL, flags | O_NONBLOCK); - } - - interpreter(ctx, STDIN_FILENO, STDOUT_FILENO, verbose, - false, use_aio, main_thread_pool); - return EXIT_SUCCESS; -} - -static int main_server(struct iio_context *ctx, bool debug) -{ - int ret, fd = -1, yes = 1, - keepalive_time = 10, - keepalive_intvl = 10, - keepalive_probes = 6; - struct pollfd pfd[2]; - char err_str[1024]; - bool ipv6; -#ifdef HAVE_AVAHI - bool avahi_started; -#endif - - INFO("Starting IIO Daemon version %u.%u\n", - LIBIIO_VERSION_MAJOR, LIBIIO_VERSION_MINOR); - -#ifdef HAVE_IPV6 - fd = socket(AF_INET6, SOCK_STREAM | SOCK_NONBLOCK, 0); -#endif - ipv6 = (fd >= 0); - if (!ipv6) - fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); - if (fd < 0) { - iio_strerror(errno, err_str, sizeof(err_str)); - ERROR("Unable to create socket: %s\n", err_str); - return EXIT_FAILURE; - } - - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - -#ifdef HAVE_IPV6 - if (ipv6) - ret = bind(fd, (struct sockaddr *) &sockaddr6, - sizeof(sockaddr6)); -#endif - if (!ipv6) - ret = bind(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)); - if (ret < 0) { - iio_strerror(errno, err_str, sizeof(err_str)); - ERROR("Bind failed: %s\n", err_str); - goto err_close_socket; - } - - if (ipv6) - INFO("IPv6 support enabled\n"); - - if (listen(fd, 16) < 0) { - iio_strerror(errno, err_str, sizeof(err_str)); - ERROR("Unable to mark as passive socket: %s\n", err_str); - goto err_close_socket; - } - -#ifdef HAVE_AVAHI - avahi_started = !start_avahi(); -#endif - - pfd[0].fd = fd; - pfd[0].events = POLLIN; - pfd[0].revents = 0; - pfd[1].fd = thread_pool_get_poll_fd(main_thread_pool); - pfd[1].events = POLLIN; - pfd[1].revents = 0; - - while (true) { - struct client_data *cdata; - struct sockaddr_in caddr; - socklen_t addr_len = sizeof(caddr); - int new; - - poll_nointr(pfd, 2); - - if (pfd[1].revents & POLLIN) /* STOP event */ - break; - - new = accept4(fd, (struct sockaddr *) &caddr, &addr_len, - SOCK_NONBLOCK); - if (new == -1) { - if (errno == EAGAIN || errno == EINTR) - continue; - iio_strerror(errno, err_str, sizeof(err_str)); - ERROR("Failed to create connection socket: %s\n", - err_str); - continue; - } - - cdata = malloc(sizeof(*cdata)); - if (!cdata) { - WARNING("Unable to allocate memory for client\n"); - close(new); - continue; - } - - /* Configure the socket to send keep-alive packets every 10s, - * and disconnect the client if no reply was received for one - * minute. */ - setsockopt(new, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)); - setsockopt(new, IPPROTO_TCP, TCP_KEEPCNT, &keepalive_probes, - sizeof(keepalive_probes)); - setsockopt(new, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive_time, - sizeof(keepalive_time)); - setsockopt(new, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive_intvl, - sizeof(keepalive_intvl)); - setsockopt(new, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); - - cdata->fd = new; - cdata->ctx = ctx; - cdata->debug = debug; - - INFO("New client connected from %s\n", - inet_ntoa(caddr.sin_addr)); - - ret = thread_pool_add_thread(main_thread_pool, client_thd, cdata, "net_client_thd"); - if (ret) { - iio_strerror(ret, err_str, sizeof(err_str)); - ERROR("Failed to create new client thread: %s\n", - err_str); - close(new); - free(cdata); - } - } - - DEBUG("Cleaning up\n"); -#ifdef HAVE_AVAHI - if (avahi_started) - stop_avahi(); -#endif - close(fd); - return EXIT_SUCCESS; - -err_close_socket: - close(fd); - return EXIT_FAILURE; -} - -int main(int argc, char **argv) -{ - bool debug = false, interactive = false, use_aio = false; -#ifdef WITH_IIOD_USBD - long nb_pipes = 3; - char *end; -#endif - struct iio_context *ctx; - int c, option_index = 0; - char *ffs_mountpoint = NULL; - char err_str[1024]; - int ret; - - while ((c = getopt_long(argc, argv, "+hVdDiaF:n:", - options, &option_index)) != -1) { - switch (c) { - case 'd': - debug = true; - break; - case 'D': - server_demux = true; - break; - case 'i': - interactive = true; - break; - case 'a': -#ifdef WITH_AIO - use_aio = true; - break; -#else - ERROR("IIOD was not compiled with AIO support.\n"); - return EXIT_FAILURE; -#endif - case 'F': -#ifdef WITH_IIOD_USBD - ffs_mountpoint = optarg; - break; -#else - ERROR("IIOD was not compiled with USB support.\n"); - return EXIT_FAILURE; -#endif - case 'n': -#ifdef WITH_IIOD_USBD - nb_pipes = strtol(optarg, &end, 10); - if (optarg == end || nb_pipes < 1) { - ERROR("--nb-pipes: Invalid parameter\n"); - return EXIT_FAILURE; - } - break; -#else - ERROR("IIOD was not compiled with USB support.\n"); - return EXIT_FAILURE; -#endif - case 'h': - usage(); - return EXIT_SUCCESS; - case 'V': - printf("%u.%u\n", LIBIIO_VERSION_MAJOR, - LIBIIO_VERSION_MINOR); - return EXIT_SUCCESS; - case '?': - return EXIT_FAILURE; - } - } - - ctx = iio_create_local_context(); - if (!ctx) { - iio_strerror(errno, err_str, sizeof(err_str)); - ERROR("Unable to create local context: %s\n", err_str); - return EXIT_FAILURE; - } - - main_thread_pool = thread_pool_new(); - if (!main_thread_pool) { - iio_strerror(errno, err_str, sizeof(err_str)); - ERROR("Unable to create thread pool: %s\n", err_str); - ret = EXIT_FAILURE; - goto out_destroy_context; - } - - set_handler(SIGHUP, sig_handler); - set_handler(SIGPIPE, sig_handler); - set_handler(SIGINT, sig_handler); - set_handler(SIGTERM, sig_handler); - - if (ffs_mountpoint) { -#ifdef WITH_IIOD_USBD - /* We pass use_aio == true directly, this is ensured to be true - * by the CMake script. */ - ret = start_usb_daemon(ctx, ffs_mountpoint, - debug, true, (unsigned int) nb_pipes, - main_thread_pool); - if (ret) { - iio_strerror(-ret, err_str, sizeof(err_str)); - ERROR("Unable to start USB daemon: %s\n", err_str); - ret = EXIT_FAILURE; - goto out_destroy_thread_pool; - } -#endif - } - - if (interactive) - ret = main_interactive(ctx, debug, use_aio); - else - ret = main_server(ctx, debug); - - /* - * In case we got here through an error in the main thread make sure all - * the worker threads are signaled to shutdown. - */ - -#ifdef WITH_IIOD_USBD -out_destroy_thread_pool: -#endif - thread_pool_stop_and_wait(main_thread_pool); - thread_pool_destroy(main_thread_pool); - -out_destroy_context: - iio_context_destroy(ctx); - - return ret; -} |