Commit e72c9ec9 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

input: add vlc_io_{send,recv,sendto,recvfrom,sendmsg,recvmsg} helpers

parent 064faae0
...@@ -26,9 +26,16 @@ ...@@ -26,9 +26,16 @@
#ifndef VLC_INTERRUPT_H #ifndef VLC_INTERRUPT_H
# define VLC_INTERRUPT_H 1 # define VLC_INTERRUPT_H 1
# include <vlc_threads.h> # include <vlc_threads.h>
# ifndef _WIN32
# include <sys/socket.h> /* socklen_t */
# else
# include <ws2tcpip.h>
# endif
struct pollfd; struct pollfd;
struct iovec; struct iovec;
struct sockaddr;
struct msghdr;
/** /**
* @defgroup interrupt Interruptible sleep * @defgroup interrupt Interruptible sleep
...@@ -77,6 +84,25 @@ VLC_API ssize_t vlc_writev_i11e(int fd, const struct iovec *, int); ...@@ -77,6 +84,25 @@ VLC_API ssize_t vlc_writev_i11e(int fd, const struct iovec *, int);
VLC_API ssize_t vlc_read_i11e(int fd, void *, size_t); VLC_API ssize_t vlc_read_i11e(int fd, void *, size_t);
VLC_API ssize_t vlc_write_i11e(int fd, const void *, size_t); VLC_API ssize_t vlc_write_i11e(int fd, const void *, size_t);
VLC_API ssize_t vlc_recvmsg_i11e(int fd, struct msghdr *, int flags);
VLC_API ssize_t vlc_sendmsg_i11e(int fd, const struct msghdr *, int flags);
VLC_API ssize_t vlc_recvfrom_i11e(int fd, void *, size_t, int flags,
struct sockaddr *, socklen_t *);
VLC_API ssize_t vlc_sendto_i11e(int fd, const void *, size_t, int flags,
const struct sockaddr *, socklen_t);
static inline ssize_t vlc_recv_i11e(int fd, void *buf, size_t len, int flags)
{
return vlc_recvfrom_i11e(fd, buf, len, flags, NULL, NULL);
}
static inline
ssize_t vlc_send_i11e(int fd, const void *buf, size_t len, int flags)
{
return vlc_sendto_i11e(fd, buf, len, flags, NULL, 0);
}
/** /**
* @} * @}
* @defgroup interrupt_context Interrupt context signaling and manipulation * @defgroup interrupt_context Interrupt context signaling and manipulation
......
...@@ -544,6 +544,10 @@ vlc_read_i11e ...@@ -544,6 +544,10 @@ vlc_read_i11e
vlc_readv_i11e vlc_readv_i11e
vlc_write_i11e vlc_write_i11e
vlc_writev_i11e vlc_writev_i11e
vlc_recvmsg_i11e
vlc_recvfrom_i11e
vlc_sendmsg_i11e
vlc_sendto_i11e
vlc_sem_wait_i11e vlc_sem_wait_i11e
vlc_interrupt_create vlc_interrupt_create
vlc_interrupt_destroy vlc_interrupt_destroy
......
...@@ -362,6 +362,8 @@ int vlc_poll_i11e(struct pollfd *fds, unsigned nfds, int timeout) ...@@ -362,6 +362,8 @@ int vlc_poll_i11e(struct pollfd *fds, unsigned nfds, int timeout)
# include <fcntl.h> # include <fcntl.h>
# include <sys/uio.h> # include <sys/uio.h>
# include <sys/socket.h>
/* There are currently no ways to atomically force a non-blocking read or write /* There are currently no ways to atomically force a non-blocking read or write
* operations. Even for sockets, the MSG_DONTWAIT flag is non-standard. * operations. Even for sockets, the MSG_DONTWAIT flag is non-standard.
...@@ -429,6 +431,64 @@ ssize_t vlc_write_i11e(int fd, const void *buf, size_t count) ...@@ -429,6 +431,64 @@ ssize_t vlc_write_i11e(int fd, const void *buf, size_t count)
return writev(fd, &iov, 1); return writev(fd, &iov, 1);
} }
ssize_t vlc_recvmsg_i11e(int fd, struct msghdr *msg, int flags)
{
struct pollfd ufd;
ufd.fd = fd;
ufd.events = POLLIN;
if (vlc_poll_i11e(&ufd, 1, -1) < 0)
return -1;
/* NOTE: MSG_OOB and MSG_PEEK should work fine here.
* MSG_WAITALL is not supported at this point. */
return recvmsg(fd, msg, flags);
}
ssize_t vlc_recvfrom_i11e(int fd, void *buf, size_t len, int flags,
struct sockaddr *addr, socklen_t *addrlen)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
struct msghdr msg = {
.msg_name = addr,
.msg_namelen = (addrlen != NULL) ? *addrlen : 0,
.msg_iov = &iov,
.msg_iovlen = 1,
};
ssize_t ret = vlc_recvmsg_i11e(fd, &msg, flags);
if (ret >= 0 && addrlen != NULL)
*addrlen = msg.msg_namelen;
return ret;
}
ssize_t vlc_sendmsg_i11e(int fd, const struct msghdr *msg, int flags)
{
struct pollfd ufd;
ufd.fd = fd;
ufd.events = POLLOUT;
if (vlc_poll_i11e(&ufd, 1, -1) < 0)
return -1;
/* NOTE: MSG_EOR, MSG_OOB and MSG_NOSIGNAL should all work fine here. */
return sendmsg(fd, msg, flags);
}
ssize_t vlc_sendto_i11e(int fd, const void *buf, size_t len, int flags,
const struct sockaddr *addr, socklen_t addrlen)
{
struct iovec iov = { .iov_base = (void *)buf, .iov_len = len };
struct msghdr msg = {
.msg_name = (struct sockaddr *)addr,
.msg_namelen = addrlen,
.msg_iov = &iov,
.msg_iovlen = 1,
};
return vlc_sendmsg_i11e(fd, &msg, flags);
}
#else /* _WIN32 */ #else /* _WIN32 */
static void CALLBACK vlc_poll_i11e_wake_self(ULONG_PTR data) static void CALLBACK vlc_poll_i11e_wake_self(ULONG_PTR data)
...@@ -514,4 +574,50 @@ ssize_t vlc_write_i11e(int fd, const void *buf, size_t count) ...@@ -514,4 +574,50 @@ ssize_t vlc_write_i11e(int fd, const void *buf, size_t count)
return write(fd, buf, count); return write(fd, buf, count);
} }
ssize_t vlc_recvmsg_i11e(int fd, struct msghdr *msg, int flags)
{
(void) fd; (void) msg; (void) flags;
vlc_assert_unreachable();
}
ssize_t vlc_recvfrom_i11e(int fd, void *buf, size_t len, int flags,
struct sockaddr *addr, socklen_t *addrlen)
{
struct pollfd ufd;
ufd.fd = fd;
ufd.events = POLLIN;
if (vlc_poll_i11e(&ufd, 1, -1) < 0)
return -1;
ssize_t ret = recvfrom(fd, buf, len, flags, addr, addrlen);
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
errno = EAGAIN;
return ret;
}
ssize_t vlc_sendmsg_i11e(int fd, const struct msghdr *msg, int flags)
{
(void) fd; (void) msg; (void) flags;
vlc_assert_unreachable();
}
ssize_t vlc_sendto_i11e(int fd, const void *buf, size_t len, int flags,
const struct sockaddr *addr, socklen_t addrlen)
{
struct pollfd ufd;
ufd.fd = fd;
ufd.events = POLLOUT;
if (vlc_poll_i11e(&ufd, 1, -1) < 0)
return -1;
ssize_t ret = sendto(fd, buf, len, flags, addr, addrlen);
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
errno = EAGAIN;
return ret;
}
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment