1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:37:35 +00:00

Kernel+LibC+UserspaceEmulator: Mostly add recvmsg(), sendmsg()

The implementation only supports a single iovec for now.
Some might say having more than one iovec is the main point of
recvmsg() and sendmsg(), but I'm interested in the control message
bits.
This commit is contained in:
Nico Weber 2020-09-16 11:45:00 -04:00 committed by Andreas Kling
parent 19f2203b53
commit b36a2d6686
9 changed files with 158 additions and 79 deletions

View file

@ -28,7 +28,9 @@
#include <Kernel/API/Syscall.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/uio.h>
extern "C" {
@ -68,11 +70,17 @@ int shutdown(int sockfd, int how)
__RETURN_WITH_ERRNO(rc, rc, -1);
}
ssize_t sendmsg(int sockfd, const struct msghdr* msg, int flags)
{
int rc = syscall(SC_sendmsg, sockfd, msg, flags);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
ssize_t sendto(int sockfd, const void* data, size_t data_length, int flags, const struct sockaddr* addr, socklen_t addr_length)
{
Syscall::SC_sendto_params params { sockfd, { data, data_length }, flags, addr, addr_length };
int rc = syscall(SC_sendto, &params);
__RETURN_WITH_ERRNO(rc, rc, -1);
iovec iov = { const_cast<void*>(data), data_length };
msghdr msg = { const_cast<struct sockaddr*>(addr), addr_length, &iov, 1, nullptr, 0, 0 };
return sendmsg(sockfd, &msg, flags);
}
ssize_t send(int sockfd, const void* data, size_t data_length, int flags)
@ -80,11 +88,28 @@ ssize_t send(int sockfd, const void* data, size_t data_length, int flags)
return sendto(sockfd, data, data_length, flags, nullptr, 0);
}
ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags)
{
int rc = syscall(SC_recvmsg, sockfd, msg, flags);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
ssize_t recvfrom(int sockfd, void* buffer, size_t buffer_length, int flags, struct sockaddr* addr, socklen_t* addr_length)
{
Syscall::SC_recvfrom_params params { sockfd, { buffer, buffer_length }, flags, addr, addr_length };
int rc = syscall(SC_recvfrom, &params);
__RETURN_WITH_ERRNO(rc, rc, -1);
if (!addr_length && addr) {
errno = EINVAL;
return -1;
}
sockaddr_storage internal_addr;
iovec iov = { buffer, buffer_length };
msghdr msg = { addr ? &internal_addr : nullptr, addr ? sizeof(internal_addr) : 0, &iov, 1, nullptr, 0, 0 };
ssize_t rc = recvmsg(sockfd, &msg, flags);
if (rc >= 0 && addr) {
memcpy(addr, &internal_addr, min(*addr_length, msg.msg_namelen));
*addr_length = msg.msg_namelen;
}
return rc;
}
ssize_t recv(int sockfd, void* buffer, size_t buffer_length, int flags)