[libc] Add functions to send/recv messages (#106467)

This patch adds the necessary functions to send and receive messages
over a socket. Those functions are: recv, recvfrom, recvmsg, send,
sendto, sendmsg, and socketpair for testing.
This commit is contained in:
Michael Jones 2024-09-19 14:43:00 -07:00 committed by GitHub
parent c3fe727181
commit f6b4c34d4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 1423 additions and 85 deletions

View File

@ -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",
];
}

View File

@ -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()

View File

@ -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
)

View File

@ -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

23
libc/hdr/types/ssize_t.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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*

View File

@ -80,11 +80,20 @@ def GetoptArgvT : NamedType<"__getoptargv_t">;
def SAFamilyType : NamedType<"sa_family_t">;
def SocklenType : NamedType<"socklen_t">;
def SocklenPtr : PtrType<SocklenType>;
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 +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<IntType>,
[ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<IntType>]
>,
FunctionSpec<
"socketpair",
RetValSpec<IntType>,
[ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<IntPtr>]
>,
FunctionSpec<
"bind",
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>]
>,
FunctionSpec<
"recv",
RetValSpec<SSizeTType>,
[ArgSpec<IntType>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<IntType>]
>,
FunctionSpec<
"recvfrom",
RetValSpec<SSizeTType>,
[
ArgSpec<IntType>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>,
ArgSpec<IntType>, ArgSpec<StructSockAddrPtr>,
ArgSpec<SocklenPtr>
]
>,
FunctionSpec<
"recvmsg",
RetValSpec<SSizeTType>,
[ArgSpec<IntType>, ArgSpec<StructMsghdrPtr>, ArgSpec<IntType>]
>,
] // Functions
>;

View File

@ -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
)

View File

@ -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
)

View File

@ -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 <linux/net.h> // For SYS_SOCKET socketcall number.
#include <sys/syscall.h> // 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<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_DECL

View File

@ -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 <linux/net.h> // For SYS_SOCKET socketcall number.
#include <sys/syscall.h> // 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<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_DECL

View File

@ -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 <linux/net.h> // For SYS_SOCKET socketcall number.
#include <sys/syscall.h> // 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<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_DECL

View File

@ -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 <linux/net.h> // For SYS_SOCKET socketcall number.
#include <sys/syscall.h> // 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<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_DECL

View File

@ -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 <linux/net.h> // For SYS_SOCKET socketcall number.
#include <sys/syscall.h> // 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<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_DECL

View File

@ -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 <linux/net.h> // For SYS_SOCKET socketcall number.
#include <sys/syscall.h> // 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<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_DECL

View File

@ -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<int>(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<int>(SYS_socketpair, domain, type,
protocol, sv);
#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_BIND,
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."

View File

@ -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 <sys/socket.h>
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

View File

@ -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 <stddef.h> // 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

View File

@ -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

View File

@ -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 <sys/socket.h>
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

View File

@ -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

View File

@ -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 <stddef.h> // 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

View File

@ -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

View File

@ -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
)

View File

@ -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 <sys/socket.h> // 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<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));
ASSERT_EQ(result, 0);
ASSERT_ERRNO_SUCCESS();
LIBC_NAMESPACE::close(sock);
LIBC_NAMESPACE::remove(SOCK_PATH);
}

View File

@ -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.
}

View File

@ -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.
}

View File

@ -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.
}

View File

@ -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 <sys/socket.h> // 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();
}

View File

@ -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(

View File

@ -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",
],
)