Skip to content

Commit

Permalink
network: split windows/unix specific code into their own C files
Browse files Browse the repository at this point in the history
Instead of having a huge #ifdef/#else/#endif block with the same
functions defined differently on each branch, move these functions to
network-unix.c and network-windows.c, which are only compiled for their
respective platform.

Signed-off-by: Paul Cercueil <[email protected]>
  • Loading branch information
pcercuei committed Apr 13, 2021
1 parent 9da628b commit b27a75c
Show file tree
Hide file tree
Showing 6 changed files with 403 additions and 337 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,11 @@ if(WITH_NETWORK_BACKEND)
endif()

list(APPEND LIBIIO_CFILES network.c)
if (WIN32)
list(APPEND LIBIIO_CFILES network-windows.c)
else()
list(APPEND LIBIIO_CFILES network-unix.c)
endif()

find_library(AVAHI_CLIENT_LIBRARIES avahi-client)
find_library(AVAHI_COMMON_LIBRARIES avahi-common)
Expand Down
6 changes: 3 additions & 3 deletions dns_sd.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#define ENOMEDIUM ENOENT
#endif

/* Used everywhere */
#define IIOD_PORT 30431

struct addrinfo;
struct AvahiSimplePoll;
struct AvahiAddress;
Expand Down Expand Up @@ -78,7 +81,4 @@ void remove_dup_discovery_data(struct dns_sd_discovery_data **ddata);
/* port knocks */
void port_knock_discovery_data(struct dns_sd_discovery_data **ddata);

/* Used everywhere */
#define IIOD_PORT 30431

#endif /* __IIO_DNS_SD_H */
209 changes: 209 additions & 0 deletions network-unix.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libiio - Library for interfacing industrial I/O (IIO) devices
*
* Copyright (C) 2021 Analog Devices, Inc.
* Author: Paul Cercueil
*/

#include "debug.h"
#include "iio-private.h"
#include "network.h"

#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <poll.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

int set_blocking_mode(int fd, bool blocking)
{
int ret = fcntl(fd, F_GETFL, 0);
if (ret < 0)
return -errno;

if (blocking)
ret &= ~O_NONBLOCK;
else
ret |= O_NONBLOCK;

ret = fcntl(fd, F_SETFL, ret);
return ret < 0 ? -errno : 0;
}

#if defined(WITH_NETWORK_EVENTFD)

#include <sys/eventfd.h>

int create_cancel_fd(struct iio_network_io_context *io_ctx)
{
io_ctx->cancel_fd[0] = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
if (io_ctx->cancel_fd[0] < 0)
return -errno;
return 0;
}

void cleanup_cancel(struct iio_network_io_context *io_ctx)
{
close(io_ctx->cancel_fd[0]);
}

#define CANCEL_WR_FD 0

#else

int create_cancel_fd(struct iio_network_io_context *io_ctx)
{
int ret;

#ifdef HAS_PIPE2
ret = pipe2(io_ctx->cancel_fd, O_CLOEXEC | O_NONBLOCK);
if (ret < 0 && errno != ENOSYS) /* If ENOSYS try pipe() */
return -errno;
#endif
ret = pipe(io_ctx->cancel_fd);
if (ret < 0)
return -errno;
ret = set_blocking_mode(io_ctx->cancel_fd[0], false);
if (ret < 0)
goto err_close;
ret = set_blocking_mode(io_ctx->cancel_fd[1], false);
if (ret < 0)
goto err_close;

return 0;
err_close:
close(io_ctx->cancel_fd[0]);
close(io_ctx->cancel_fd[1]);
return ret;
}

void cleanup_cancel(struct iio_network_io_context *io_ctx)
{
close(io_ctx->cancel_fd[0]);
close(io_ctx->cancel_fd[1]);
}

#define CANCEL_WR_FD 1

#endif

int setup_cancel(struct iio_network_io_context *io_ctx)
{
int ret;

ret = set_blocking_mode(io_ctx->fd, false);
if (ret)
return ret;

return create_cancel_fd(io_ctx);
}

void do_cancel(struct iio_network_io_context *io_ctx)
{
uint64_t event = 1;
int ret;

ret = write(io_ctx->cancel_fd[CANCEL_WR_FD], &event, sizeof(event));
if (ret == -1) {
/* If this happens something went very seriously wrong */
char err_str[1024];
iio_strerror(errno, err_str, sizeof(err_str));
IIO_ERROR("Unable to signal cancellation event: %s\n", err_str);
}
}

