[libc-commits] [libc] [libc] Add functions to send/recv messages (PR #106467)
Michael Jones via libc-commits
libc-commits at lists.llvm.org
Tue Sep 17 11:30:27 PDT 2024
https://github.com/michaelrj-google updated https://github.com/llvm/llvm-project/pull/106467
>From 46510503182d6ccc3c1c10765e127eab1fcc38e6 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Wed, 7 Feb 2024 15:57:05 -0800
Subject: [PATCH 1/5] [libc] Add functions to send/recv messages
This patch adds the necessary functions to send and receive messages
over a socket. Those functions are: accept, bind, connect, listen, recv,
recvfrom, recvmsg, send, sendto, and sendmsg.
---
libc/config/linux/api.td | 4 +
libc/config/linux/x86_64/entrypoints.txt | 11 +-
libc/include/CMakeLists.txt | 2 +
libc/include/llvm-libc-types/CMakeLists.txt | 6 +-
libc/include/llvm-libc-types/struct_iovec.h | 19 +++
libc/include/llvm-libc-types/struct_msghdr.h | 26 ++++
libc/newhdrgen/yaml/sys/socket.yaml | 83 +++++++++++++
libc/spec/posix.td | 31 +++++
libc/src/sys/socket/CMakeLists.txt | 63 ++++++++++
libc/src/sys/socket/accept.h | 21 ++++
libc/src/sys/socket/connect.h | 20 +++
libc/src/sys/socket/linux/CMakeLists.txt | 117 ++++++++++++++++++
libc/src/sys/socket/linux/accept.cpp | 43 +++++++
libc/src/sys/socket/linux/bind.cpp | 2 +-
libc/src/sys/socket/linux/connect.cpp | 43 +++++++
libc/src/sys/socket/linux/listen.cpp | 40 ++++++
libc/src/sys/socket/linux/recv.cpp | 45 +++++++
libc/src/sys/socket/linux/recvfrom.cpp | 47 +++++++
libc/src/sys/socket/linux/recvmsg.cpp | 41 ++++++
libc/src/sys/socket/linux/send.cpp | 44 +++++++
libc/src/sys/socket/linux/sendmsg.cpp | 41 ++++++
libc/src/sys/socket/linux/sendto.cpp | 47 +++++++
libc/src/sys/socket/listen.h | 18 +++
libc/src/sys/socket/recv.h | 20 +++
libc/src/sys/socket/recvfrom.h | 21 ++++
libc/src/sys/socket/recvmsg.h | 20 +++
libc/src/sys/socket/send.h | 20 +++
libc/src/sys/socket/sendmsg.h | 20 +++
libc/src/sys/socket/sendto.h | 21 ++++
libc/test/src/sys/socket/linux/CMakeLists.txt | 20 ++-
libc/test/src/sys/socket/linux/send_test.cpp | 73 +++++++++++
.../src/sys/socket/linux/sendmsg_test.cpp | 1 +
.../test/src/sys/socket/linux/sendto_test.cpp | 1 +
33 files changed, 1026 insertions(+), 5 deletions(-)
create mode 100644 libc/include/llvm-libc-types/struct_iovec.h
create mode 100644 libc/include/llvm-libc-types/struct_msghdr.h
create mode 100644 libc/src/sys/socket/accept.h
create mode 100644 libc/src/sys/socket/connect.h
create mode 100644 libc/src/sys/socket/linux/accept.cpp
create mode 100644 libc/src/sys/socket/linux/connect.cpp
create mode 100644 libc/src/sys/socket/linux/listen.cpp
create mode 100644 libc/src/sys/socket/linux/recv.cpp
create mode 100644 libc/src/sys/socket/linux/recvfrom.cpp
create mode 100644 libc/src/sys/socket/linux/recvmsg.cpp
create mode 100644 libc/src/sys/socket/linux/send.cpp
create mode 100644 libc/src/sys/socket/linux/sendmsg.cpp
create mode 100644 libc/src/sys/socket/linux/sendto.cpp
create mode 100644 libc/src/sys/socket/listen.h
create mode 100644 libc/src/sys/socket/recv.h
create mode 100644 libc/src/sys/socket/recvfrom.h
create mode 100644 libc/src/sys/socket/recvmsg.h
create mode 100644 libc/src/sys/socket/send.h
create mode 100644 libc/src/sys/socket/sendmsg.h
create mode 100644 libc/src/sys/socket/sendto.h
create mode 100644 libc/test/src/sys/socket/linux/send_test.cpp
create mode 100644 libc/test/src/sys/socket/linux/sendmsg_test.cpp
create mode 100644 libc/test/src/sys/socket/linux/sendto_test.cpp
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 6a7c64296bf922..46523b4ca4b8df 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -193,6 +193,10 @@ def SysSocketAPI : PublicAPI<"sys/socket.h"> {
"socklen_t",
"struct sockaddr",
"struct sockaddr_un",
+ "struct msghdr",
+ "struct iovec",
+ "size_t",
+ "ssize_t",
];
}
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 141dc70463d64a..d7220131046008 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1026,8 +1026,17 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.sys.select.select
# sys/socket.h entrypoints
- libc.src.sys.socket.bind
libc.src.sys.socket.socket
+ libc.src.sys.socket.bind
+ libc.src.sys.socket.send
+ libc.src.sys.socket.sendto
+ libc.src.sys.socket.sendmsg
+ libc.src.sys.socket.recv
+ libc.src.sys.socket.recvfrom
+ libc.src.sys.socket.recvmsg
+ libc.src.sys.socket.connect
+ libc.src.sys.socket.listen
+ libc.src.sys.socket.accept
)
endif()
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 910f9eea015f27..d2289ab160ba14 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -592,6 +592,8 @@ add_header_macro(
.llvm-libc-macros.sys_socket_macros
.llvm-libc-types.sa_family_t
.llvm-libc-types.socklen_t
+ .llvm-libc-types.struct_iovec
+ .llvm-libc-types.struct_msghdr
.llvm-libc-types.struct_sockaddr
.llvm-libc-types.struct_sockaddr_un
)
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 583b84ccaae67c..a4cf4631c8470e 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -117,8 +117,10 @@ add_header(
add_header(wint_t HDR wint_t.h)
add_header(sa_family_t HDR sa_family_t.h)
add_header(socklen_t HDR socklen_t.h)
-add_header(struct_sockaddr_un HDR struct_sockaddr_un.h)
-add_header(struct_sockaddr HDR struct_sockaddr.h)
+add_header(struct_sockaddr_un HDR struct_sockaddr_un.h DEPENDS .sa_family_t)
+add_header(struct_sockaddr HDR struct_sockaddr.h DEPENDS .sa_family_t)
+add_header(struct_iovec HDR struct_iovec.h DEPENDS .size_t)
+add_header(struct_msghdr HDR struct_msghdr.h DEPENDS .size_t .socklen_t .struct_iovec)
add_header(rpc_opcodes_t HDR rpc_opcodes_t.h)
add_header(ACTION HDR ACTION.h)
add_header(ENTRY HDR ENTRY.h)
diff --git a/libc/include/llvm-libc-types/struct_iovec.h b/libc/include/llvm-libc-types/struct_iovec.h
new file mode 100644
index 00000000000000..36e7bb79d0787f
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_iovec.h
@@ -0,0 +1,19 @@
+//===-- Definition of struct iovec ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
+#define __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
+
+#include <llvm-libc-types/size_t.h>
+
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+
+#endif // __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
diff --git a/libc/include/llvm-libc-types/struct_msghdr.h b/libc/include/llvm-libc-types/struct_msghdr.h
new file mode 100644
index 00000000000000..5af6d56218c0fc
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_msghdr.h
@@ -0,0 +1,26 @@
+//===-- Definition of struct msghdr ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_STRUCT_MSGHDR_H__
+#define __LLVM_LIBC_TYPES_STRUCT_MSGHDR_H__
+
+#include <llvm-libc-types/size_t.h>
+#include <llvm-libc-types/socklen_t.h>
+#include <llvm-libc-types/struct_iovec.h>
+
+struct msghdr {
+ void *msg_name; /* Optional address */
+ socklen_t msg_namelen; /* Size of address */
+ struct iovec *msg_iov; /* Scatter/gather array */
+ size_t msg_iovlen; /* # elements in msg_iov */
+ void *msg_control; /* Ancillary data, see below */
+ size_t msg_controllen; /* Ancillary data buffer len */
+ int msg_flags; /* Flags (unused) */
+};
+
+#endif // __LLVM_LIBC_TYPES_STRUCT_MSGHDR_H__
diff --git a/libc/newhdrgen/yaml/sys/socket.yaml b/libc/newhdrgen/yaml/sys/socket.yaml
index 3b8bf4cecfe5aa..4f7b1109d99456 100644
--- a/libc/newhdrgen/yaml/sys/socket.yaml
+++ b/libc/newhdrgen/yaml/sys/socket.yaml
@@ -5,9 +5,21 @@ types:
- type_name: struct_sockaddr
- type_name: socklen_t
- type_name: sa_family_t
+ - type_name: struct_msghdr
+ - type_name: struct_iovec
+ - type_name: size_t
+ - type_name: ssize_t
enums: []
objects: []
functions:
+ - name: accept
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: int
+ - type: sockaddr *__restrict
+ - type: socklen_t *__restrict
- name: bind
standards:
- POSIX
@@ -16,6 +28,77 @@ functions:
- type: int
- type: const struct sockaddr *
- type: socklen_t
+ - name: connect
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: int
+ - type: const struct sockaddr *
+ - type: socklen_t
+ - name: listen
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: int
+ - type: int
+ - name: recv
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const void *
+ - type: size_t
+ - type: int
+ - name: recvfrom
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const void*
+ - type: size_t
+ - type: int
+ - type: const struct sockaddr *
+ - type: socklen_t
+ - name: recvmsg
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const struct msghdr *
+ - type: int
+ - name: send
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const void*
+ - type: size_t
+ - type: int
+ - name: sendmsg
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const struct msghdr *
+ - type: int
+ - name: sendto
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const void *
+ - type: size_t
+ - type: int
+ - type: const struct sockaddr *
+ - type: socklen_t
- name: socket
standards:
- POSIX
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 085f2ec34ab346..b2c53c9a1bd2f5 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -85,6 +85,14 @@ def StructSockAddr : NamedType<"struct sockaddr">;
def StructSockAddrPtr : PtrType<StructSockAddr>;
def ConstStructSockAddrPtr : ConstType<StructSockAddrPtr>;
+def StructMsghdr : NamedType<"struct msghdr">;
+def StructMsghdrPtr : PtrType<StructMsghdr>;
+def ConstStructMsghdrPtr : ConstType<StructMsghdrPtr>;
+
+def StructIovec : NamedType<"struct iovec">;
+def StructIovecPtr : PtrType<StructIovec>;
+def ConstStructIovecPtr : ConstType<StructIovecPtr>;
+
def StructSockAddrUn : NamedType<"struct sockaddr_un">;
def StructStatvfs : NamedType<"struct statvfs">;
@@ -1711,10 +1719,14 @@ def POSIX : StandardSpec<"POSIX"> {
Macro<"SOCK_PACKET">,
], // Macros
[
+ SizeTType,
+ SSizeTType,
SAFamilyType,
StructSockAddr,
StructSockAddrUn,
SocklenType,
+ StructIovec,
+ StructMsghdr,
], // Types
[], // Enumerations
[
@@ -1728,6 +1740,25 @@ def POSIX : StandardSpec<"POSIX"> {
RetValSpec<IntType>,
[ArgSpec<IntType>, ArgSpec<ConstStructSockAddrPtr>, ArgSpec<SocklenType>]
>,
+ FunctionSpec<
+ "send",
+ RetValSpec<SSizeTType>,
+ [ArgSpec<IntType>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "sendto",
+ RetValSpec<SSizeTType>,
+ [
+ ArgSpec<IntType>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>,
+ ArgSpec<IntType>, ArgSpec<ConstStructSockAddrPtr>,
+ ArgSpec<SocklenType>
+ ]
+ >,
+ FunctionSpec<
+ "sendmsg",
+ RetValSpec<SSizeTType>,
+ [ArgSpec<IntType>, ArgSpec<ConstStructMsghdrPtr>, ArgSpec<IntType>]
+ >,
] // Functions
>;
diff --git a/libc/src/sys/socket/CMakeLists.txt b/libc/src/sys/socket/CMakeLists.txt
index e0bc48735a0314..cd877b923f9f37 100644
--- a/libc/src/sys/socket/CMakeLists.txt
+++ b/libc/src/sys/socket/CMakeLists.txt
@@ -15,3 +15,66 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_OS}.bind
)
+
+add_entrypoint_object(
+ send
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.send
+)
+
+add_entrypoint_object(
+ sendto
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sendto
+)
+
+add_entrypoint_object(
+ sendmsg
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sendmsg
+)
+
+add_entrypoint_object(
+ recv
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.recv
+)
+
+add_entrypoint_object(
+ recvfrom
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.recvfrom
+)
+
+add_entrypoint_object(
+ recvmsg
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.recvmsg
+)
+
+add_entrypoint_object(
+ connect
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.connect
+)
+
+add_entrypoint_object(
+ accept
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.accept
+)
+
+add_entrypoint_object(
+ listen
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.listen
+)
diff --git a/libc/src/sys/socket/accept.h b/libc/src/sys/socket/accept.h
new file mode 100644
index 00000000000000..b523d9e3b7586a
--- /dev/null
+++ b/libc/src/sys/socket/accept.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for accept ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+int accept(int domain, sockaddr *__restrict address,
+ socklen_t *__restrict address_len);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
diff --git a/libc/src/sys/socket/connect.h b/libc/src/sys/socket/connect.h
new file mode 100644
index 00000000000000..0588c56504be39
--- /dev/null
+++ b/libc/src/sys/socket/connect.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for connect -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index fc9febdec2cc3c..4a73f87fbd7bef 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -23,3 +23,120 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ send
+ SRCS
+ send.cpp
+ HDRS
+ ../send.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sendto
+ SRCS
+ sendto.cpp
+ HDRS
+ ../sendto.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sendmsg
+ SRCS
+ sendmsg.cpp
+ HDRS
+ ../sendmsg.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ connect
+ SRCS
+ connect.cpp
+ HDRS
+ ../connect.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ recv
+ SRCS
+ recv.cpp
+ HDRS
+ ../recv.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ recvfrom
+ SRCS
+ recvfrom.cpp
+ HDRS
+ ../recvfrom.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ recvmsg
+ SRCS
+ recvmsg.cpp
+ HDRS
+ ../recvmsg.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ accept
+ SRCS
+ accept.cpp
+ HDRS
+ ../accept.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ listen
+ SRCS
+ listen.cpp
+ HDRS
+ ../listen.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
diff --git a/libc/src/sys/socket/linux/accept.cpp b/libc/src/sys/socket/linux/accept.cpp
new file mode 100644
index 00000000000000..ea615be36762f0
--- /dev/null
+++ b/libc/src/sys/socket/linux/accept.cpp
@@ -0,0 +1,43 @@
+//===-- Linux implementation of accept ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/accept.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/errno/libc_errno.h"
+
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, accept,
+ (int domain, sockaddr *__restrict address,
+ socklen_t *__restrict address_len)) {
+#ifdef SYS_accept
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_accept, domain, address,
+ address_len);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[3] = {static_cast<unsigned long>(domain),
+ reinterpret_cast<unsigned long>(address),
+ static_cast<unsigned long>(address_len)};
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_ACCEPT,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/bind.cpp b/libc/src/sys/socket/linux/bind.cpp
index 3289e9f0852e86..925fca81e56810 100644
--- a/libc/src/sys/socket/linux/bind.cpp
+++ b/libc/src/sys/socket/linux/bind.cpp
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, bind,
(int domain, const struct sockaddr *address,
socklen_t address_len)) {
-#ifdef SYS_socket
+#ifdef SYS_bind
int ret =
LIBC_NAMESPACE::syscall_impl<int>(SYS_bind, domain, address, address_len);
#elif defined(SYS_socketcall)
diff --git a/libc/src/sys/socket/linux/connect.cpp b/libc/src/sys/socket/linux/connect.cpp
new file mode 100644
index 00000000000000..d1e7265c1ddbc3
--- /dev/null
+++ b/libc/src/sys/socket/linux/connect.cpp
@@ -0,0 +1,43 @@
+//===-- Linux implementation of connect
+//--------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/connect.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, connect,
+ (int sockfd, const struct sockaddr *addr,
+ socklen_t addrlen)) {
+#ifdef SYS_connect
+ int ret =
+ LIBC_NAMESPACE::syscall_impl<int>(SYS_connect, sockfd, addr, addrlen);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[4] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(addr),
+ static_cast<unsigned long>(addrlen)};
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_CONNECT,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/listen.cpp b/libc/src/sys/socket/linux/listen.cpp
new file mode 100644
index 00000000000000..e57738e5ce4a94
--- /dev/null
+++ b/libc/src/sys/socket/linux/listen.cpp
@@ -0,0 +1,40 @@
+//===-- Linux implementation of listen
+//--------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/listen.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/errno/libc_errno.h"
+
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, listen, (int socket, int backlog)) {
+#ifdef SYS_listen
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_listen, socket, backlog);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[2] = {static_cast<unsigned long>(socket),
+ reinterpret_cast<unsigned long>(backlog)};
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_LISTEN,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/recv.cpp b/libc/src/sys/socket/linux/recv.cpp
new file mode 100644
index 00000000000000..2d19d761215478
--- /dev/null
+++ b/libc/src/sys/socket/linux/recv.cpp
@@ -0,0 +1,45 @@
+//===-- Linux implementation of recv --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recv.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, recv,
+ (int sockfd, const void *buf, size_t len, int flags)) {
+#ifdef SYS_recv
+ ssize_t ret =
+ LIBC_NAMESPACE::syscall_impl<int>(SYS_recv, sockfd, buf, len, flags);
+#elif defined(SYS_recvfrom)
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_recvfrom, sockfd,
+ reinterpret_cast<long>(buf),
+ len, flags, nullptr, 0);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[4] = {
+ static_cast<unsigned long>(sockfd), reinterpret_cast<unsigned long>(buf),
+ static_cast<unsigned long>(len), static_cast<unsigned long>(flags)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_RECV,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/recvfrom.cpp b/libc/src/sys/socket/linux/recvfrom.cpp
new file mode 100644
index 00000000000000..550ae4c11389b9
--- /dev/null
+++ b/libc/src/sys/socket/linux/recvfrom.cpp
@@ -0,0 +1,47 @@
+//===-- Linux implementation of recvfrom ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recvfrom.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
+ (int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen)) {
+#ifdef SYS_recvfrom
+
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_recvfrom, sockfd, reinterpret_cast<long>(buf), len, flags,
+ reinterpret_cast<long>(dest_addr), addrlen);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[6] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(buf),
+ static_cast<unsigned long>(len),
+ static_cast<unsigned long>(flags),
+ reinterpret_cast<unsigned long>(dest_addr),
+ static_cast<unsigned long>(addrlen)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_RECVFROM,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/recvmsg.cpp b/libc/src/sys/socket/linux/recvmsg.cpp
new file mode 100644
index 00000000000000..1bae39694833c4
--- /dev/null
+++ b/libc/src/sys/socket/linux/recvmsg.cpp
@@ -0,0 +1,41 @@
+//===-- Linux implementation of recvmsg -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recvmsg.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, recvmsg,
+ (int sockfd, const struct msghdr *msg, int flags)) {
+#ifdef SYS_recvmsg
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_recvmsg, sockfd, reinterpret_cast<long>(msg), flags);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[3] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(msg),
+ static_cast<unsigned long>(flags)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_RECVMSG,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/send.cpp b/libc/src/sys/socket/linux/send.cpp
new file mode 100644
index 00000000000000..4fa0da72a0c9f0
--- /dev/null
+++ b/libc/src/sys/socket/linux/send.cpp
@@ -0,0 +1,44 @@
+//===-- Linux implementation of send --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/send.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, send,
+ (int sockfd, const void *buf, size_t len, int flags)) {
+#ifdef SYS_send
+ ssize_t ret =
+ LIBC_NAMESPACE::syscall_impl<int>(SYS_send, sockfd, buf, len, flags);
+#elif defined(SYS_sendto)
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_sendto, sockfd, reinterpret_cast<long>(buf), len, flags, nullptr, 0);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[4] = {
+ static_cast<unsigned long>(sockfd), reinterpret_cast<unsigned long>(buf),
+ static_cast<unsigned long>(len), static_cast<unsigned long>(flags)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SEND,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/sendmsg.cpp b/libc/src/sys/socket/linux/sendmsg.cpp
new file mode 100644
index 00000000000000..3eeaef38d76ca7
--- /dev/null
+++ b/libc/src/sys/socket/linux/sendmsg.cpp
@@ -0,0 +1,41 @@
+//===-- Linux implementation of sendmsg -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/sendmsg.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, sendmsg,
+ (int sockfd, const struct msghdr *msg, int flags)) {
+#ifdef SYS_sendmsg
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_sendmsg, sockfd, reinterpret_cast<long>(msg), flags);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[3] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(msg),
+ static_cast<unsigned long>(flags)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SENDMSG,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/sendto.cpp b/libc/src/sys/socket/linux/sendto.cpp
new file mode 100644
index 00000000000000..7c66408d37e1d5
--- /dev/null
+++ b/libc/src/sys/socket/linux/sendto.cpp
@@ -0,0 +1,47 @@
+//===-- Linux implementation of sendto ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/sendto.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, sendto,
+ (int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen)) {
+#ifdef SYS_sendto
+
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_sendto, sockfd, reinterpret_cast<long>(buf), len, flags,
+ reinterpret_cast<long>(dest_addr), addrlen);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[6] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(buf),
+ static_cast<unsigned long>(len),
+ static_cast<unsigned long>(flags),
+ reinterpret_cast<unsigned long>(dest_addr),
+ static_cast<unsigned long>(addrlen)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SENDTO,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/listen.h b/libc/src/sys/socket/listen.h
new file mode 100644
index 00000000000000..ad77fac655ce41
--- /dev/null
+++ b/libc/src/sys/socket/listen.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for listen ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
+
+namespace LIBC_NAMESPACE {
+
+int listen(int socket, int backlog);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
diff --git a/libc/src/sys/socket/recv.h b/libc/src/sys/socket/recv.h
new file mode 100644
index 00000000000000..7b626e35d3ef47
--- /dev/null
+++ b/libc/src/sys/socket/recv.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for recv --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t recv(int sockfd, const void *buf, size_t len, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
diff --git a/libc/src/sys/socket/recvfrom.h b/libc/src/sys/socket/recvfrom.h
new file mode 100644
index 00000000000000..aee387b3dc0f3a
--- /dev/null
+++ b/libc/src/sys/socket/recvfrom.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for recvfrom ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t recvfrom(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *address, socklen_t addrlen);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
diff --git a/libc/src/sys/socket/recvmsg.h b/libc/src/sys/socket/recvmsg.h
new file mode 100644
index 00000000000000..cc6a934f705eec
--- /dev/null
+++ b/libc/src/sys/socket/recvmsg.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for recvmsg -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t recvmsg(int sockfd, const struct msghdr *msg, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
diff --git a/libc/src/sys/socket/send.h b/libc/src/sys/socket/send.h
new file mode 100644
index 00000000000000..a06db3b978ac19
--- /dev/null
+++ b/libc/src/sys/socket/send.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for send --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t send(int sockfd, const void *buf, size_t len, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
diff --git a/libc/src/sys/socket/sendmsg.h b/libc/src/sys/socket/sendmsg.h
new file mode 100644
index 00000000000000..4c970585558eb0
--- /dev/null
+++ b/libc/src/sys/socket/sendmsg.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for sendmsg -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
diff --git a/libc/src/sys/socket/sendto.h b/libc/src/sys/socket/sendto.h
new file mode 100644
index 00000000000000..afb1fce9d61fcc
--- /dev/null
+++ b/libc/src/sys/socket/sendto.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for sendto ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index 666dc28c7e4ee1..32ae9d7481ed42 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -13,7 +13,6 @@ add_libc_unittest(
libc.src.unistd.close
)
-
add_libc_unittest(
bind_test
SUITE
@@ -28,3 +27,22 @@ add_libc_unittest(
libc.src.stdio.remove
libc.src.unistd.close
)
+
+add_libc_unittest(
+ send_test
+ SUITE
+ libc_sys_socket_unittests
+ SRCS
+ send_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.send
+ libc.src.sys.socket.socket
+ libc.src.sys.socket.bind
+ libc.src.sys.socket.connect
+ libc.src.sys.socket.listen
+ libc.src.sys.socket.accept
+ libc.src.stdio.remove
+ libc.src.unistd.close
+)
diff --git a/libc/test/src/sys/socket/linux/send_test.cpp b/libc/test/src/sys/socket/linux/send_test.cpp
new file mode 100644
index 00000000000000..def46a0edcb277
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/send_test.cpp
@@ -0,0 +1,73 @@
+//===-- Unittests for send ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/remove.h"
+#include "src/sys/socket/accept.h"
+#include "src/sys/socket/bind.h"
+#include "src/sys/socket/connect.h"
+#include "src/sys/socket/listen.h"
+#include "src/sys/socket/send.h"
+#include "src/sys/socket/socket.h"
+#include "src/unistd/close.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+
+TEST(LlvmLibcSocketTest, BindLocalSocket) {
+
+ const char *FILENAME = "send_file.test";
+ auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+
+ // if might exist if the test fails
+ LIBC_NAMESPACE::remove(SOCK_PATH);
+
+ int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_DGRAM, 0);
+ ASSERT_GE(sock, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr_un my_addr;
+
+ my_addr.sun_family = AF_UNIX;
+ unsigned int i = 0;
+ for (;
+ SOCK_PATH[i] != '\0' && (i < sizeof(sockaddr_un) - sizeof(sa_family_t));
+ ++i)
+ my_addr.sun_path[i] = SOCK_PATH[i];
+ my_addr.sun_path[i] = '\0';
+
+ // It's important that the path fits in the struct, if it doesn't then we
+ // can't try to bind to the file.
+ ASSERT_LT(
+ i, static_cast<unsigned int>(sizeof(sockaddr_un) - sizeof(sa_family_t)));
+
+ int result =
+ LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+ sizeof(struct sockaddr_un));
+
+ EXPECT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr *connected_sock;
+
+ // result = LIBC_NAMESPACE::connect(sock, connected_sock, socklen_t addrlen)
+
+ const char TEST_MESSAGE[] = "connection successful";
+ const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+ ssize_t send_result =
+ LIBC_NAMESPACE::send(sock, TEST_MESSAGE, MESSAGE_LEN, 0);
+
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::close(sock);
+
+ // LIBC_NAMESPACE::remove(SOCK_PATH);
+}
diff --git a/libc/test/src/sys/socket/linux/sendmsg_test.cpp b/libc/test/src/sys/socket/linux/sendmsg_test.cpp
new file mode 100644
index 00000000000000..b00a271b5497a1
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/sendmsg_test.cpp
@@ -0,0 +1 @@
+TODO: TESTS
diff --git a/libc/test/src/sys/socket/linux/sendto_test.cpp b/libc/test/src/sys/socket/linux/sendto_test.cpp
new file mode 100644
index 00000000000000..b00a271b5497a1
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/sendto_test.cpp
@@ -0,0 +1 @@
+TODO: TESTS
>From 367640d3ac4387faf97a78d5c1bea8c9cac96a80 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Tue, 10 Sep 2024 10:59:18 -0700
Subject: [PATCH 2/5] move tests to be integration tests.
---
libc/src/sys/socket/accept.h | 5 +-
libc/src/sys/socket/bind.h | 2 +-
libc/src/sys/socket/connect.h | 11 +-
libc/src/sys/socket/linux/accept.cpp | 4 +-
libc/src/sys/socket/linux/bind.cpp | 6 +-
libc/src/sys/socket/linux/connect.cpp | 4 +-
libc/src/sys/socket/linux/listen.cpp | 4 +-
libc/src/sys/socket/linux/recv.cpp | 4 +-
libc/src/sys/socket/linux/recvfrom.cpp | 4 +-
libc/src/sys/socket/linux/recvmsg.cpp | 4 +-
libc/src/sys/socket/linux/send.cpp | 4 +-
libc/src/sys/socket/linux/sendmsg.cpp | 4 +-
libc/src/sys/socket/linux/sendto.cpp | 4 +-
libc/src/sys/socket/listen.h | 5 +-
libc/src/sys/socket/recv.h | 5 +-
libc/src/sys/socket/recvfrom.h | 5 +-
libc/src/sys/socket/recvmsg.h | 5 +-
libc/src/sys/socket/send.h | 5 +-
libc/src/sys/socket/sendmsg.h | 5 +-
libc/src/sys/socket/sendto.h | 5 +-
libc/test/integration/src/CMakeLists.txt | 1 +
libc/test/integration/src/sys/CMakeLists.txt | 1 +
.../integration/src/sys/socket/CMakeLists.txt | 3 +
.../src/sys/socket/linux/CMakeLists.txt | 24 +++
.../socket/linux/socket_send_recv_test.cpp | 138 ++++++++++++++++++
libc/test/src/sys/socket/linux/CMakeLists.txt | 19 ---
libc/test/src/sys/socket/linux/send_test.cpp | 73 ---------
.../src/sys/socket/linux/sendmsg_test.cpp | 1 -
.../test/src/sys/socket/linux/sendto_test.cpp | 1 -
29 files changed, 219 insertions(+), 137 deletions(-)
create mode 100644 libc/test/integration/src/sys/CMakeLists.txt
create mode 100644 libc/test/integration/src/sys/socket/CMakeLists.txt
create mode 100644 libc/test/integration/src/sys/socket/linux/CMakeLists.txt
create mode 100644 libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
delete mode 100644 libc/test/src/sys/socket/linux/send_test.cpp
delete mode 100644 libc/test/src/sys/socket/linux/sendmsg_test.cpp
delete mode 100644 libc/test/src/sys/socket/linux/sendto_test.cpp
diff --git a/libc/src/sys/socket/accept.h b/libc/src/sys/socket/accept.h
index b523d9e3b7586a..c7cebc35e987cf 100644
--- a/libc/src/sys/socket/accept.h
+++ b/libc/src/sys/socket/accept.h
@@ -9,13 +9,14 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
#define LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
+#include "src/__support/macros/config.h"
#include <sys/socket.h>
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
int accept(int domain, sockaddr *__restrict address,
socklen_t *__restrict address_len);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
diff --git a/libc/src/sys/socket/bind.h b/libc/src/sys/socket/bind.h
index 1676ab6a003ad9..cec9c9da0c871e 100644
--- a/libc/src/sys/socket/bind.h
+++ b/libc/src/sys/socket/bind.h
@@ -14,7 +14,7 @@
namespace LIBC_NAMESPACE_DECL {
-int bind(int domain, const struct sockaddr *address, socklen_t address_len);
+int bind(int socket, const struct sockaddr *address, socklen_t address_len);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/connect.h b/libc/src/sys/socket/connect.h
index 0588c56504be39..221f9a44cbaf9a 100644
--- a/libc/src/sys/socket/connect.h
+++ b/libc/src/sys/socket/connect.h
@@ -6,15 +6,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
-#define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
+#include "src/__support/macros/config.h"
#include <sys/socket.h>
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
-#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
diff --git a/libc/src/sys/socket/linux/accept.cpp b/libc/src/sys/socket/linux/accept.cpp
index ea615be36762f0..5a6c70349e048a 100644
--- a/libc/src/sys/socket/linux/accept.cpp
+++ b/libc/src/sys/socket/linux/accept.cpp
@@ -16,7 +16,7 @@
#include <linux/net.h> // For SYS_SOCKET socketcall number.
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, accept,
(int domain, sockaddr *__restrict address,
@@ -40,4 +40,4 @@ LLVM_LIBC_FUNCTION(int, accept,
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/bind.cpp b/libc/src/sys/socket/linux/bind.cpp
index 925fca81e56810..72a3307a91ddd7 100644
--- a/libc/src/sys/socket/linux/bind.cpp
+++ b/libc/src/sys/socket/linux/bind.cpp
@@ -20,13 +20,13 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, bind,
- (int domain, const struct sockaddr *address,
+ (int socket, const struct sockaddr *address,
socklen_t address_len)) {
#ifdef SYS_bind
int ret =
- LIBC_NAMESPACE::syscall_impl<int>(SYS_bind, domain, address, address_len);
+ LIBC_NAMESPACE::syscall_impl<int>(SYS_bind, socket, address, address_len);
#elif defined(SYS_socketcall)
- unsigned long sockcall_args[3] = {static_cast<unsigned long>(domain),
+ unsigned long sockcall_args[3] = {static_cast<unsigned long>(socket),
reinterpret_cast<unsigned long>(address),
static_cast<unsigned long>(address_len)};
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_BIND,
diff --git a/libc/src/sys/socket/linux/connect.cpp b/libc/src/sys/socket/linux/connect.cpp
index d1e7265c1ddbc3..eaf422613f5e62 100644
--- a/libc/src/sys/socket/linux/connect.cpp
+++ b/libc/src/sys/socket/linux/connect.cpp
@@ -16,7 +16,7 @@
#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, connect,
(int sockfd, const struct sockaddr *addr,
@@ -40,4 +40,4 @@ LLVM_LIBC_FUNCTION(int, connect,
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/listen.cpp b/libc/src/sys/socket/linux/listen.cpp
index e57738e5ce4a94..a5906e57371c9c 100644
--- a/libc/src/sys/socket/linux/listen.cpp
+++ b/libc/src/sys/socket/linux/listen.cpp
@@ -17,7 +17,7 @@
#include <linux/net.h> // For SYS_SOCKET socketcall number.
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, listen, (int socket, int backlog)) {
#ifdef SYS_listen
@@ -37,4 +37,4 @@ LLVM_LIBC_FUNCTION(int, listen, (int socket, int backlog)) {
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/recv.cpp b/libc/src/sys/socket/linux/recv.cpp
index 2d19d761215478..afefac73f3db4a 100644
--- a/libc/src/sys/socket/linux/recv.cpp
+++ b/libc/src/sys/socket/linux/recv.cpp
@@ -15,7 +15,7 @@
#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, recv,
(int sockfd, const void *buf, size_t len, int flags)) {
@@ -42,4 +42,4 @@ LLVM_LIBC_FUNCTION(ssize_t, recv,
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/recvfrom.cpp b/libc/src/sys/socket/linux/recvfrom.cpp
index 550ae4c11389b9..9b20982bb1fbf3 100644
--- a/libc/src/sys/socket/linux/recvfrom.cpp
+++ b/libc/src/sys/socket/linux/recvfrom.cpp
@@ -15,7 +15,7 @@
#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
(int sockfd, const void *buf, size_t len, int flags,
@@ -44,4 +44,4 @@ LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/recvmsg.cpp b/libc/src/sys/socket/linux/recvmsg.cpp
index 1bae39694833c4..4a2f6fabbc2da1 100644
--- a/libc/src/sys/socket/linux/recvmsg.cpp
+++ b/libc/src/sys/socket/linux/recvmsg.cpp
@@ -15,7 +15,7 @@
#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, recvmsg,
(int sockfd, const struct msghdr *msg, int flags)) {
@@ -38,4 +38,4 @@ LLVM_LIBC_FUNCTION(ssize_t, recvmsg,
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/send.cpp b/libc/src/sys/socket/linux/send.cpp
index 4fa0da72a0c9f0..fc5305d5cdfa3d 100644
--- a/libc/src/sys/socket/linux/send.cpp
+++ b/libc/src/sys/socket/linux/send.cpp
@@ -15,7 +15,7 @@
#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, send,
(int sockfd, const void *buf, size_t len, int flags)) {
@@ -41,4 +41,4 @@ LLVM_LIBC_FUNCTION(ssize_t, send,
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/sendmsg.cpp b/libc/src/sys/socket/linux/sendmsg.cpp
index 3eeaef38d76ca7..822a26493dddb4 100644
--- a/libc/src/sys/socket/linux/sendmsg.cpp
+++ b/libc/src/sys/socket/linux/sendmsg.cpp
@@ -15,7 +15,7 @@
#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, sendmsg,
(int sockfd, const struct msghdr *msg, int flags)) {
@@ -38,4 +38,4 @@ LLVM_LIBC_FUNCTION(ssize_t, sendmsg,
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/sendto.cpp b/libc/src/sys/socket/linux/sendto.cpp
index 7c66408d37e1d5..bc0769bc77d1d7 100644
--- a/libc/src/sys/socket/linux/sendto.cpp
+++ b/libc/src/sys/socket/linux/sendto.cpp
@@ -15,7 +15,7 @@
#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, sendto,
(int sockfd, const void *buf, size_t len, int flags,
@@ -44,4 +44,4 @@ LLVM_LIBC_FUNCTION(ssize_t, sendto,
return ret;
}
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/listen.h b/libc/src/sys/socket/listen.h
index ad77fac655ce41..ab943b3b8be3a8 100644
--- a/libc/src/sys/socket/listen.h
+++ b/libc/src/sys/socket/listen.h
@@ -9,10 +9,11 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
#define LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
-namespace LIBC_NAMESPACE {
+#include "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
int listen(int socket, int backlog);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
diff --git a/libc/src/sys/socket/recv.h b/libc/src/sys/socket/recv.h
index 7b626e35d3ef47..093e8ca9b12304 100644
--- a/libc/src/sys/socket/recv.h
+++ b/libc/src/sys/socket/recv.h
@@ -9,12 +9,13 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
#define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#include "src/__support/macros/config.h"
#include <sys/socket.h>
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
ssize_t recv(int sockfd, const void *buf, size_t len, int flags);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
diff --git a/libc/src/sys/socket/recvfrom.h b/libc/src/sys/socket/recvfrom.h
index aee387b3dc0f3a..b1f36467bd574a 100644
--- a/libc/src/sys/socket/recvfrom.h
+++ b/libc/src/sys/socket/recvfrom.h
@@ -9,13 +9,14 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
#define LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
+#include "src/__support/macros/config.h"
#include <sys/socket.h>
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
ssize_t recvfrom(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *address, socklen_t addrlen);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
diff --git a/libc/src/sys/socket/recvmsg.h b/libc/src/sys/socket/recvmsg.h
index cc6a934f705eec..0cffb7af7c3d7d 100644
--- a/libc/src/sys/socket/recvmsg.h
+++ b/libc/src/sys/socket/recvmsg.h
@@ -9,12 +9,13 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
#define LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
+#include "src/__support/macros/config.h"
#include <sys/socket.h>
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
ssize_t recvmsg(int sockfd, const struct msghdr *msg, int flags);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
diff --git a/libc/src/sys/socket/send.h b/libc/src/sys/socket/send.h
index a06db3b978ac19..e1706694cd5f5d 100644
--- a/libc/src/sys/socket/send.h
+++ b/libc/src/sys/socket/send.h
@@ -9,12 +9,13 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
#define LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
+#include "src/__support/macros/config.h"
#include <sys/socket.h>
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
diff --git a/libc/src/sys/socket/sendmsg.h b/libc/src/sys/socket/sendmsg.h
index 4c970585558eb0..d902632eee0fa3 100644
--- a/libc/src/sys/socket/sendmsg.h
+++ b/libc/src/sys/socket/sendmsg.h
@@ -9,12 +9,13 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
#define LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
+#include "src/__support/macros/config.h"
#include <sys/socket.h>
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
diff --git a/libc/src/sys/socket/sendto.h b/libc/src/sys/socket/sendto.h
index afb1fce9d61fcc..8b56362b930c97 100644
--- a/libc/src/sys/socket/sendto.h
+++ b/libc/src/sys/socket/sendto.h
@@ -9,13 +9,14 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
#define LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
+#include "src/__support/macros/config.h"
#include <sys/socket.h>
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
diff --git a/libc/test/integration/src/CMakeLists.txt b/libc/test/integration/src/CMakeLists.txt
index 1104b3de99e9b7..7c97c68d2a7d15 100644
--- a/libc/test/integration/src/CMakeLists.txt
+++ b/libc/test/integration/src/CMakeLists.txt
@@ -5,3 +5,4 @@ add_subdirectory(stdio)
add_subdirectory(stdlib)
add_subdirectory(threads)
add_subdirectory(unistd)
+add_subdirectory(sys)
diff --git a/libc/test/integration/src/sys/CMakeLists.txt b/libc/test/integration/src/sys/CMakeLists.txt
new file mode 100644
index 00000000000000..5a3c0f8150c7ee
--- /dev/null
+++ b/libc/test/integration/src/sys/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(socket)
diff --git a/libc/test/integration/src/sys/socket/CMakeLists.txt b/libc/test/integration/src/sys/socket/CMakeLists.txt
new file mode 100644
index 00000000000000..b4bbe81c92ff2e
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
new file mode 100644
index 00000000000000..b31b01cce5dcb5
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
@@ -0,0 +1,24 @@
+add_custom_target(sys-socket-integration-tests)
+add_dependencies(libc-integration-tests sys-socket-integration-tests)
+
+
+add_integration_test(
+ socket_send_recv_test
+ SUITE
+ sys-socket-integration-tests
+ SRCS
+ socket_send_recv_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.send
+ libc.src.sys.socket.recv
+ libc.src.sys.socket.socket
+ libc.src.sys.socket.bind
+ libc.src.sys.socket.connect
+ libc.src.sys.socket.listen
+ libc.src.sys.socket.accept
+ libc.src.stdio.remove
+ libc.src.unistd.close
+ libc.src.unistd.fork
+)
diff --git a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
new file mode 100644
index 00000000000000..80e65e2290dacd
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
@@ -0,0 +1,138 @@
+//===-- Integration tests for socket functions ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/threads/sleep.h"
+
+#include "src/stdio/remove.h"
+#include "src/sys/socket/accept.h"
+#include "src/sys/socket/bind.h"
+#include "src/sys/socket/connect.h"
+#include "src/sys/socket/listen.h"
+#include "src/sys/socket/recv.h"
+#include "src/sys/socket/send.h"
+#include "src/sys/socket/socket.h"
+#include "src/unistd/close.h"
+#include "src/unistd/fork.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/IntegrationTest/test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+
+const char TEST_MESSAGE[] = "connection successful";
+const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+void run_client(const char *SOCK_PATH) {
+ constexpr size_t SPIN_TRIES = 100;
+ int result;
+
+ int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_NE(sock, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr_un my_addr;
+
+ my_addr.sun_family = AF_UNIX;
+ size_t i = 0;
+ for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
+ my_addr.sun_path[i] = SOCK_PATH[i];
+ my_addr.sun_path[i] = '\0';
+
+ // If the connection fails with "EAGAIN" then sleep breifly and try again, but
+ // only up to SPIN_TRIES times.
+ LIBC_NAMESPACE::libc_errno = EAGAIN;
+ for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
+ ++j, LIBC_NAMESPACE::sleep_briefly()) {
+ LIBC_NAMESPACE::libc_errno = 0;
+ result = LIBC_NAMESPACE::connect(
+ sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+ sizeof(my_addr.sun_path));
+ }
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ ssize_t send_result =
+ LIBC_NAMESPACE::send(sock, TEST_MESSAGE, MESSAGE_LEN, 0);
+
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::close(sock);
+}
+
+void run_server(const char *SOCK_PATH) {
+ int result;
+
+ int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_NE(sock, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr_un my_addr;
+
+ my_addr.sun_family = AF_UNIX;
+ size_t i = 0;
+ for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
+ my_addr.sun_path[i] = SOCK_PATH[i];
+ my_addr.sun_path[i] = '\0';
+
+ result =
+ LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+ sizeof(my_addr.sun_path));
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ result = LIBC_NAMESPACE::listen(sock, 1);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr connected_sock;
+ socklen_t sockaddr_len = sizeof(struct sockaddr);
+
+ int accepted_sock =
+ LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
+ ASSERT_NE(accepted_sock, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ char buffer[256];
+
+ ssize_t recv_result =
+ LIBC_NAMESPACE::recv(accepted_sock, buffer, sizeof(buffer), 0);
+ ASSERT_EQ(recv_result, MESSAGE_LEN);
+ ASSERT_ERRNO_SUCCESS();
+
+ for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+ ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+ }
+
+ LIBC_NAMESPACE::close(sock);
+}
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+
+ const char *FILENAME = "send_file.test";
+ // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+ auto SOCK_PATH = FILENAME;
+
+ // If the test fails, then the file for the socket may not be properly
+ // removed. This ensures a consistent start.
+ LIBC_NAMESPACE::remove(SOCK_PATH);
+ LIBC_NAMESPACE::libc_errno = 0;
+
+ // split into client and server processes.
+ pid_t pid = LIBC_NAMESPACE::fork();
+ ASSERT_NE(pid, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ if (pid == 0) { // child
+ run_client(SOCK_PATH);
+ } else { // parent
+ run_server(SOCK_PATH);
+ }
+
+ return 0;
+}
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index 32ae9d7481ed42..566233c2041780 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -27,22 +27,3 @@ add_libc_unittest(
libc.src.stdio.remove
libc.src.unistd.close
)
-
-add_libc_unittest(
- send_test
- SUITE
- libc_sys_socket_unittests
- SRCS
- send_test.cpp
- DEPENDS
- libc.include.sys_socket
- libc.src.errno.errno
- libc.src.sys.socket.send
- libc.src.sys.socket.socket
- libc.src.sys.socket.bind
- libc.src.sys.socket.connect
- libc.src.sys.socket.listen
- libc.src.sys.socket.accept
- libc.src.stdio.remove
- libc.src.unistd.close
-)
diff --git a/libc/test/src/sys/socket/linux/send_test.cpp b/libc/test/src/sys/socket/linux/send_test.cpp
deleted file mode 100644
index def46a0edcb277..00000000000000
--- a/libc/test/src/sys/socket/linux/send_test.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-//===-- Unittests for send ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "src/stdio/remove.h"
-#include "src/sys/socket/accept.h"
-#include "src/sys/socket/bind.h"
-#include "src/sys/socket/connect.h"
-#include "src/sys/socket/listen.h"
-#include "src/sys/socket/send.h"
-#include "src/sys/socket/socket.h"
-#include "src/unistd/close.h"
-
-#include "src/errno/libc_errno.h"
-#include "test/UnitTest/Test.h"
-
-#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
-
-TEST(LlvmLibcSocketTest, BindLocalSocket) {
-
- const char *FILENAME = "send_file.test";
- auto SOCK_PATH = libc_make_test_file_path(FILENAME);
-
- // if might exist if the test fails
- LIBC_NAMESPACE::remove(SOCK_PATH);
-
- int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_DGRAM, 0);
- ASSERT_GE(sock, 0);
- ASSERT_ERRNO_SUCCESS();
-
- struct sockaddr_un my_addr;
-
- my_addr.sun_family = AF_UNIX;
- unsigned int i = 0;
- for (;
- SOCK_PATH[i] != '\0' && (i < sizeof(sockaddr_un) - sizeof(sa_family_t));
- ++i)
- my_addr.sun_path[i] = SOCK_PATH[i];
- my_addr.sun_path[i] = '\0';
-
- // It's important that the path fits in the struct, if it doesn't then we
- // can't try to bind to the file.
- ASSERT_LT(
- i, static_cast<unsigned int>(sizeof(sockaddr_un) - sizeof(sa_family_t)));
-
- int result =
- LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
- sizeof(struct sockaddr_un));
-
- EXPECT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- struct sockaddr *connected_sock;
-
- // result = LIBC_NAMESPACE::connect(sock, connected_sock, socklen_t addrlen)
-
- const char TEST_MESSAGE[] = "connection successful";
- const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
-
- ssize_t send_result =
- LIBC_NAMESPACE::send(sock, TEST_MESSAGE, MESSAGE_LEN, 0);
-
- EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::close(sock);
-
- // LIBC_NAMESPACE::remove(SOCK_PATH);
-}
diff --git a/libc/test/src/sys/socket/linux/sendmsg_test.cpp b/libc/test/src/sys/socket/linux/sendmsg_test.cpp
deleted file mode 100644
index b00a271b5497a1..00000000000000
--- a/libc/test/src/sys/socket/linux/sendmsg_test.cpp
+++ /dev/null
@@ -1 +0,0 @@
-TODO: TESTS
diff --git a/libc/test/src/sys/socket/linux/sendto_test.cpp b/libc/test/src/sys/socket/linux/sendto_test.cpp
deleted file mode 100644
index b00a271b5497a1..00000000000000
--- a/libc/test/src/sys/socket/linux/sendto_test.cpp
+++ /dev/null
@@ -1 +0,0 @@
-TODO: TESTS
>From 13e2a7a3f2e2fc33ee9d3e8d298d99def2a146f4 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Thu, 12 Sep 2024 16:18:44 -0700
Subject: [PATCH 3/5] add msg tests, also add proxy headers
---
libc/hdr/types/CMakeLists.txt | 27 +++
libc/hdr/types/socklen_t.h | 21 +++
libc/hdr/types/ssize_t.h | 23 +++
libc/hdr/types/struct_msghdr.h | 21 +++
libc/hdr/types/struct_sockaddr.h | 21 +++
libc/include/llvm-libc-types/struct_iovec.h | 2 +-
libc/include/llvm-libc-types/struct_msghdr.h | 6 +-
libc/src/sys/socket/accept.h | 3 +-
libc/src/sys/socket/bind.h | 3 +-
libc/src/sys/socket/connect.h | 3 +-
libc/src/sys/socket/linux/CMakeLists.txt | 25 ++-
libc/src/sys/socket/linux/connect.cpp | 3 +-
libc/src/sys/socket/linux/recv.cpp | 4 +-
libc/src/sys/socket/linux/recvfrom.cpp | 4 +-
libc/src/sys/socket/linux/recvmsg.cpp | 3 +-
libc/src/sys/socket/linux/send.cpp | 4 +-
libc/src/sys/socket/linux/sendmsg.cpp | 3 +-
libc/src/sys/socket/linux/sendto.cpp | 4 +-
libc/src/sys/socket/recvfrom.h | 5 +-
libc/src/sys/socket/recvmsg.h | 3 +-
libc/src/sys/socket/sendmsg.h | 3 +-
libc/src/sys/socket/sendto.h | 5 +-
.../src/sys/socket/linux/CMakeLists.txt | 24 +++
.../socket/linux/socket_send_recv_test.cpp | 12 +-
.../linux/socket_sendmsg_recvmsg_test.cpp | 169 ++++++++++++++++++
25 files changed, 371 insertions(+), 30 deletions(-)
create mode 100644 libc/hdr/types/socklen_t.h
create mode 100644 libc/hdr/types/ssize_t.h
create mode 100644 libc/hdr/types/struct_msghdr.h
create mode 100644 libc/hdr/types/struct_sockaddr.h
create mode 100644 libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index f41576c07d99be..ff6842ae074e56 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -171,3 +171,30 @@ add_proxy_header_library(
libc.include.llvm-libc-types.locale_t
libc.include.locale
)
+
+add_proxy_header_library(
+ struct_msghdr
+ HDRS
+ struct_msghdr.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.struct_msghdr
+ libc.include.sys_socket
+)
+
+add_proxy_header_library(
+ struct_sockaddr
+ HDRS
+ struct_sockaddr.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.struct_sockaddr
+ libc.include.sys_socket
+)
+
+add_proxy_header_library(
+ socklen_t
+ HDRS
+ socklen_t.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.socklen_t
+ libc.include.sys_socket
+)
diff --git a/libc/hdr/types/socklen_t.h b/libc/hdr/types/socklen_t.h
new file mode 100644
index 00000000000000..79a6b9c7deadf0
--- /dev/null
+++ b/libc/hdr/types/socklen_t.h
@@ -0,0 +1,21 @@
+//===-- Proxy for socklen_t -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_HDR_TYPES_SOCKLEN_T_H
+#define LLVM_LIBC_HDR_TYPES_SOCKLEN_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/socklen_t.h"
+
+#else
+
+#include <signal.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_SOCKLEN_T_H
diff --git a/libc/hdr/types/ssize_t.h b/libc/hdr/types/ssize_t.h
new file mode 100644
index 00000000000000..4d2000780ee11f
--- /dev/null
+++ b/libc/hdr/types/ssize_t.h
@@ -0,0 +1,23 @@
+//===-- Proxy for ssize_t -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_HDR_TYPES_SSIZE_T_H
+#define LLVM_LIBC_HDR_TYPES_SSIZE_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/ssize_t.h"
+
+#else
+
+#define __need_ssize_t
+#include <stddef.h>
+#undef __need_ssize_t
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_SSIZE_T_H
diff --git a/libc/hdr/types/struct_msghdr.h b/libc/hdr/types/struct_msghdr.h
new file mode 100644
index 00000000000000..6a36af791e2147
--- /dev/null
+++ b/libc/hdr/types/struct_msghdr.h
@@ -0,0 +1,21 @@
+//===-- Proxy for struct msghdr ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_MSGHDR_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_MSGHDR_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_msghdr.h"
+
+#else
+
+#include <sys/socket.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_MSGHDR_H
diff --git a/libc/hdr/types/struct_sockaddr.h b/libc/hdr/types/struct_sockaddr.h
new file mode 100644
index 00000000000000..0fc31d53748540
--- /dev/null
+++ b/libc/hdr/types/struct_sockaddr.h
@@ -0,0 +1,21 @@
+//===-- Proxy for struct sockaddr ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_SOCKADDR_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_SOCKADDR_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_sockaddr.h"
+
+#else
+
+#include <sys/socket.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_SOCKADDR_H
diff --git a/libc/include/llvm-libc-types/struct_iovec.h b/libc/include/llvm-libc-types/struct_iovec.h
index 36e7bb79d0787f..4f889d3d038a11 100644
--- a/libc/include/llvm-libc-types/struct_iovec.h
+++ b/libc/include/llvm-libc-types/struct_iovec.h
@@ -9,7 +9,7 @@
#ifndef __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
#define __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
-#include <llvm-libc-types/size_t.h>
+#include "llvm-libc-types/size_t.h"
struct iovec {
void *iov_base;
diff --git a/libc/include/llvm-libc-types/struct_msghdr.h b/libc/include/llvm-libc-types/struct_msghdr.h
index 5af6d56218c0fc..afd37263fd22c1 100644
--- a/libc/include/llvm-libc-types/struct_msghdr.h
+++ b/libc/include/llvm-libc-types/struct_msghdr.h
@@ -9,9 +9,9 @@
#ifndef __LLVM_LIBC_TYPES_STRUCT_MSGHDR_H__
#define __LLVM_LIBC_TYPES_STRUCT_MSGHDR_H__
-#include <llvm-libc-types/size_t.h>
-#include <llvm-libc-types/socklen_t.h>
-#include <llvm-libc-types/struct_iovec.h>
+#include "llvm-libc-types/size_t.h"
+#include "llvm-libc-types/socklen_t.h"
+#include "llvm-libc-types/struct_iovec.h"
struct msghdr {
void *msg_name; /* Optional address */
diff --git a/libc/src/sys/socket/accept.h b/libc/src/sys/socket/accept.h
index c7cebc35e987cf..99789e3da70814 100644
--- a/libc/src/sys/socket/accept.h
+++ b/libc/src/sys/socket/accept.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
#define LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/macros/config.h"
-#include <sys/socket.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/bind.h b/libc/src/sys/socket/bind.h
index cec9c9da0c871e..619cd9f6594ec4 100644
--- a/libc/src/sys/socket/bind.h
+++ b/libc/src/sys/socket/bind.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_BIND_H
#define LLVM_LIBC_SRC_SYS_SOCKET_BIND_H
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/macros/config.h"
-#include <sys/socket.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/connect.h b/libc/src/sys/socket/connect.h
index 221f9a44cbaf9a..a91afb34589545 100644
--- a/libc/src/sys/socket/connect.h
+++ b/libc/src/sys/socket/connect.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
#define LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/macros/config.h"
-#include <sys/socket.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index 4a73f87fbd7bef..d0e77c85231091 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -19,7 +19,8 @@ add_entrypoint_object(
../bind.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_sockaddr
+ libc.hdr.types.socklen_t
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
@@ -32,7 +33,8 @@ add_entrypoint_object(
../send.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_sockaddr
+ libc.hdr.types.socklen_t
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
@@ -45,7 +47,8 @@ add_entrypoint_object(
../sendto.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_sockaddr
+ libc.hdr.types.socklen_t
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
@@ -58,7 +61,7 @@ add_entrypoint_object(
../sendmsg.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_msghdr
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
@@ -71,7 +74,8 @@ add_entrypoint_object(
../connect.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_sockaddr
+ libc.hdr.types.socklen_t
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
@@ -84,7 +88,8 @@ add_entrypoint_object(
../recv.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_sockaddr
+ libc.hdr.types.socklen_t
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
@@ -97,7 +102,8 @@ add_entrypoint_object(
../recvfrom.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_sockaddr
+ libc.hdr.types.socklen_t
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
@@ -110,7 +116,7 @@ add_entrypoint_object(
../recvmsg.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_msghdr
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
@@ -123,7 +129,8 @@ add_entrypoint_object(
../accept.h
DEPENDS
libc.include.sys_syscall
- libc.include.sys_socket
+ libc.hdr.types.struct_sockaddr
+ libc.hdr.types.socklen_t
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
diff --git a/libc/src/sys/socket/linux/connect.cpp b/libc/src/sys/socket/linux/connect.cpp
index eaf422613f5e62..93cb28ab95fc31 100644
--- a/libc/src/sys/socket/linux/connect.cpp
+++ b/libc/src/sys/socket/linux/connect.cpp
@@ -9,11 +9,12 @@
#include "src/sys/socket/connect.h"
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <linux/net.h> // For SYS_SOCKET socketcall number.
-#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/linux/recv.cpp b/libc/src/sys/socket/linux/recv.cpp
index afefac73f3db4a..96acf449dc4bfd 100644
--- a/libc/src/sys/socket/linux/recv.cpp
+++ b/libc/src/sys/socket/linux/recv.cpp
@@ -8,11 +8,13 @@
#include "src/sys/socket/recv.h"
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <linux/net.h> // For SYS_SOCKET socketcall number.
-#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/linux/recvfrom.cpp b/libc/src/sys/socket/linux/recvfrom.cpp
index 9b20982bb1fbf3..17489a99c922dc 100644
--- a/libc/src/sys/socket/linux/recvfrom.cpp
+++ b/libc/src/sys/socket/linux/recvfrom.cpp
@@ -8,11 +8,13 @@
#include "src/sys/socket/recvfrom.h"
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <linux/net.h> // For SYS_SOCKET socketcall number.
-#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/linux/recvmsg.cpp b/libc/src/sys/socket/linux/recvmsg.cpp
index 4a2f6fabbc2da1..60045d6a80f535 100644
--- a/libc/src/sys/socket/linux/recvmsg.cpp
+++ b/libc/src/sys/socket/linux/recvmsg.cpp
@@ -8,11 +8,12 @@
#include "src/sys/socket/recvmsg.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_msghdr.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <linux/net.h> // For SYS_SOCKET socketcall number.
-#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/linux/send.cpp b/libc/src/sys/socket/linux/send.cpp
index fc5305d5cdfa3d..0d29b6fd35b903 100644
--- a/libc/src/sys/socket/linux/send.cpp
+++ b/libc/src/sys/socket/linux/send.cpp
@@ -8,11 +8,13 @@
#include "src/sys/socket/send.h"
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <linux/net.h> // For SYS_SOCKET socketcall number.
-#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/linux/sendmsg.cpp b/libc/src/sys/socket/linux/sendmsg.cpp
index 822a26493dddb4..ba2b37768cc246 100644
--- a/libc/src/sys/socket/linux/sendmsg.cpp
+++ b/libc/src/sys/socket/linux/sendmsg.cpp
@@ -8,11 +8,12 @@
#include "src/sys/socket/sendmsg.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_msghdr.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <linux/net.h> // For SYS_SOCKET socketcall number.
-#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/linux/sendto.cpp b/libc/src/sys/socket/linux/sendto.cpp
index bc0769bc77d1d7..f5c3ffe8954da9 100644
--- a/libc/src/sys/socket/linux/sendto.cpp
+++ b/libc/src/sys/socket/linux/sendto.cpp
@@ -8,11 +8,13 @@
#include "src/sys/socket/sendto.h"
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include <linux/net.h> // For SYS_SOCKET socketcall number.
-#include <sys/socket.h> // For the types
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/recvfrom.h b/libc/src/sys/socket/recvfrom.h
index b1f36467bd574a..ee8d52157b705d 100644
--- a/libc/src/sys/socket/recvfrom.h
+++ b/libc/src/sys/socket/recvfrom.h
@@ -9,8 +9,11 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
#define LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/macros/config.h"
-#include <sys/socket.h>
+#include <stddef.h> // For size_t
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/recvmsg.h b/libc/src/sys/socket/recvmsg.h
index 0cffb7af7c3d7d..a506fb0ae68fa0 100644
--- a/libc/src/sys/socket/recvmsg.h
+++ b/libc/src/sys/socket/recvmsg.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
#define LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_msghdr.h"
#include "src/__support/macros/config.h"
-#include <sys/socket.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/sendmsg.h b/libc/src/sys/socket/sendmsg.h
index d902632eee0fa3..c11f3bd4beb596 100644
--- a/libc/src/sys/socket/sendmsg.h
+++ b/libc/src/sys/socket/sendmsg.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
#define LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_msghdr.h"
#include "src/__support/macros/config.h"
-#include <sys/socket.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/socket/sendto.h b/libc/src/sys/socket/sendto.h
index 8b56362b930c97..6e5e6d4cdab66f 100644
--- a/libc/src/sys/socket/sendto.h
+++ b/libc/src/sys/socket/sendto.h
@@ -9,8 +9,11 @@
#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
#define LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
#include "src/__support/macros/config.h"
-#include <sys/socket.h>
+#include <stddef.h> // For size_t
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
index b31b01cce5dcb5..977f895c609fc1 100644
--- a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
@@ -19,6 +19,30 @@ add_integration_test(
libc.src.sys.socket.listen
libc.src.sys.socket.accept
libc.src.stdio.remove
+ libc.src.stdio.puts
+ libc.src.unistd.close
+ libc.src.unistd.fork
+)
+
+
+add_integration_test(
+ socket_sendmsg_recvmsg_test
+ SUITE
+ sys-socket-integration-tests
+ SRCS
+ socket_sendmsg_recvmsg_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.sendmsg
+ libc.src.sys.socket.recvmsg
+ libc.src.sys.socket.socket
+ libc.src.sys.socket.bind
+ libc.src.sys.socket.connect
+ libc.src.sys.socket.listen
+ libc.src.sys.socket.accept
+ libc.src.stdio.remove
+ libc.src.stdio.puts
libc.src.unistd.close
libc.src.unistd.fork
)
diff --git a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
index 80e65e2290dacd..459738459fbf8a 100644
--- a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
+++ b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
@@ -8,6 +8,7 @@
#include "src/__support/threads/sleep.h"
+#include "src/stdio/puts.h"
#include "src/stdio/remove.h"
#include "src/sys/socket/accept.h"
#include "src/sys/socket/bind.h"
@@ -22,13 +23,13 @@
#include "src/errno/libc_errno.h"
#include "test/IntegrationTest/test.h"
-#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
const char TEST_MESSAGE[] = "connection successful";
const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
void run_client(const char *SOCK_PATH) {
- constexpr size_t SPIN_TRIES = 100;
+ constexpr size_t SPIN_TRIES = 1000;
int result;
int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
@@ -123,16 +124,21 @@ TEST_MAIN(int argc, char **argv, char **envp) {
LIBC_NAMESPACE::remove(SOCK_PATH);
LIBC_NAMESPACE::libc_errno = 0;
+ LIBC_NAMESPACE::puts("Send/Recv Test Start");
+
// split into client and server processes.
pid_t pid = LIBC_NAMESPACE::fork();
ASSERT_NE(pid, -1);
ASSERT_ERRNO_SUCCESS();
if (pid == 0) { // child
+ LIBC_NAMESPACE::puts("Send/Recv Child Start");
run_client(SOCK_PATH);
+ LIBC_NAMESPACE::puts("Send/Recv Child End");
} else { // parent
+ LIBC_NAMESPACE::puts("Send/Recv Parent Start");
run_server(SOCK_PATH);
+ LIBC_NAMESPACE::puts("Send/Recv Parent End");
}
-
return 0;
}
diff --git a/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
new file mode 100644
index 00000000000000..7dc0413f8ff157
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
@@ -0,0 +1,169 @@
+//===-- Integration tests for socket functions ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/threads/sleep.h"
+
+#include "src/stdio/puts.h"
+#include "src/stdio/remove.h"
+#include "src/sys/socket/accept.h"
+#include "src/sys/socket/bind.h"
+#include "src/sys/socket/connect.h"
+#include "src/sys/socket/listen.h"
+#include "src/sys/socket/recvmsg.h"
+#include "src/sys/socket/sendmsg.h"
+#include "src/sys/socket/socket.h"
+#include "src/unistd/close.h"
+#include "src/unistd/fork.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/IntegrationTest/test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
+
+const char TEST_MESSAGE[] = "connection successful";
+const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+void run_client(const char *SOCK_PATH) {
+ constexpr size_t SPIN_TRIES = 1000;
+ int result;
+
+ int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_NE(sock, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr_un my_addr;
+
+ my_addr.sun_family = AF_UNIX;
+ size_t i = 0;
+ for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
+ my_addr.sun_path[i] = SOCK_PATH[i];
+ my_addr.sun_path[i] = '\0';
+
+ // If the connection fails with "EAGAIN" then sleep breifly and try again, but
+ // only up to SPIN_TRIES times.
+ LIBC_NAMESPACE::libc_errno = EAGAIN;
+ for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
+ ++j, LIBC_NAMESPACE::sleep_briefly()) {
+ LIBC_NAMESPACE::libc_errno = 0;
+ result = LIBC_NAMESPACE::connect(
+ sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+ sizeof(my_addr.sun_path));
+ }
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ iovec msg_text;
+ msg_text.iov_base =
+ reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
+ msg_text.iov_len = MESSAGE_LEN;
+
+ msghdr message;
+ message.msg_name = nullptr;
+ message.msg_namelen = 0;
+ message.msg_iov = &msg_text;
+ message.msg_iovlen = 1;
+ message.msg_control = nullptr;
+ message.msg_controllen = 0;
+ message.msg_flags = 0;
+
+ ssize_t send_result = LIBC_NAMESPACE::sendmsg(sock, &message, 0);
+
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::close(sock);
+}
+
+void run_server(const char *SOCK_PATH) {
+ int result;
+
+ int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_NE(sock, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr_un my_addr;
+
+ my_addr.sun_family = AF_UNIX;
+ size_t i = 0;
+ for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
+ my_addr.sun_path[i] = SOCK_PATH[i];
+ my_addr.sun_path[i] = '\0';
+
+ result =
+ LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+ sizeof(my_addr.sun_path));
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ result = LIBC_NAMESPACE::listen(sock, 1);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr connected_sock;
+ socklen_t sockaddr_len = sizeof(struct sockaddr);
+
+ int accepted_sock =
+ LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
+ ASSERT_NE(accepted_sock, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ char buffer[256];
+
+ iovec msg_text;
+ msg_text.iov_base = reinterpret_cast<void *>(buffer);
+ msg_text.iov_len = sizeof(buffer);
+
+ msghdr message;
+ message.msg_name = nullptr;
+ message.msg_namelen = 0;
+ message.msg_iov = &msg_text;
+ message.msg_iovlen = 1;
+ message.msg_control = nullptr;
+ message.msg_controllen = 0;
+ message.msg_flags = 0;
+
+ ssize_t recv_result = LIBC_NAMESPACE::recvmsg(accepted_sock, &message, 0);
+ ASSERT_EQ(recv_result, MESSAGE_LEN);
+ ASSERT_ERRNO_SUCCESS();
+
+ for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+ ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+ }
+
+ LIBC_NAMESPACE::close(sock);
+}
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+
+ const char *FILENAME = "sendmsg_file.test";
+ // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+ auto SOCK_PATH = FILENAME;
+
+ // If the test fails, then the file for the socket may not be properly
+ // removed. This ensures a consistent start.
+ LIBC_NAMESPACE::remove(SOCK_PATH);
+ LIBC_NAMESPACE::libc_errno = 0;
+
+ LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Test Start");
+
+ // split into client and server processes.
+ pid_t pid = LIBC_NAMESPACE::fork();
+ ASSERT_NE(pid, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ if (pid == 0) { // child
+ LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Child Start");
+ run_client(SOCK_PATH);
+ LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Child End");
+ } else { // parent
+ LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Parent Start");
+ run_server(SOCK_PATH);
+ LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Parent End");
+ }
+ return 0;
+}
>From df5c60ae337f9b2623c636a84054dbb42c851a50 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Tue, 17 Sep 2024 11:05:48 -0700
Subject: [PATCH 4/5] move to socketpair to simplify parallelism
---
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/src/sys/socket/CMakeLists.txt | 7 +
libc/src/sys/socket/linux/CMakeLists.txt | 13 ++
libc/src/sys/socket/linux/socketpair.cpp | 43 ++++
libc/src/sys/socket/socketpair.h | 20 ++
.../src/sys/socket/linux/CMakeLists.txt | 29 ++-
.../socket/linux/socket_send_recv_test.cpp | 131 ++++---------
.../linux/socket_sendmsg_recvmsg_test.cpp | 183 ++++++------------
.../linux/socket_sendto_recvfrom_test.cpp | 84 ++++++++
9 files changed, 283 insertions(+), 228 deletions(-)
create mode 100644 libc/src/sys/socket/linux/socketpair.cpp
create mode 100644 libc/src/sys/socket/socketpair.h
create mode 100644 libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index d7220131046008..7e47920245f87a 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1027,6 +1027,7 @@ if(LLVM_LIBC_FULL_BUILD)
# sys/socket.h entrypoints
libc.src.sys.socket.socket
+ libc.src.sys.socket.socketpair
libc.src.sys.socket.bind
libc.src.sys.socket.send
libc.src.sys.socket.sendto
diff --git a/libc/src/sys/socket/CMakeLists.txt b/libc/src/sys/socket/CMakeLists.txt
index cd877b923f9f37..7a2572fa2781b0 100644
--- a/libc/src/sys/socket/CMakeLists.txt
+++ b/libc/src/sys/socket/CMakeLists.txt
@@ -9,6 +9,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.socket
)
+add_entrypoint_object(
+ socketpair
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.socketpair
+)
+
add_entrypoint_object(
bind
ALIAS
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index d0e77c85231091..97d4481fec3da1 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -11,6 +11,19 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ socketpair
+ SRCS
+ socketpair.cpp
+ HDRS
+ ../socketpair.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
bind
SRCS
diff --git a/libc/src/sys/socket/linux/socketpair.cpp b/libc/src/sys/socket/linux/socketpair.cpp
new file mode 100644
index 00000000000000..d459a74433906d
--- /dev/null
+++ b/libc/src/sys/socket/linux/socketpair.cpp
@@ -0,0 +1,43 @@
+//===-- Linux implementation of socketpair --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/socketpair.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/__support/macros/config.h"
+#include "src/errno/libc_errno.h"
+
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, socketpair,
+ (int domain, int type, int protocol, int sv[2])) {
+#ifdef SYS_socketpair
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketpair, domain, type,
+ protocol, sv);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[3] = {
+ static_cast<unsigned long>(domain), static_cast<unsigned long>(type),
+ static_cast<unsigned long>(protocol), static_cast<unsigned long>(sv)};
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SOCKETPAIR,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/socketpair.h b/libc/src/sys/socket/socketpair.h
new file mode 100644
index 00000000000000..1d847c3284708b
--- /dev/null
+++ b/libc/src/sys/socket/socketpair.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for socketpair --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SOCKETPAIR_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SOCKETPAIR_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int socketpair(int domain, int type, int protocol, int sv[2]);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SOCKETPAIR_H
diff --git a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
index 977f895c609fc1..684ad2d48d163f 100644
--- a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
@@ -13,17 +13,30 @@ add_integration_test(
libc.src.errno.errno
libc.src.sys.socket.send
libc.src.sys.socket.recv
- libc.src.sys.socket.socket
- libc.src.sys.socket.bind
- libc.src.sys.socket.connect
- libc.src.sys.socket.listen
- libc.src.sys.socket.accept
+ libc.src.sys.socket.socketpair
libc.src.stdio.remove
libc.src.stdio.puts
libc.src.unistd.close
libc.src.unistd.fork
)
+add_integration_test(
+ socket_sendto_recvfrom_test
+ SUITE
+ sys-socket-integration-tests
+ SRCS
+ socket_sendto_recvfrom_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.sendto
+ libc.src.sys.socket.recvfrom
+ libc.src.sys.socket.socketpair
+ libc.src.stdio.remove
+ libc.src.stdio.puts
+ libc.src.unistd.close
+ libc.src.unistd.fork
+)
add_integration_test(
socket_sendmsg_recvmsg_test
@@ -36,11 +49,7 @@ add_integration_test(
libc.src.errno.errno
libc.src.sys.socket.sendmsg
libc.src.sys.socket.recvmsg
- libc.src.sys.socket.socket
- libc.src.sys.socket.bind
- libc.src.sys.socket.connect
- libc.src.sys.socket.listen
- libc.src.sys.socket.accept
+ libc.src.sys.socket.socketpair
libc.src.stdio.remove
libc.src.stdio.puts
libc.src.unistd.close
diff --git a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
index 459738459fbf8a..25056bf589bace 100644
--- a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
+++ b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
@@ -10,13 +10,9 @@
#include "src/stdio/puts.h"
#include "src/stdio/remove.h"
-#include "src/sys/socket/accept.h"
-#include "src/sys/socket/bind.h"
-#include "src/sys/socket/connect.h"
-#include "src/sys/socket/listen.h"
#include "src/sys/socket/recv.h"
#include "src/sys/socket/send.h"
-#include "src/sys/socket/socket.h"
+#include "src/sys/socket/socketpair.h"
#include "src/unistd/close.h"
#include "src/unistd/fork.h"
@@ -28,90 +24,7 @@
const char TEST_MESSAGE[] = "connection successful";
const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
-void run_client(const char *SOCK_PATH) {
- constexpr size_t SPIN_TRIES = 1000;
- int result;
-
- int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
- ASSERT_NE(sock, -1);
- ASSERT_ERRNO_SUCCESS();
-
- struct sockaddr_un my_addr;
-
- my_addr.sun_family = AF_UNIX;
- size_t i = 0;
- for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
- my_addr.sun_path[i] = SOCK_PATH[i];
- my_addr.sun_path[i] = '\0';
-
- // If the connection fails with "EAGAIN" then sleep breifly and try again, but
- // only up to SPIN_TRIES times.
- LIBC_NAMESPACE::libc_errno = EAGAIN;
- for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
- ++j, LIBC_NAMESPACE::sleep_briefly()) {
- LIBC_NAMESPACE::libc_errno = 0;
- result = LIBC_NAMESPACE::connect(
- sock, reinterpret_cast<struct sockaddr *>(&my_addr),
- sizeof(my_addr.sun_path));
- }
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- ssize_t send_result =
- LIBC_NAMESPACE::send(sock, TEST_MESSAGE, MESSAGE_LEN, 0);
-
- EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::close(sock);
-}
-
-void run_server(const char *SOCK_PATH) {
- int result;
-
- int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
- ASSERT_NE(sock, -1);
- ASSERT_ERRNO_SUCCESS();
-
- struct sockaddr_un my_addr;
-
- my_addr.sun_family = AF_UNIX;
- size_t i = 0;
- for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
- my_addr.sun_path[i] = SOCK_PATH[i];
- my_addr.sun_path[i] = '\0';
-
- result =
- LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
- sizeof(my_addr.sun_path));
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- result = LIBC_NAMESPACE::listen(sock, 1);
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- struct sockaddr connected_sock;
- socklen_t sockaddr_len = sizeof(struct sockaddr);
-
- int accepted_sock =
- LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
- ASSERT_NE(accepted_sock, -1);
- ASSERT_ERRNO_SUCCESS();
-
- char buffer[256];
-
- ssize_t recv_result =
- LIBC_NAMESPACE::recv(accepted_sock, buffer, sizeof(buffer), 0);
- ASSERT_EQ(recv_result, MESSAGE_LEN);
- ASSERT_ERRNO_SUCCESS();
-
- for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
- ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
- }
-
- LIBC_NAMESPACE::close(sock);
-}
+#define SEND_TEST_NAME "Send/Recv"
TEST_MAIN(int argc, char **argv, char **envp) {
@@ -124,7 +37,13 @@ TEST_MAIN(int argc, char **argv, char **envp) {
LIBC_NAMESPACE::remove(SOCK_PATH);
LIBC_NAMESPACE::libc_errno = 0;
- LIBC_NAMESPACE::puts("Send/Recv Test Start");
+ int sockpair[2] = {0, 0};
+
+ int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
// split into client and server processes.
pid_t pid = LIBC_NAMESPACE::fork();
@@ -132,13 +51,33 @@ TEST_MAIN(int argc, char **argv, char **envp) {
ASSERT_ERRNO_SUCCESS();
if (pid == 0) { // child
- LIBC_NAMESPACE::puts("Send/Recv Child Start");
- run_client(SOCK_PATH);
- LIBC_NAMESPACE::puts("Send/Recv Child End");
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
+ LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+
+ ssize_t send_result =
+ LIBC_NAMESPACE::send(sockpair[0], TEST_MESSAGE, MESSAGE_LEN, 0);
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
} else { // parent
- LIBC_NAMESPACE::puts("Send/Recv Parent Start");
- run_server(SOCK_PATH);
- LIBC_NAMESPACE::puts("Send/Recv Parent End");
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
+ LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+
+ char buffer[256];
+
+ ssize_t recv_result =
+ LIBC_NAMESPACE::recv(sockpair[1], buffer, sizeof(buffer), 0);
+ ASSERT_EQ(recv_result, MESSAGE_LEN);
+ ASSERT_ERRNO_SUCCESS();
+
+ for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+ ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+ }
+
+ LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
}
return 0;
}
diff --git a/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
index 7dc0413f8ff157..97af9c160bc7a7 100644
--- a/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
+++ b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
@@ -10,13 +10,9 @@
#include "src/stdio/puts.h"
#include "src/stdio/remove.h"
-#include "src/sys/socket/accept.h"
-#include "src/sys/socket/bind.h"
-#include "src/sys/socket/connect.h"
-#include "src/sys/socket/listen.h"
#include "src/sys/socket/recvmsg.h"
#include "src/sys/socket/sendmsg.h"
-#include "src/sys/socket/socket.h"
+#include "src/sys/socket/socketpair.h"
#include "src/unistd/close.h"
#include "src/unistd/fork.h"
@@ -28,119 +24,11 @@
const char TEST_MESSAGE[] = "connection successful";
const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
-void run_client(const char *SOCK_PATH) {
- constexpr size_t SPIN_TRIES = 1000;
- int result;
-
- int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
- ASSERT_NE(sock, -1);
- ASSERT_ERRNO_SUCCESS();
-
- struct sockaddr_un my_addr;
-
- my_addr.sun_family = AF_UNIX;
- size_t i = 0;
- for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
- my_addr.sun_path[i] = SOCK_PATH[i];
- my_addr.sun_path[i] = '\0';
-
- // If the connection fails with "EAGAIN" then sleep breifly and try again, but
- // only up to SPIN_TRIES times.
- LIBC_NAMESPACE::libc_errno = EAGAIN;
- for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
- ++j, LIBC_NAMESPACE::sleep_briefly()) {
- LIBC_NAMESPACE::libc_errno = 0;
- result = LIBC_NAMESPACE::connect(
- sock, reinterpret_cast<struct sockaddr *>(&my_addr),
- sizeof(my_addr.sun_path));
- }
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- iovec msg_text;
- msg_text.iov_base =
- reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
- msg_text.iov_len = MESSAGE_LEN;
-
- msghdr message;
- message.msg_name = nullptr;
- message.msg_namelen = 0;
- message.msg_iov = &msg_text;
- message.msg_iovlen = 1;
- message.msg_control = nullptr;
- message.msg_controllen = 0;
- message.msg_flags = 0;
-
- ssize_t send_result = LIBC_NAMESPACE::sendmsg(sock, &message, 0);
-
- EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::close(sock);
-}
-
-void run_server(const char *SOCK_PATH) {
- int result;
-
- int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
- ASSERT_NE(sock, -1);
- ASSERT_ERRNO_SUCCESS();
-
- struct sockaddr_un my_addr;
-
- my_addr.sun_family = AF_UNIX;
- size_t i = 0;
- for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
- my_addr.sun_path[i] = SOCK_PATH[i];
- my_addr.sun_path[i] = '\0';
-
- result =
- LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
- sizeof(my_addr.sun_path));
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- result = LIBC_NAMESPACE::listen(sock, 1);
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- struct sockaddr connected_sock;
- socklen_t sockaddr_len = sizeof(struct sockaddr);
-
- int accepted_sock =
- LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
- ASSERT_NE(accepted_sock, -1);
- ASSERT_ERRNO_SUCCESS();
-
- char buffer[256];
-
- iovec msg_text;
- msg_text.iov_base = reinterpret_cast<void *>(buffer);
- msg_text.iov_len = sizeof(buffer);
-
- msghdr message;
- message.msg_name = nullptr;
- message.msg_namelen = 0;
- message.msg_iov = &msg_text;
- message.msg_iovlen = 1;
- message.msg_control = nullptr;
- message.msg_controllen = 0;
- message.msg_flags = 0;
-
- ssize_t recv_result = LIBC_NAMESPACE::recvmsg(accepted_sock, &message, 0);
- ASSERT_EQ(recv_result, MESSAGE_LEN);
- ASSERT_ERRNO_SUCCESS();
-
- for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
- ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
- }
-
- LIBC_NAMESPACE::close(sock);
-}
+#define SEND_TEST_NAME "Sendmsg/Recvmsg"
TEST_MAIN(int argc, char **argv, char **envp) {
- const char *FILENAME = "sendmsg_file.test";
+ const char *FILENAME = "send_file.test";
// auto SOCK_PATH = libc_make_test_file_path(FILENAME);
auto SOCK_PATH = FILENAME;
@@ -149,7 +37,13 @@ TEST_MAIN(int argc, char **argv, char **envp) {
LIBC_NAMESPACE::remove(SOCK_PATH);
LIBC_NAMESPACE::libc_errno = 0;
- LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Test Start");
+ int sockpair[2] = {0, 0};
+
+ int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
// split into client and server processes.
pid_t pid = LIBC_NAMESPACE::fork();
@@ -157,13 +51,58 @@ TEST_MAIN(int argc, char **argv, char **envp) {
ASSERT_ERRNO_SUCCESS();
if (pid == 0) { // child
- LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Child Start");
- run_client(SOCK_PATH);
- LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Child End");
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
+ LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+
+ iovec msg_text;
+ msg_text.iov_base =
+ reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
+ msg_text.iov_len = MESSAGE_LEN;
+
+ msghdr message;
+ message.msg_name = nullptr;
+ message.msg_namelen = 0;
+ message.msg_iov = &msg_text;
+ message.msg_iovlen = 1;
+ message.msg_control = nullptr;
+ message.msg_controllen = 0;
+ message.msg_flags = 0;
+
+ ssize_t send_result = LIBC_NAMESPACE::sendmsg(sockpair[0], &message, 0);
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
} else { // parent
- LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Parent Start");
- run_server(SOCK_PATH);
- LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Parent End");
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
+ LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+
+ char buffer[256];
+
+ iovec msg_text;
+ msg_text.iov_base = reinterpret_cast<void *>(buffer);
+ msg_text.iov_len = sizeof(buffer);
+
+ msghdr message;
+ message.msg_name = nullptr;
+ message.msg_namelen = 0;
+ message.msg_iov = &msg_text;
+ message.msg_iovlen = 1;
+ message.msg_control = nullptr;
+ message.msg_controllen = 0;
+ message.msg_flags = 0;
+
+ ssize_t recv_result = LIBC_NAMESPACE::recvmsg(sockpair[1], &message, 0);
+ ASSERT_EQ(recv_result, MESSAGE_LEN);
+ ASSERT_ERRNO_SUCCESS();
+
+ for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+ ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+ }
+
+ LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
}
return 0;
}
diff --git a/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp
new file mode 100644
index 00000000000000..0a0904ffcd5483
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp
@@ -0,0 +1,84 @@
+//===-- Integration tests for socket functions ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/threads/sleep.h"
+
+#include "src/stdio/puts.h"
+#include "src/stdio/remove.h"
+#include "src/sys/socket/recvfrom.h"
+#include "src/sys/socket/sendto.h"
+#include "src/sys/socket/socketpair.h"
+#include "src/unistd/close.h"
+#include "src/unistd/fork.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/IntegrationTest/test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
+
+const char TEST_MESSAGE[] = "connection successful";
+const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+// macro for easy string pasting, we don't need printf here
+#define SEND_TEST_NAME "Sendto/Recvfrom"
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+
+ const char *FILENAME = "send_file.test";
+ // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+ auto SOCK_PATH = FILENAME;
+
+ // If the test fails, then the file for the socket may not be properly
+ // removed. This ensures a consistent start.
+ LIBC_NAMESPACE::remove(SOCK_PATH);
+ LIBC_NAMESPACE::libc_errno = 0;
+
+ int sockpair[2] = {0, 0};
+
+ int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
+
+ // split into client and server processes.
+ pid_t pid = LIBC_NAMESPACE::fork();
+ ASSERT_NE(pid, -1);
+ ASSERT_ERRNO_SUCCESS();
+
+ if (pid == 0) { // child
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
+ LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+
+ ssize_t send_result = LIBC_NAMESPACE::sendto(sockpair[0], TEST_MESSAGE,
+ MESSAGE_LEN, 0, nullptr, 0);
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
+ } else { // parent
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
+ LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+
+ char buffer[256];
+
+ ssize_t recv_result = LIBC_NAMESPACE::recvfrom(
+ sockpair[1], buffer, sizeof(buffer), 0, nullptr, 0);
+ ASSERT_EQ(recv_result, MESSAGE_LEN);
+ ASSERT_ERRNO_SUCCESS();
+
+ for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+ ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+ }
+
+ LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+ LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
+ }
+ return 0;
+}
>From 5d947861b90d6077ab7a389f7c6eef3502df13be Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Tue, 17 Sep 2024 11:29:37 -0700
Subject: [PATCH 5/5] move back to unittests since socketpair doesn't need
threads
---
libc/test/integration/src/CMakeLists.txt | 1 -
libc/test/integration/src/sys/CMakeLists.txt | 1 -
.../integration/src/sys/socket/CMakeLists.txt | 3 -
.../src/sys/socket/linux/CMakeLists.txt | 57 --------
.../socket/linux/socket_send_recv_test.cpp | 83 ------------
.../linux/socket_sendmsg_recvmsg_test.cpp | 108 ---------------
.../linux/socket_sendto_recvfrom_test.cpp | 84 ------------
libc/test/src/sys/socket/linux/CMakeLists.txt | 45 +++++++
.../src/sys/socket/linux/send_recv_test.cpp | 73 ++++++++++
.../sys/socket/linux/sendmsg_recvmsg_test.cpp | 125 ++++++++++++++++++
.../sys/socket/linux/sendto_recvfrom_test.cpp | 75 +++++++++++
11 files changed, 318 insertions(+), 337 deletions(-)
delete mode 100644 libc/test/integration/src/sys/CMakeLists.txt
delete mode 100644 libc/test/integration/src/sys/socket/CMakeLists.txt
delete mode 100644 libc/test/integration/src/sys/socket/linux/CMakeLists.txt
delete mode 100644 libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
delete mode 100644 libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
delete mode 100644 libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp
create mode 100644 libc/test/src/sys/socket/linux/send_recv_test.cpp
create mode 100644 libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp
create mode 100644 libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp
diff --git a/libc/test/integration/src/CMakeLists.txt b/libc/test/integration/src/CMakeLists.txt
index 7c97c68d2a7d15..1104b3de99e9b7 100644
--- a/libc/test/integration/src/CMakeLists.txt
+++ b/libc/test/integration/src/CMakeLists.txt
@@ -5,4 +5,3 @@ add_subdirectory(stdio)
add_subdirectory(stdlib)
add_subdirectory(threads)
add_subdirectory(unistd)
-add_subdirectory(sys)
diff --git a/libc/test/integration/src/sys/CMakeLists.txt b/libc/test/integration/src/sys/CMakeLists.txt
deleted file mode 100644
index 5a3c0f8150c7ee..00000000000000
--- a/libc/test/integration/src/sys/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-add_subdirectory(socket)
diff --git a/libc/test/integration/src/sys/socket/CMakeLists.txt b/libc/test/integration/src/sys/socket/CMakeLists.txt
deleted file mode 100644
index b4bbe81c92ff2e..00000000000000
--- a/libc/test/integration/src/sys/socket/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
- add_subdirectory(${LIBC_TARGET_OS})
-endif()
diff --git a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
deleted file mode 100644
index 684ad2d48d163f..00000000000000
--- a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-add_custom_target(sys-socket-integration-tests)
-add_dependencies(libc-integration-tests sys-socket-integration-tests)
-
-
-add_integration_test(
- socket_send_recv_test
- SUITE
- sys-socket-integration-tests
- SRCS
- socket_send_recv_test.cpp
- DEPENDS
- libc.include.sys_socket
- libc.src.errno.errno
- libc.src.sys.socket.send
- libc.src.sys.socket.recv
- libc.src.sys.socket.socketpair
- libc.src.stdio.remove
- libc.src.stdio.puts
- libc.src.unistd.close
- libc.src.unistd.fork
-)
-
-add_integration_test(
- socket_sendto_recvfrom_test
- SUITE
- sys-socket-integration-tests
- SRCS
- socket_sendto_recvfrom_test.cpp
- DEPENDS
- libc.include.sys_socket
- libc.src.errno.errno
- libc.src.sys.socket.sendto
- libc.src.sys.socket.recvfrom
- libc.src.sys.socket.socketpair
- libc.src.stdio.remove
- libc.src.stdio.puts
- libc.src.unistd.close
- libc.src.unistd.fork
-)
-
-add_integration_test(
- socket_sendmsg_recvmsg_test
- SUITE
- sys-socket-integration-tests
- SRCS
- socket_sendmsg_recvmsg_test.cpp
- DEPENDS
- libc.include.sys_socket
- libc.src.errno.errno
- libc.src.sys.socket.sendmsg
- libc.src.sys.socket.recvmsg
- libc.src.sys.socket.socketpair
- libc.src.stdio.remove
- libc.src.stdio.puts
- libc.src.unistd.close
- libc.src.unistd.fork
-)
diff --git a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
deleted file mode 100644
index 25056bf589bace..00000000000000
--- a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//===-- Integration tests for socket functions ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "src/__support/threads/sleep.h"
-
-#include "src/stdio/puts.h"
-#include "src/stdio/remove.h"
-#include "src/sys/socket/recv.h"
-#include "src/sys/socket/send.h"
-#include "src/sys/socket/socketpair.h"
-#include "src/unistd/close.h"
-#include "src/unistd/fork.h"
-
-#include "src/errno/libc_errno.h"
-#include "test/IntegrationTest/test.h"
-
-#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
-
-const char TEST_MESSAGE[] = "connection successful";
-const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
-
-#define SEND_TEST_NAME "Send/Recv"
-
-TEST_MAIN(int argc, char **argv, char **envp) {
-
- const char *FILENAME = "send_file.test";
- // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
- auto SOCK_PATH = FILENAME;
-
- // If the test fails, then the file for the socket may not be properly
- // removed. This ensures a consistent start.
- LIBC_NAMESPACE::remove(SOCK_PATH);
- LIBC_NAMESPACE::libc_errno = 0;
-
- int sockpair[2] = {0, 0};
-
- int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
-
- // split into client and server processes.
- pid_t pid = LIBC_NAMESPACE::fork();
- ASSERT_NE(pid, -1);
- ASSERT_ERRNO_SUCCESS();
-
- if (pid == 0) { // child
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
- LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
-
- ssize_t send_result =
- LIBC_NAMESPACE::send(sockpair[0], TEST_MESSAGE, MESSAGE_LEN, 0);
- EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::close(sockpair[0]); // close child sock
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
- } else { // parent
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
- LIBC_NAMESPACE::close(sockpair[0]); // close child sock
-
- char buffer[256];
-
- ssize_t recv_result =
- LIBC_NAMESPACE::recv(sockpair[1], buffer, sizeof(buffer), 0);
- ASSERT_EQ(recv_result, MESSAGE_LEN);
- ASSERT_ERRNO_SUCCESS();
-
- for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
- ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
- }
-
- LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
- }
- return 0;
-}
diff --git a/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
deleted file mode 100644
index 97af9c160bc7a7..00000000000000
--- a/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-//===-- Integration tests for socket functions ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "src/__support/threads/sleep.h"
-
-#include "src/stdio/puts.h"
-#include "src/stdio/remove.h"
-#include "src/sys/socket/recvmsg.h"
-#include "src/sys/socket/sendmsg.h"
-#include "src/sys/socket/socketpair.h"
-#include "src/unistd/close.h"
-#include "src/unistd/fork.h"
-
-#include "src/errno/libc_errno.h"
-#include "test/IntegrationTest/test.h"
-
-#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
-
-const char TEST_MESSAGE[] = "connection successful";
-const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
-
-#define SEND_TEST_NAME "Sendmsg/Recvmsg"
-
-TEST_MAIN(int argc, char **argv, char **envp) {
-
- const char *FILENAME = "send_file.test";
- // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
- auto SOCK_PATH = FILENAME;
-
- // If the test fails, then the file for the socket may not be properly
- // removed. This ensures a consistent start.
- LIBC_NAMESPACE::remove(SOCK_PATH);
- LIBC_NAMESPACE::libc_errno = 0;
-
- int sockpair[2] = {0, 0};
-
- int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
-
- // split into client and server processes.
- pid_t pid = LIBC_NAMESPACE::fork();
- ASSERT_NE(pid, -1);
- ASSERT_ERRNO_SUCCESS();
-
- if (pid == 0) { // child
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
- LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
-
- iovec msg_text;
- msg_text.iov_base =
- reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
- msg_text.iov_len = MESSAGE_LEN;
-
- msghdr message;
- message.msg_name = nullptr;
- message.msg_namelen = 0;
- message.msg_iov = &msg_text;
- message.msg_iovlen = 1;
- message.msg_control = nullptr;
- message.msg_controllen = 0;
- message.msg_flags = 0;
-
- ssize_t send_result = LIBC_NAMESPACE::sendmsg(sockpair[0], &message, 0);
- EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::close(sockpair[0]); // close child sock
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
- } else { // parent
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
- LIBC_NAMESPACE::close(sockpair[0]); // close child sock
-
- char buffer[256];
-
- iovec msg_text;
- msg_text.iov_base = reinterpret_cast<void *>(buffer);
- msg_text.iov_len = sizeof(buffer);
-
- msghdr message;
- message.msg_name = nullptr;
- message.msg_namelen = 0;
- message.msg_iov = &msg_text;
- message.msg_iovlen = 1;
- message.msg_control = nullptr;
- message.msg_controllen = 0;
- message.msg_flags = 0;
-
- ssize_t recv_result = LIBC_NAMESPACE::recvmsg(sockpair[1], &message, 0);
- ASSERT_EQ(recv_result, MESSAGE_LEN);
- ASSERT_ERRNO_SUCCESS();
-
- for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
- ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
- }
-
- LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
- }
- return 0;
-}
diff --git a/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp
deleted file mode 100644
index 0a0904ffcd5483..00000000000000
--- a/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-//===-- Integration tests for socket functions ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "src/__support/threads/sleep.h"
-
-#include "src/stdio/puts.h"
-#include "src/stdio/remove.h"
-#include "src/sys/socket/recvfrom.h"
-#include "src/sys/socket/sendto.h"
-#include "src/sys/socket/socketpair.h"
-#include "src/unistd/close.h"
-#include "src/unistd/fork.h"
-
-#include "src/errno/libc_errno.h"
-#include "test/IntegrationTest/test.h"
-
-#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
-
-const char TEST_MESSAGE[] = "connection successful";
-const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
-
-// macro for easy string pasting, we don't need printf here
-#define SEND_TEST_NAME "Sendto/Recvfrom"
-
-TEST_MAIN(int argc, char **argv, char **envp) {
-
- const char *FILENAME = "send_file.test";
- // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
- auto SOCK_PATH = FILENAME;
-
- // If the test fails, then the file for the socket may not be properly
- // removed. This ensures a consistent start.
- LIBC_NAMESPACE::remove(SOCK_PATH);
- LIBC_NAMESPACE::libc_errno = 0;
-
- int sockpair[2] = {0, 0};
-
- int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
- ASSERT_EQ(result, 0);
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
-
- // split into client and server processes.
- pid_t pid = LIBC_NAMESPACE::fork();
- ASSERT_NE(pid, -1);
- ASSERT_ERRNO_SUCCESS();
-
- if (pid == 0) { // child
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
- LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
-
- ssize_t send_result = LIBC_NAMESPACE::sendto(sockpair[0], TEST_MESSAGE,
- MESSAGE_LEN, 0, nullptr, 0);
- EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
- ASSERT_ERRNO_SUCCESS();
-
- LIBC_NAMESPACE::close(sockpair[0]); // close child sock
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
- } else { // parent
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
- LIBC_NAMESPACE::close(sockpair[0]); // close child sock
-
- char buffer[256];
-
- ssize_t recv_result = LIBC_NAMESPACE::recvfrom(
- sockpair[1], buffer, sizeof(buffer), 0, nullptr, 0);
- ASSERT_EQ(recv_result, MESSAGE_LEN);
- ASSERT_ERRNO_SUCCESS();
-
- for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
- ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
- }
-
- LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
- LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
- }
- return 0;
-}
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index 566233c2041780..8daf7d85c4c7d9 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -27,3 +27,48 @@ add_libc_unittest(
libc.src.stdio.remove
libc.src.unistd.close
)
+
+add_libc_unittest(
+ send_recv_test
+ SUITE
+ libc_sys_socket_unittests
+ SRCS
+ send_recv_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.socketpair
+ libc.src.sys.socket.send
+ libc.src.sys.socket.recv
+ libc.src.unistd.close
+)
+
+add_libc_unittest(
+ sendto_recvfrom_test
+ SUITE
+ libc_sys_socket_unittests
+ SRCS
+ sendto_recvfrom_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.socketpair
+ libc.src.sys.socket.sendto
+ libc.src.sys.socket.recvfrom
+ libc.src.unistd.close
+)
+
+add_libc_unittest(
+ sendmsg_recvmsg_test
+ SUITE
+ libc_sys_socket_unittests
+ SRCS
+ sendmsg_recvmsg_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.socketpair
+ libc.src.sys.socket.sendmsg
+ libc.src.sys.socket.recvmsg
+ libc.src.unistd.close
+)
diff --git a/libc/test/src/sys/socket/linux/send_recv_test.cpp b/libc/test/src/sys/socket/linux/send_recv_test.cpp
new file mode 100644
index 00000000000000..a5d4880d934cc7
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/send_recv_test.cpp
@@ -0,0 +1,73 @@
+//===-- Unittests for send/recv -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recv.h"
+#include "src/sys/socket/send.h"
+#include "src/sys/socket/socketpair.h"
+
+#include "src/unistd/close.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+
+TEST(LlvmLibcSendRecvTest, SucceedsWithSocketPair) {
+ const char TEST_MESSAGE[] = "connection successful";
+ const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+ int sockpair[2] = {0, 0};
+
+ int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ ssize_t send_result =
+ LIBC_NAMESPACE::send(sockpair[0], TEST_MESSAGE, MESSAGE_LEN, 0);
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ char buffer[256];
+
+ ssize_t recv_result =
+ LIBC_NAMESPACE::recv(sockpair[1], buffer, sizeof(buffer), 0);
+ ASSERT_EQ(recv_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ ASSERT_STREQ(buffer, TEST_MESSAGE);
+
+ // close both ends of the socket
+ result = LIBC_NAMESPACE::close(sockpair[0]);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ result = LIBC_NAMESPACE::close(sockpair[1]);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+}
+
+TEST(LlvmLibcSendRecvTest, SendFails) {
+ const char TEST_MESSAGE[] = "connection terminated";
+ const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+ ssize_t send_result = LIBC_NAMESPACE::send(-1, TEST_MESSAGE, MESSAGE_LEN, 0);
+ EXPECT_EQ(send_result, ssize_t(-1));
+ ASSERT_ERRNO_FAILURE();
+
+ LIBC_NAMESPACE::libc_errno = 0; // reset errno to avoid test ordering issues.
+}
+
+TEST(LlvmLibcSendRecvTest, RecvFails) {
+ char buffer[256];
+
+ ssize_t recv_result = LIBC_NAMESPACE::recv(-1, buffer, sizeof(buffer), 0);
+ ASSERT_EQ(recv_result, ssize_t(-1));
+ ASSERT_ERRNO_FAILURE();
+
+ LIBC_NAMESPACE::libc_errno = 0; // reset errno to avoid test ordering issues.
+}
diff --git a/libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp b/libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp
new file mode 100644
index 00000000000000..abcb0a3e6e5062
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp
@@ -0,0 +1,125 @@
+//===-- Unittests for sendmsg/recvmsg -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recvmsg.h"
+#include "src/sys/socket/sendmsg.h"
+#include "src/sys/socket/socketpair.h"
+
+#include "src/unistd/close.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+
+TEST(LlvmLibcSendMsgRecvMsgTest, SucceedsWithSocketPair) {
+ const char TEST_MESSAGE[] = "connection successful";
+ const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+ int sockpair[2] = {0, 0};
+
+ int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ iovec send_msg_text;
+ send_msg_text.iov_base =
+ reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
+ send_msg_text.iov_len = MESSAGE_LEN;
+
+ msghdr send_message;
+ send_message.msg_name = nullptr;
+ send_message.msg_namelen = 0;
+ send_message.msg_iov = &send_msg_text;
+ send_message.msg_iovlen = 1;
+ send_message.msg_control = nullptr;
+ send_message.msg_controllen = 0;
+ send_message.msg_flags = 0;
+
+ ssize_t send_result = LIBC_NAMESPACE::sendmsg(sockpair[0], &send_message, 0);
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ char buffer[256];
+
+ iovec recv_msg_text;
+ recv_msg_text.iov_base = reinterpret_cast<void *>(buffer);
+ recv_msg_text.iov_len = sizeof(buffer);
+
+ msghdr recv_message;
+ recv_message.msg_name = nullptr;
+ recv_message.msg_namelen = 0;
+ recv_message.msg_iov = &recv_msg_text;
+ recv_message.msg_iovlen = 1;
+ recv_message.msg_control = nullptr;
+ recv_message.msg_controllen = 0;
+ recv_message.msg_flags = 0;
+
+ ssize_t recv_result = LIBC_NAMESPACE::recvmsg(sockpair[1], &recv_message, 0);
+ ASSERT_EQ(recv_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ ASSERT_STREQ(buffer, TEST_MESSAGE);
+
+ // close both ends of the socket
+ result = LIBC_NAMESPACE::close(sockpair[0]);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ result = LIBC_NAMESPACE::close(sockpair[1]);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+}
+
+TEST(LlvmLibcSendMsgRecvMsgTest, SendFails) {
+ const char TEST_MESSAGE[] = "connection terminated";
+ const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+ iovec send_msg_text;
+ send_msg_text.iov_base =
+ reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
+ send_msg_text.iov_len = MESSAGE_LEN;
+
+ msghdr send_message;
+ send_message.msg_name = nullptr;
+ send_message.msg_namelen = 0;
+ send_message.msg_iov = &send_msg_text;
+ send_message.msg_iovlen = 1;
+ send_message.msg_control = nullptr;
+ send_message.msg_controllen = 0;
+ send_message.msg_flags = 0;
+
+ ssize_t send_result = LIBC_NAMESPACE::sendmsg(-1, &send_message, 0);
+ EXPECT_EQ(send_result, ssize_t(-1));
+ ASSERT_ERRNO_FAILURE();
+
+ LIBC_NAMESPACE::libc_errno = 0; // reset errno to avoid test ordering issues.
+}
+
+TEST(LlvmLibcSendMsgRecvMsgTest, RecvFails) {
+ char buffer[256];
+
+ iovec recv_msg_text;
+ recv_msg_text.iov_base = reinterpret_cast<void *>(buffer);
+ recv_msg_text.iov_len = sizeof(buffer);
+
+ msghdr recv_message;
+ recv_message.msg_name = nullptr;
+ recv_message.msg_namelen = 0;
+ recv_message.msg_iov = &recv_msg_text;
+ recv_message.msg_iovlen = 1;
+ recv_message.msg_control = nullptr;
+ recv_message.msg_controllen = 0;
+ recv_message.msg_flags = 0;
+
+ ssize_t recv_result = LIBC_NAMESPACE::recvmsg(-1, &recv_message, 0);
+ ASSERT_EQ(recv_result, ssize_t(-1));
+ ASSERT_ERRNO_FAILURE();
+
+ LIBC_NAMESPACE::libc_errno = 0; // reset errno to avoid test ordering issues.
+}
diff --git a/libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp b/libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp
new file mode 100644
index 00000000000000..e91b333deac581
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp
@@ -0,0 +1,75 @@
+//===-- Unittests for sendto/recvfrom -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recvfrom.h"
+#include "src/sys/socket/sendto.h"
+#include "src/sys/socket/socketpair.h"
+
+#include "src/unistd/close.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+
+TEST(LlvmLibcSendToRecvFromTest, SucceedsWithSocketPair) {
+ const char TEST_MESSAGE[] = "connection successful";
+ const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+ int sockpair[2] = {0, 0};
+
+ int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ ssize_t send_result = LIBC_NAMESPACE::sendto(sockpair[0], TEST_MESSAGE,
+ MESSAGE_LEN, 0, nullptr, 0);
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ char buffer[256];
+
+ ssize_t recv_result = LIBC_NAMESPACE::recvfrom(sockpair[1], buffer,
+ sizeof(buffer), 0, nullptr, 0);
+ ASSERT_EQ(recv_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ ASSERT_STREQ(buffer, TEST_MESSAGE);
+
+ // close both ends of the socket
+ result = LIBC_NAMESPACE::close(sockpair[0]);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ result = LIBC_NAMESPACE::close(sockpair[1]);
+ ASSERT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+}
+
+TEST(LlvmLibcSendToRecvFromTest, SendToFails) {
+ const char TEST_MESSAGE[] = "connection terminated";
+ const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+ ssize_t send_result =
+ LIBC_NAMESPACE::sendto(-1, TEST_MESSAGE, MESSAGE_LEN, 0, nullptr, 0);
+ EXPECT_EQ(send_result, ssize_t(-1));
+ ASSERT_ERRNO_FAILURE();
+
+ LIBC_NAMESPACE::libc_errno = 0; // reset errno to avoid test ordering issues.
+}
+
+TEST(LlvmLibcSendToRecvFromTest, RecvFromFails) {
+ char buffer[256];
+
+ ssize_t recv_result =
+ LIBC_NAMESPACE::recvfrom(-1, buffer, sizeof(buffer), 0, nullptr, 0);
+ ASSERT_EQ(recv_result, ssize_t(-1));
+ ASSERT_ERRNO_FAILURE();
+
+ LIBC_NAMESPACE::libc_errno = 0; // reset errno to avoid test ordering issues.
+}
More information about the libc-commits
mailing list