-
Notifications
You must be signed in to change notification settings - Fork 320
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
network: split windows/unix specific code into their own C files
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
Showing
6 changed files
with
403 additions
and
337 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
Oops, something went wrong.