diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td index 6a7c64296bf9..46523b4ca4b8 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 2a38db5bcdad..86fd33136832 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -1041,8 +1041,14 @@ 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.socketpair + 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 ) endif() diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt index 12641c4d93ff..2259ca02f2db 100644 --- a/libc/hdr/types/CMakeLists.txt +++ b/libc/hdr/types/CMakeLists.txt @@ -199,3 +199,30 @@ add_proxy_header_library( libc.include.setjmp ) + +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 000000000000..79a6b9c7dead --- /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 + +#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 000000000000..4d2000780ee1 --- /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 +#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 000000000000..6a36af791e21 --- /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 + +#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 000000000000..0fc31d537485 --- /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 + +#endif // LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_TYPES_STRUCT_SOCKADDR_H diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index dfa5063889e8..16c2ac5124c8 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -593,6 +593,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 583b84ccaae6..a4cf4631c847 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 000000000000..db2ca64cc1a1 --- /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 "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 000000000000..7933de190f34 --- /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 "size_t.h" +#include "socklen_t.h" +#include "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 3b8bf4cecfe5..accb4b14099e 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 @@ -24,3 +107,12 @@ functions: - type: int - type: int - type: int + - name: socketpair + standards: + - posix + return_type: int + arguments: + - type: int + - type: int + - type: int + - type: int* diff --git a/libc/spec/posix.td b/libc/spec/posix.td index 085f2ec34ab3..beede79a38ec 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -80,11 +80,20 @@ def GetoptArgvT : NamedType<"__getoptargv_t">; def SAFamilyType : NamedType<"sa_family_t">; def SocklenType : NamedType<"socklen_t">; +def SocklenPtr : PtrType; def StructSockAddr : NamedType<"struct sockaddr">; def StructSockAddrPtr : PtrType; def ConstStructSockAddrPtr : ConstType; +def StructMsghdr : NamedType<"struct msghdr">; +def StructMsghdrPtr : PtrType; +def ConstStructMsghdrPtr : ConstType; + +def StructIovec : NamedType<"struct iovec">; +def StructIovecPtr : PtrType; +def ConstStructIovecPtr : ConstType; + def StructSockAddrUn : NamedType<"struct sockaddr_un">; def StructStatvfs : NamedType<"struct statvfs">; @@ -1711,10 +1720,14 @@ def POSIX : StandardSpec<"POSIX"> { Macro<"SOCK_PACKET">, ], // Macros [ + SizeTType, + SSizeTType, SAFamilyType, StructSockAddr, StructSockAddrUn, SocklenType, + StructIovec, + StructMsghdr, ], // Types [], // Enumerations [ @@ -1723,11 +1736,54 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec, ArgSpec, ArgSpec] >, + FunctionSpec< + "socketpair", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec, ArgSpec] + >, FunctionSpec< "bind", RetValSpec, [ArgSpec, ArgSpec, ArgSpec] >, + FunctionSpec< + "send", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec, ArgSpec] + >, + FunctionSpec< + "sendto", + RetValSpec, + [ + ArgSpec, ArgSpec, ArgSpec, + ArgSpec, ArgSpec, + ArgSpec + ] + >, + FunctionSpec< + "sendmsg", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec] + >, + FunctionSpec< + "recv", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec, ArgSpec] + >, + FunctionSpec< + "recvfrom", + RetValSpec, + [ + ArgSpec, ArgSpec, ArgSpec, + ArgSpec, ArgSpec, + ArgSpec + ] + >, + FunctionSpec< + "recvmsg", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec] + >, ] // Functions >; diff --git a/libc/src/sys/socket/CMakeLists.txt b/libc/src/sys/socket/CMakeLists.txt index e0bc48735a03..e283c12abef3 100644 --- a/libc/src/sys/socket/CMakeLists.txt +++ b/libc/src/sys/socket/CMakeLists.txt @@ -10,8 +10,50 @@ add_entrypoint_object( ) add_entrypoint_object( - bind + socketpair ALIAS DEPENDS - .${LIBC_TARGET_OS}.bind + .${LIBC_TARGET_OS}.socketpair +) + +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 ) diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt index fc9febdec2cc..5ced5c5e310d 100644 --- a/libc/src/sys/socket/linux/CMakeLists.txt +++ b/libc/src/sys/socket/linux/CMakeLists.txt @@ -12,14 +12,95 @@ add_entrypoint_object( ) add_entrypoint_object( - bind + socketpair SRCS - bind.cpp + socketpair.cpp HDRS - ../bind.h + ../socketpair.h DEPENDS libc.include.sys_syscall libc.include.sys_socket 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.hdr.types.struct_sockaddr + libc.hdr.types.socklen_t + 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.hdr.types.struct_sockaddr + libc.hdr.types.socklen_t + 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.hdr.types.struct_msghdr + 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.hdr.types.struct_sockaddr + libc.hdr.types.socklen_t + 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.hdr.types.struct_sockaddr + libc.hdr.types.socklen_t + 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.hdr.types.struct_msghdr + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) diff --git a/libc/src/sys/socket/linux/recv.cpp b/libc/src/sys/socket/linux/recv.cpp new file mode 100644 index 000000000000..96acf449dc4b --- /dev/null +++ b/libc/src/sys/socket/linux/recv.cpp @@ -0,0 +1,47 @@ +//===-- 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 "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 // For SYS_SOCKET socketcall number. +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +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(SYS_recv, sockfd, buf, len, flags); +#elif defined(SYS_recvfrom) + ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_recvfrom, sockfd, + reinterpret_cast(buf), + len, flags, nullptr, 0); +#elif defined(SYS_socketcall) + unsigned long sockcall_args[4] = { + static_cast(sockfd), reinterpret_cast(buf), + static_cast(len), static_cast(flags)}; + ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_socketcall, SYS_RECV, + sockcall_args); +#else +#error "socket and socketcall syscalls unavailable for this platform." +#endif + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return ret; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/socket/linux/recvfrom.cpp b/libc/src/sys/socket/linux/recvfrom.cpp new file mode 100644 index 000000000000..17489a99c922 --- /dev/null +++ b/libc/src/sys/socket/linux/recvfrom.cpp @@ -0,0 +1,49 @@ +//===-- 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 "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 // For SYS_SOCKET socketcall number. +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +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( + SYS_recvfrom, sockfd, reinterpret_cast(buf), len, flags, + reinterpret_cast(dest_addr), addrlen); +#elif defined(SYS_socketcall) + unsigned long sockcall_args[6] = {static_cast(sockfd), + reinterpret_cast(buf), + static_cast(len), + static_cast(flags), + reinterpret_cast(dest_addr), + static_cast(addrlen)}; + ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_socketcall, SYS_RECVFROM, + sockcall_args); +#else +#error "socket and socketcall syscalls unavailable for this platform." +#endif + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return ret; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/socket/linux/recvmsg.cpp b/libc/src/sys/socket/linux/recvmsg.cpp new file mode 100644 index 000000000000..60045d6a80f5 --- /dev/null +++ b/libc/src/sys/socket/linux/recvmsg.cpp @@ -0,0 +1,42 @@ +//===-- 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 "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 // For SYS_SOCKET socketcall number. +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(ssize_t, recvmsg, + (int sockfd, const struct msghdr *msg, int flags)) { +#ifdef SYS_recvmsg + ssize_t ret = LIBC_NAMESPACE::syscall_impl( + SYS_recvmsg, sockfd, reinterpret_cast(msg), flags); +#elif defined(SYS_socketcall) + unsigned long sockcall_args[3] = {static_cast(sockfd), + reinterpret_cast(msg), + static_cast(flags)}; + ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_socketcall, SYS_RECVMSG, + sockcall_args); +#else +#error "socket and socketcall syscalls unavailable for this platform." +#endif + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return ret; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/socket/linux/send.cpp b/libc/src/sys/socket/linux/send.cpp new file mode 100644 index 000000000000..0d29b6fd35b9 --- /dev/null +++ b/libc/src/sys/socket/linux/send.cpp @@ -0,0 +1,46 @@ +//===-- 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 "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 // For SYS_SOCKET socketcall number. +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +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(SYS_send, sockfd, buf, len, flags); +#elif defined(SYS_sendto) + ssize_t ret = LIBC_NAMESPACE::syscall_impl( + SYS_sendto, sockfd, reinterpret_cast(buf), len, flags, nullptr, 0); +#elif defined(SYS_socketcall) + unsigned long sockcall_args[4] = { + static_cast(sockfd), reinterpret_cast(buf), + static_cast(len), static_cast(flags)}; + ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_socketcall, SYS_SEND, + sockcall_args); +#else +#error "socket and socketcall syscalls unavailable for this platform." +#endif + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return ret; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/socket/linux/sendmsg.cpp b/libc/src/sys/socket/linux/sendmsg.cpp new file mode 100644 index 000000000000..ba2b37768cc2 --- /dev/null +++ b/libc/src/sys/socket/linux/sendmsg.cpp @@ -0,0 +1,42 @@ +//===-- 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 "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 // For SYS_SOCKET socketcall number. +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(ssize_t, sendmsg, + (int sockfd, const struct msghdr *msg, int flags)) { +#ifdef SYS_sendmsg + ssize_t ret = LIBC_NAMESPACE::syscall_impl( + SYS_sendmsg, sockfd, reinterpret_cast(msg), flags); +#elif defined(SYS_socketcall) + unsigned long sockcall_args[3] = {static_cast(sockfd), + reinterpret_cast(msg), + static_cast(flags)}; + ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_socketcall, SYS_SENDMSG, + sockcall_args); +#else +#error "socket and socketcall syscalls unavailable for this platform." +#endif + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return ret; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/socket/linux/sendto.cpp b/libc/src/sys/socket/linux/sendto.cpp new file mode 100644 index 000000000000..f5c3ffe8954d --- /dev/null +++ b/libc/src/sys/socket/linux/sendto.cpp @@ -0,0 +1,49 @@ +//===-- 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 "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 // For SYS_SOCKET socketcall number. +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +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( + SYS_sendto, sockfd, reinterpret_cast(buf), len, flags, + reinterpret_cast(dest_addr), addrlen); +#elif defined(SYS_socketcall) + unsigned long sockcall_args[6] = {static_cast(sockfd), + reinterpret_cast(buf), + static_cast(len), + static_cast(flags), + reinterpret_cast(dest_addr), + static_cast(addrlen)}; + ssize_t ret = LIBC_NAMESPACE::syscall_impl(SYS_socketcall, SYS_SENDTO, + sockcall_args); +#else +#error "socket and socketcall syscalls unavailable for this platform." +#endif + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return ret; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/socket/linux/bind.cpp b/libc/src/sys/socket/linux/socketpair.cpp similarity index 62% rename from libc/src/sys/socket/linux/bind.cpp rename to libc/src/sys/socket/linux/socketpair.cpp index 3289e9f0852e..d459a7443390 100644 --- a/libc/src/sys/socket/linux/bind.cpp +++ b/libc/src/sys/socket/linux/socketpair.cpp @@ -1,4 +1,4 @@ -//===-- Linux implementation of bind --------------------------------------===// +//===-- 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. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "src/sys/socket/bind.h" +#include "src/sys/socket/socketpair.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" @@ -19,17 +19,16 @@ namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(int, bind, - (int domain, const struct sockaddr *address, - socklen_t address_len)) { -#ifdef SYS_socket - int ret = - LIBC_NAMESPACE::syscall_impl(SYS_bind, domain, address, address_len); +LLVM_LIBC_FUNCTION(int, socketpair, + (int domain, int type, int protocol, int sv[2])) { +#ifdef SYS_socketpair + int ret = LIBC_NAMESPACE::syscall_impl(SYS_socketpair, domain, type, + protocol, sv); #elif defined(SYS_socketcall) - unsigned long sockcall_args[3] = {static_cast(domain), - reinterpret_cast(address), - static_cast(address_len)}; - int ret = LIBC_NAMESPACE::syscall_impl(SYS_socketcall, SYS_BIND, + unsigned long sockcall_args[3] = { + static_cast(domain), static_cast(type), + static_cast(protocol), static_cast(sv)}; + int ret = LIBC_NAMESPACE::syscall_impl(SYS_socketcall, SYS_SOCKETPAIR, sockcall_args); #else #error "socket and socketcall syscalls unavailable for this platform." diff --git a/libc/src/sys/socket/bind.h b/libc/src/sys/socket/recv.h similarity index 62% rename from libc/src/sys/socket/bind.h rename to libc/src/sys/socket/recv.h index 1676ab6a003a..093e8ca9b123 100644 --- a/libc/src/sys/socket/bind.h +++ b/libc/src/sys/socket/recv.h @@ -1,4 +1,4 @@ -//===-- Implementation header for bind --------------------------*- C++ -*-===// +//===-- 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. @@ -6,16 +6,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC_SYS_SOCKET_BIND_H -#define LLVM_LIBC_SRC_SYS_SOCKET_BIND_H +#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H +#define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H #include "src/__support/macros/config.h" #include namespace LIBC_NAMESPACE_DECL { -int bind(int domain, const struct sockaddr *address, socklen_t address_len); +ssize_t recv(int sockfd, const void *buf, size_t len, int flags); } // namespace LIBC_NAMESPACE_DECL -#endif // LLVM_LIBC_SRC_SYS_SOCKET_BIND_H +#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 000000000000..ee8d52157b70 --- /dev/null +++ b/libc/src/sys/socket/recvfrom.h @@ -0,0 +1,25 @@ +//===-- 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 "hdr/types/socklen_t.h" +#include "hdr/types/ssize_t.h" +#include "hdr/types/struct_sockaddr.h" +#include "src/__support/macros/config.h" +#include // For size_t + +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_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 new file mode 100644 index 000000000000..a506fb0ae68f --- /dev/null +++ b/libc/src/sys/socket/recvmsg.h @@ -0,0 +1,22 @@ +//===-- 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 "hdr/types/ssize_t.h" +#include "hdr/types/struct_msghdr.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +ssize_t recvmsg(int sockfd, const struct msghdr *msg, int flags); + +} // 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 new file mode 100644 index 000000000000..e1706694cd5f --- /dev/null +++ b/libc/src/sys/socket/send.h @@ -0,0 +1,21 @@ +//===-- 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 "src/__support/macros/config.h" +#include + +namespace LIBC_NAMESPACE_DECL { + +ssize_t send(int sockfd, const void *buf, size_t len, int flags); + +} // 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 new file mode 100644 index 000000000000..c11f3bd4beb5 --- /dev/null +++ b/libc/src/sys/socket/sendmsg.h @@ -0,0 +1,22 @@ +//===-- 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 "hdr/types/ssize_t.h" +#include "hdr/types/struct_msghdr.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); + +} // 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 new file mode 100644 index 000000000000..6e5e6d4cdab6 --- /dev/null +++ b/libc/src/sys/socket/sendto.h @@ -0,0 +1,25 @@ +//===-- 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 "hdr/types/socklen_t.h" +#include "hdr/types/ssize_t.h" +#include "hdr/types/struct_sockaddr.h" +#include "src/__support/macros/config.h" +#include // For size_t + +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_DECL + +#endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H diff --git a/libc/src/sys/socket/socketpair.h b/libc/src/sys/socket/socketpair.h new file mode 100644 index 000000000000..1d847c328470 --- /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/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt index 666dc28c7e4e..acbf26c45af9 100644 --- a/libc/test/src/sys/socket/linux/CMakeLists.txt +++ b/libc/test/src/sys/socket/linux/CMakeLists.txt @@ -13,18 +13,60 @@ add_libc_unittest( libc.src.unistd.close ) - add_libc_unittest( - bind_test + socketpair_test SUITE libc_sys_socket_unittests SRCS - bind_test.cpp + socketpair_test.cpp DEPENDS libc.include.sys_socket libc.src.errno.errno - libc.src.sys.socket.socket - libc.src.sys.socket.bind - libc.src.stdio.remove + libc.src.sys.socket.socketpair + 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/bind_test.cpp b/libc/test/src/sys/socket/linux/bind_test.cpp deleted file mode 100644 index e70cbd578290..000000000000 --- a/libc/test/src/sys/socket/linux/bind_test.cpp +++ /dev/null @@ -1,54 +0,0 @@ -//===-- Unittests for bind ------------------------------------------------===// -// -// 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/bind.h" -#include "src/sys/socket/socket.h" - -#include "src/stdio/remove.h" -#include "src/unistd/close.h" - -#include "src/errno/libc_errno.h" -#include "test/UnitTest/Test.h" - -#include // For AF_UNIX and SOCK_DGRAM - -TEST(LlvmLibcSocketTest, BindLocalSocket) { - - const char *FILENAME = "bind_file.test"; - auto SOCK_PATH = libc_make_test_file_path(FILENAME); - - 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(sizeof(sockaddr_un) - sizeof(sa_family_t))); - - int result = - LIBC_NAMESPACE::bind(sock, reinterpret_cast(&my_addr), - sizeof(struct sockaddr_un)); - - ASSERT_EQ(result, 0); - ASSERT_ERRNO_SUCCESS(); - - LIBC_NAMESPACE::close(sock); - - LIBC_NAMESPACE::remove(SOCK_PATH); -} 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 000000000000..a5d4880d934c --- /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 // 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(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(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 000000000000..abcb0a3e6e50 --- /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 // 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(const_cast(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(MESSAGE_LEN)); + ASSERT_ERRNO_SUCCESS(); + + char buffer[256]; + + iovec recv_msg_text; + recv_msg_text.iov_base = reinterpret_cast(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(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(const_cast(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(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 000000000000..e91b333deac5 --- /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 // 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(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(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. +} diff --git a/libc/test/src/sys/socket/linux/socketpair_test.cpp b/libc/test/src/sys/socket/linux/socketpair_test.cpp new file mode 100644 index 000000000000..9393ddd5c19d --- /dev/null +++ b/libc/test/src/sys/socket/linux/socketpair_test.cpp @@ -0,0 +1,37 @@ +//===-- Unittests for 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/unistd/close.h" + +#include "src/errno/libc_errno.h" +#include "test/UnitTest/Test.h" + +#include // For AF_UNIX and SOCK_DGRAM + +TEST(LlvmLibcSocketPairTest, LocalSocket) { + int sockpair[2] = {-1, -1}; + int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_DGRAM, 0, sockpair); + ASSERT_EQ(result, 0); + ASSERT_ERRNO_SUCCESS(); + + ASSERT_GE(sockpair[0], 0); + ASSERT_GE(sockpair[1], 0); + + LIBC_NAMESPACE::close(sockpair[0]); + LIBC_NAMESPACE::close(sockpair[1]); + ASSERT_ERRNO_SUCCESS(); +} + +TEST(LlvmLibcSocketPairTest, SocketFails) { + int sockpair[2] = {-1, -1}; + int result = LIBC_NAMESPACE::socketpair(-1, -1, -1, sockpair); + ASSERT_EQ(result, -1); + ASSERT_ERRNO_FAILURE(); +} diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index f253f69b5133..0e39211988f8 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -217,6 +217,26 @@ libc_support_library( hdrs = ["hdr/types/FILE.h"], ) +libc_support_library( + name = "types_ssize_t", + hdrs = ["hdr/types/ssize_t.h"], +) + +libc_support_library( + name = "types_socklen_t", + hdrs = ["hdr/types/socklen_t.h"], +) + +libc_support_library( + name = "types_struct_sockaddr", + hdrs = ["hdr/types/struct_sockaddr.h"], +) + +libc_support_library( + name = "types_struct_msghdr", + hdrs = ["hdr/types/struct_msghdr.h"], +) + ############################### Support libraries ############################## libc_support_library( @@ -4153,6 +4173,112 @@ libc_function( ], ) +############################## sys/socket targets ############################## + +libc_function( + name = "socket", + srcs = ["src/sys/socket/linux/socket.cpp"], + hdrs = ["src/sys/socket/socket.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ], +) + +libc_function( + name = "socketpair", + srcs = ["src/sys/socket/linux/socketpair.cpp"], + hdrs = ["src/sys/socket/socketpair.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ], +) + +libc_function( + name = "send", + srcs = ["src/sys/socket/linux/send.cpp"], + hdrs = ["src/sys/socket/send.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ":types_socklen_t", + ":types_ssize_t", + ":types_struct_sockaddr", + ], +) + +libc_function( + name = "sendto", + srcs = ["src/sys/socket/linux/sendto.cpp"], + hdrs = ["src/sys/socket/sendto.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ":types_socklen_t", + ":types_ssize_t", + ":types_struct_sockaddr", + ], +) + +libc_function( + name = "sendmsg", + srcs = ["src/sys/socket/linux/sendmsg.cpp"], + hdrs = ["src/sys/socket/sendmsg.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ":types_ssize_t", + ":types_struct_msghdr", + ], +) + +libc_function( + name = "recv", + srcs = ["src/sys/socket/linux/recv.cpp"], + hdrs = ["src/sys/socket/recv.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ":types_socklen_t", + ":types_ssize_t", + ":types_struct_sockaddr", + ], +) + +libc_function( + name = "recvfrom", + srcs = ["src/sys/socket/linux/recvfrom.cpp"], + hdrs = ["src/sys/socket/recvfrom.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ":types_socklen_t", + ":types_ssize_t", + ":types_struct_sockaddr", + ], +) + +libc_function( + name = "recvmsg", + srcs = ["src/sys/socket/linux/recvmsg.cpp"], + hdrs = ["src/sys/socket/recvmsg.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ":types_ssize_t", + ":types_struct_msghdr", + ], +) + ############################## sys/epoll targets ############################### libc_function( diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/sys/socket/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/sys/socket/BUILD.bazel new file mode 100644 index 000000000000..865f5e6f4961 --- /dev/null +++ b/utils/bazel/llvm-project-overlay/libc/test/src/sys/socket/BUILD.bazel @@ -0,0 +1,62 @@ +# This file is licensed 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 + +# Tests for LLVM libc string.h functions. + +load("//libc/test:libc_test_rules.bzl", "libc_test") + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +libc_test( + name = "socket_test", + srcs = ["linux/socket_test.cpp"], + libc_function_deps = [ + "//libc:socket", + "//libc:close", + ], +) + +libc_test( + name = "socketpair_test", + srcs = ["linux/socketpair_test.cpp"], + libc_function_deps = [ + "//libc:socketpair", + "//libc:close", + ], +) + +libc_test( + name = "send_recv_test", + srcs = ["linux/send_recv_test.cpp"], + libc_function_deps = [ + "//libc:socketpair", + "//libc:send", + "//libc:recv", + "//libc:close", + ], +) + +libc_test( + name = "sendto_recvfrom_test", + srcs = ["linux/sendto_recvfrom_test.cpp"], + libc_function_deps = [ + "//libc:socketpair", + "//libc:sendto", + "//libc:recvfrom", + "//libc:close", + ], +) + +libc_test( + name = "sendmsg_recvmsg_test", + srcs = ["linux/sendmsg_recvmsg_test.cpp"], + libc_function_deps = [ + "//libc:socketpair", + "//libc:sendmsg", + "//libc:recvmsg", + "//libc:close", + ], +)