summaryrefslogtreecommitdiff
path: root/iiod/iiod.c
diff options
context:
space:
mode:
Diffstat (limited to 'iiod/iiod.c')
-rw-r--r--iiod/iiod.c471
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;
-}