int wait_cancellable(struct iio_network_io_context *io_ctx, bool read)
{
struct pollfd pfd[2];
int ret;

if (!io_ctx->cancellable)
return 0;

memset(pfd, 0, sizeof(pfd));

pfd[0].fd = io_ctx->fd;
if (read)
pfd[0].events = POLLIN;
else
pfd[0].events = POLLOUT;
pfd[1].fd = io_ctx->cancel_fd[0];
pfd[1].events = POLLIN;

do {
int timeout_ms;

if (io_ctx->timeout_ms > 0)
timeout_ms = (int) io_ctx->timeout_ms;
else
timeout_ms = -1;

do {
ret = poll(pfd, 2, timeout_ms);
} while (ret == -1 && errno == EINTR);

if (ret == -1)
return -errno;
if (!ret)
return -EPIPE;

if (pfd[1].revents & POLLIN)
return -EBADF;
} while (!(pfd[0].revents & (pfd[0].events | POLLERR | POLLHUP)));

return 0;
}

int network_get_error(void)
{
return -errno;
}

bool network_should_retry(int err)
{
return err == -EAGAIN;
}

bool network_is_interrupted(int err)
{
return err == -EINTR;
}

bool network_connect_in_progress(int err)
{
return err == -EINPROGRESS;
}


/* Use it if available */
#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC 0
#endif

int do_create_socket(const struct addrinfo *addrinfo)
{
int fd;

fd = socket(addrinfo->ai_family, addrinfo->ai_socktype | SOCK_CLOEXEC, 0);
if (fd < 0)
return -errno;

return fd;
}

int set_socket_timeout(int fd, unsigned int timeout)
{
struct timeval tv;

tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
&tv, sizeof(tv)) < 0)
return -errno;
else
return 0;
}
131 changes: 131 additions & 0 deletions network-windows.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libiio - Library for interfacing industrial I/O (IIO) devices
*
* Copyright (C) 2021 Analog Devices, Inc.
* Author: Paul Cercueil
*/

#include "network.h"

#include <ws2tcpip.h>
#define close(s) closesocket(s)
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN (MAX_COMPUTERNAME_LENGTH+1)
#endif /* MAXHOSTNAMELEN */

int set_blocking_mode(int s, bool blocking)
{
unsigned long nonblock;
int ret;

nonblock = blocking ? 0 : 1;

ret = ioctlsocket(s, FIONBIO, &nonblock);
if (ret == SOCKET_ERROR) {
ret = -WSAGetLastError();
return ret;
}

return 0;
}

int setup_cancel(struct iio_network_io_context *io_ctx)
{
io_ctx->events[0] = WSACreateEvent();
if (io_ctx->events[0] == WSA_INVALID_EVENT)
return -ENOMEM; /* Pretty much the only error that can happen */

io_ctx->events[1] = WSACreateEvent();
if (io_ctx->events[1] == WSA_INVALID_EVENT) {
WSACloseEvent(io_ctx->events[0]);
return -ENOMEM;
}

return 0;
}

void cleanup_cancel(struct iio_network_io_context *io_ctx)
{
WSACloseEvent(io_ctx->events[0]);
WSACloseEvent(io_ctx->events[1]);
}

void do_cancel(struct iio_network_io_context *io_ctx)
{
WSASetEvent(io_ctx->events[1]);
}

int wait_cancellable(struct iio_network_io_context *io_ctx, bool read)
{
long wsa_events = FD_CLOSE;
DWORD ret;

if (!io_ctx->cancellable)
return 0;

if (read)
wsa_events |= FD_READ;
else
wsa_events |= FD_WRITE;

WSAEventSelect(io_ctx->fd, NULL, 0);
WSAResetEvent(io_ctx->events[0]);
WSAEventSelect(io_ctx->fd, io_ctx->events[0], wsa_events);

ret = WSAWaitForMultipleEvents(2, io_ctx->events, FALSE,
WSA_INFINITE, FALSE);

if (ret == WSA_WAIT_EVENT_0 + 1)
return -EBADF;

return 0;
}

int network_get_error(void)
{
return -WSAGetLastError();
}

bool network_should_retry(int err)
{
return err == -WSAEWOULDBLOCK || err == -WSAETIMEDOUT;
}

bool network_is_interrupted(int err)
{
return false;
}

bool network_connect_in_progress(int err)
{
return err == -WSAEWOULDBLOCK;
}

/* Use it if available */
#ifndef WSA_FLAG_NO_HANDLE_INHERIT
#define WSA_FLAG_NO_HANDLE_INHERIT 0
#endif

int do_create_socket(const struct addrinfo *addrinfo)
{
SOCKET s;

s = WSASocketW(addrinfo->ai_family, addrinfo->ai_socktype, 0, NULL, 0,
WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
if (s == INVALID_SOCKET)
return -WSAGetLastError();

return (int) s;
}

int set_socket_timeout(int fd, unsigned int timeout)
{
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
(const char *) &timeout, sizeof(timeout)) < 0 ||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
(const char *) &timeout, sizeof(timeout)) < 0)
return -WSAGetLastError();
else
return 0;
}
Loading

0 comments on commit b27a75c

Please sign in to comment.