summaryrefslogtreecommitdiffstats
path: root/libc-bottom-half/cloudlibc/src/libc/sys/socket
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 13:54:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 13:54:38 +0000
commit8c1ab65c0f548d20b7f177bdb736daaf603340e1 (patch)
treedf55b7e75bf43f2bf500845b105afe3ac3a5157e /libc-bottom-half/cloudlibc/src/libc/sys/socket
parentInitial commit. (diff)
downloadwasi-libc-upstream/0.0_git20221206.8b7148f.tar.xz
wasi-libc-upstream/0.0_git20221206.8b7148f.zip
Adding upstream version 0.0~git20221206.8b7148f.upstream/0.0_git20221206.8b7148f
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libc-bottom-half/cloudlibc/src/libc/sys/socket')
-rw-r--r--libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c48
-rw-r--r--libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c40
-rw-r--r--libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c32
-rw-r--r--libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c27
-rw-r--r--libc-bottom-half/cloudlibc/src/libc/sys/socket/socket_impl.h57
5 files changed, 204 insertions, 0 deletions
diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c
new file mode 100644
index 0000000..1fe41c4
--- /dev/null
+++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c
@@ -0,0 +1,48 @@
+// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/
+//
+// SPDX-License-Identifier: BSD-2-Clause
+
+#include <sys/socket.h>
+
+#include <wasi/api.h>
+#include <errno.h>
+#include <string.h>
+
+int getsockopt(int socket, int level, int option_name,
+ void *restrict option_value, socklen_t *restrict option_len) {
+ // Only support SOL_SOCKET options for now.
+ if (level != SOL_SOCKET) {
+ errno = ENOPROTOOPT;
+ return -1;
+ }
+
+ int value;
+ switch (option_name) {
+ case SO_TYPE: {
+ // Return the type of the socket. This information can simply be
+ // obtained by looking at the file descriptor type.
+ __wasi_fdstat_t fsb;
+ if (__wasi_fd_fdstat_get(socket, &fsb) != 0) {
+ errno = EBADF;
+ return -1;
+ }
+ if (fsb.fs_filetype != __WASI_FILETYPE_SOCKET_DGRAM &&
+ fsb.fs_filetype != __WASI_FILETYPE_SOCKET_STREAM) {
+ errno = ENOTSOCK;
+ return -1;
+ }
+ value = fsb.fs_filetype;
+ break;
+ }
+ default: {
+ errno = ENOPROTOOPT;
+ return -1;
+ }
+ }
+
+ // Copy out integer value.
+ memcpy(option_value, &value,
+ *option_len < sizeof(int) ? *option_len : sizeof(int));
+ *option_len = sizeof(int);
+ return 0;
+}
diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c
new file mode 100644
index 0000000..d35f889
--- /dev/null
+++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c
@@ -0,0 +1,40 @@
+// Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/
+//
+// SPDX-License-Identifier: BSD-2-Clause
+
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <wasi/api.h>
+#include <errno.h>
+#include <stdint.h>
+
+static_assert(MSG_PEEK == __WASI_RIFLAGS_RECV_PEEK, "Value mismatch");
+static_assert(MSG_WAITALL == __WASI_RIFLAGS_RECV_WAITALL, "Value mismatch");
+
+ssize_t recv(int socket, void *restrict buffer, size_t length, int flags) {
+ // Validate flags.
+ if ((flags & ~(MSG_PEEK | MSG_WAITALL)) != 0) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ // Prepare input parameters.
+ __wasi_iovec_t iov = {.buf = buffer, .buf_len = length};
+ __wasi_iovec_t *ri_data = &iov;
+ size_t ri_data_len = 1;
+ __wasi_riflags_t ri_flags = flags;
+
+ // Perform system call.
+ size_t ro_datalen;
+ __wasi_roflags_t ro_flags;
+ __wasi_errno_t error = __wasi_sock_recv(socket,
+ ri_data, ri_data_len, ri_flags,
+ &ro_datalen,
+ &ro_flags);
+ if (error != 0) {
+ errno = error;
+ return -1;
+ }
+ return ro_datalen;
+}
diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c
new file mode 100644
index 0000000..85a298a
--- /dev/null
+++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c
@@ -0,0 +1,32 @@
+// Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/
+//
+// SPDX-License-Identifier: BSD-2-Clause
+
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <wasi/api.h>
+#include <errno.h>
+
+ssize_t send(int socket, const void *buffer, size_t length, int flags) {
+ // This implementation does not support any flags.
+ if (flags != 0) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ // Prepare input parameters.
+ __wasi_ciovec_t iov = {.buf = buffer, .buf_len = length};
+ __wasi_ciovec_t *si_data = &iov;
+ size_t si_data_len = 1;
+ __wasi_siflags_t si_flags = 0;
+
+ // Perform system call.
+ size_t so_datalen;
+ __wasi_errno_t error = __wasi_sock_send(socket, si_data, si_data_len, si_flags, &so_datalen);
+ if (error != 0) {
+ errno = error;
+ return -1;
+ }
+ return so_datalen;
+}
diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c
new file mode 100644
index 0000000..261fcb8
--- /dev/null
+++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c
@@ -0,0 +1,27 @@
+// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/
+//
+// SPDX-License-Identifier: BSD-2-Clause
+
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <wasi/api.h>
+#include <errno.h>
+
+static_assert(SHUT_RD == __WASI_SDFLAGS_RD, "Value mismatch");
+static_assert(SHUT_WR == __WASI_SDFLAGS_WR, "Value mismatch");
+
+int shutdown(int socket, int how) {
+ // Validate shutdown flags.
+ if (how != SHUT_RD && how != SHUT_WR && how != SHUT_RDWR) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ __wasi_errno_t error = __wasi_sock_shutdown(socket, how);
+ if (error != 0) {
+ errno = error;
+ return -1;
+ }
+ return error;
+}
diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/socket_impl.h b/libc-bottom-half/cloudlibc/src/libc/sys/socket/socket_impl.h
new file mode 100644
index 0000000..7b1a366
--- /dev/null
+++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/socket_impl.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/
+//
+// SPDX-License-Identifier: BSD-2-Clause
+
+#ifndef SYS_SOCKET_SOCKET_IMPL_H
+#define SYS_SOCKET_SOCKET_IMPL_H
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+
+#include <assert.h>
+#include <stdalign.h>
+#include <stddef.h>
+#include <stdint.h>
+
+static_assert(sizeof(struct sockaddr_storage) >= sizeof(struct sockaddr),
+ "struct sockaddr_storage too small");
+static_assert(alignof(struct sockaddr_storage) == alignof(struct sockaddr),
+ "struct sockaddr alignment incorrect");
+static_assert(sizeof(struct sockaddr_storage) >= sizeof(struct sockaddr_in),
+ "struct sockaddr_storage too small");
+static_assert(alignof(struct sockaddr_storage) == alignof(struct sockaddr_in),
+ "struct sockaddr_in alignment incorrect");
+static_assert(sizeof(struct sockaddr_storage) >= sizeof(struct sockaddr_in6),
+ "struct sockaddr_storage too small");
+static_assert(alignof(struct sockaddr_storage) == alignof(struct sockaddr_in6),
+ "struct sockaddr_in6 alignment incorrect");
+static_assert(sizeof(struct sockaddr_storage) >= sizeof(struct sockaddr_un),
+ "struct sockaddr_storage too small");
+static_assert(alignof(struct sockaddr_storage) == alignof(struct sockaddr_un),
+ "struct sockaddr_un alignment incorrect");
+
+// Returns the control message header stored at a provided memory
+// address, ensuring that it is stored within the ancillary data buffer
+// of a message header.
+static inline struct cmsghdr *CMSG_GET(const struct msghdr *mhdr, void *cmsg) {
+ // Safety belt: require that the returned object is properly aligned.
+ assert((uintptr_t)cmsg % alignof(struct cmsghdr) == 0 &&
+ "Attempted to access unaligned control message header");
+
+ // Safety belt: the computed starting address of the control message
+ // header may only lie inside the ancillary data buffer, or right
+ // after it in case we've reached the end of the buffer.
+ const unsigned char *begin = mhdr->msg_control;
+ const unsigned char *end = begin + mhdr->msg_controllen;
+ assert((unsigned char *)cmsg >= begin &&
+ (unsigned char *)cmsg < end + alignof(struct cmsghdr) &&
+ "Computed object outside of buffer boundaries");
+
+ // Only return the control message header in case all of its fields
+ // lie within the ancillary data buffer.
+ return CMSG_DATA((struct cmsghdr *)cmsg) <= end ? cmsg : NULL;
+}
+
+#endif