From c6a9eaaf88d20057cf52bd06c891d7be9891c1de Mon Sep 17 00:00:00 2001 From: staphen Date: Tue, 8 Jun 2021 09:34:42 -0400 Subject: [PATCH] Implement sendmsg and recvmsg --- Source/platform/ctr/asio/sys/socket.c | 94 ++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/Source/platform/ctr/asio/sys/socket.c b/Source/platform/ctr/asio/sys/socket.c index 2325f6fd1..7bb578b2b 100644 --- a/Source/platform/ctr/asio/sys/socket.c +++ b/Source/platform/ctr/asio/sys/socket.c @@ -1,15 +1,105 @@ #include #include +#include #include -ssize_t recvmsg(int socket, struct msghdr *message, int flags) +ssize_t stream_recvmsg(int socket, struct msghdr *message, int flags) +{ + struct iovec *next = message->msg_iov; + int iovcount = message->msg_iovlen; + + ssize_t total = 0; + for (int i = 0; i < iovcount; ++i, ++next) { + struct iovec *iov = next; + void *base = iov->iov_base; + size_t length = iov->iov_len; + + while (length > 0) { + ssize_t bytesReceived = recv(socket, base, length, flags); + if (bytesReceived == -1) { + if (total > 0 && errno == EAGAIN) + return total; + if (total > 0 && errno == EWOULDBLOCK) + return total; + return -1; + } + base += bytesReceived; + length -= bytesReceived; + total += bytesReceived; + + if ((flags & MSG_WAITALL) == 0) + return total; + } + } + return total; +} + +ssize_t dgram_recvmsg(int socket, struct msghdr *message, int flags) { return ENOTSUP; } +ssize_t recvmsg(int socket, struct msghdr *message, int flags) +{ + int type; + socklen_t length = sizeof(int); + if (getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &length) == -1) + return -1; + + if (type == SOCK_STREAM) + return stream_recvmsg(socket, message, flags); + if (type == SOCK_DGRAM) + return dgram_recvmsg(socket, message, flags); + + errno = ENOTSOCK; + return -1; +} + +ssize_t stream_sendmsg(int socket, const struct msghdr *message, int flags) +{ + struct iovec *next = message->msg_iov; + int iovcount = message->msg_iovlen; + + ssize_t total = 0; + for (int i = 0; i < iovcount; ++i, ++next) { + struct iovec *iov = next; + void *base = iov->iov_base; + size_t length = iov->iov_len; + if (length == 0) + continue; + + ssize_t bytesSent = send(socket, base, length, flags); + if (bytesSent == -1) { + if (total > 0 && errno == EAGAIN) + return total; + if (total > 0 && errno == EWOULDBLOCK) + return total; + return -1; + } + total += bytesSent; + } + return total; +} + +ssize_t dgram_sendmsg(int socket, const struct msghdr *message, int flags) +{ + return ENOTSUP; +} + ssize_t sendmsg(int socket, const struct msghdr *message, int flags) { - return ENOTSUP; + int type; + socklen_t length = sizeof(int); + if (getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &length) == -1) + return -1; + + if (type == SOCK_STREAM) + return stream_sendmsg(socket, message, flags); + if (type == SOCK_DGRAM) + return dgram_sendmsg(socket, message, flags); + + errno = ENOTSOCK; + return -1; } int socketpair(int domain, int type, int protocol, int socket_vector[2])