AF_UNIX preliminary support (#3506)

* AF_UNIX preliminary support

* fixed windows

* added windows implemenation for socketpair

* More gotos

* added sys_socketpair for libkernel_ps2emu

---------

Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
Marcin Mikołajczyk
2025-09-06 18:49:21 +02:00
committed by GitHub
parent 17568353a9
commit 90f6bf0516
7 changed files with 550 additions and 0 deletions

View File

@@ -390,6 +390,7 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
src/core/libraries/network/sys_net.h
src/core/libraries/network/posix_sockets.cpp
src/core/libraries/network/p2p_sockets.cpp
src/core/libraries/network/unix_sockets.cpp
src/core/libraries/network/sockets.h
)

View File

@@ -277,16 +277,26 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_connect);
LIB_FUNCTION("pG70GT5yRo4", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_socketex);
LIB_FUNCTION("KuOmgKoqCdY", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_bind);
LIB_FUNCTION("6O8EwYOgH9Y", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_getsockopt);
LIB_FUNCTION("fFxGkxF2bVo", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_setsockopt);
LIB_FUNCTION("pxnCmagrtao", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_listen);
LIB_FUNCTION("3e+4Iv7IJ8U", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_accept);
LIB_FUNCTION("TUuiYS2kE8s", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_shutdown);
LIB_FUNCTION("TU-d9PfIHPM", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_socket);
LIB_FUNCTION("MZb0GKT3mo8", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_socketpair);
LIB_FUNCTION("MZb0GKT3mo8", "libkernel_ps2emu", 1, "libkernel", 1, 1,
Libraries::Net::sys_socketpair);
LIB_FUNCTION("K1S8oc61xiM", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_htonl);
LIB_FUNCTION("jogUIsOV3-U", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_htons);
LIB_FUNCTION("fZOeZIOEmLw", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_send);
LIB_FUNCTION("oBr313PppNE", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_sendto);
LIB_FUNCTION("Ez8xjo9UF4E", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_recv);
LIB_FUNCTION("lUk6wrGXyMw", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_recvfrom);
LIB_FUNCTION("TU-d9PfIHPM", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_socket);
LIB_FUNCTION("fZOeZIOEmLw", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_send);
LIB_FUNCTION("oBr313PppNE", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_sendto);
LIB_FUNCTION("Ez8xjo9UF4E", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recv);
LIB_FUNCTION("lUk6wrGXyMw", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recvfrom);
LIB_FUNCTION("hI7oVeOluPM", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recvmsg);
LIB_FUNCTION("TXFFFiNldU8", "libScePosix", 1, "libkernel", 1, 1,

View File

@@ -23,6 +23,7 @@ namespace Libraries::Net {
static int ConvertFamilies(int family);
enum OrbisNetFamily : u32 {
ORBIS_NET_AF_UNIX = 1,
ORBIS_NET_AF_INET = 2,
ORBIS_NET_AF_INET6 = 28,
};
@@ -126,6 +127,12 @@ struct OrbisNetInAddr {
OrbisNetInAddr_t inaddr_addr;
};
struct OrbisNetSockaddrUn {
u8 sun_len;
u8 sun_family; // AF_UNIX
char sun_path[104];
};
struct OrbisNetIovec {
void* iov_base;
u64 iov_len;

View File

@@ -6,6 +6,7 @@
#ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <Ws2tcpip.h>
#include <afunix.h>
#include <iphlpapi.h>
#include <mstcpip.h>
#include <winsock2.h>
@@ -148,4 +149,33 @@ struct P2PSocket : public Socket {
}
};
struct UnixSocket : public Socket {
net_socket sock;
int socket_type;
explicit UnixSocket(int domain, int type, int protocol)
: Socket(domain, type, protocol), sock(socket(domain, type, protocol)) {
socket_type = type;
}
explicit UnixSocket(net_socket sock) : Socket(0, 0, 0), sock(sock) {}
bool IsValid() const override;
int Close() override;
int SetSocketOptions(int level, int optname, const void* optval, u32 optlen) override;
int GetSocketOptions(int level, int optname, void* optval, u32* optlen) override;
int Bind(const OrbisNetSockaddr* addr, u32 addrlen) override;
int Listen(int backlog) override;
int SendMessage(const OrbisNetMsghdr* msg, int flags) override;
int SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
u32 tolen) override;
int ReceiveMessage(OrbisNetMsghdr* msg, int flags) override;
int ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) override;
SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override;
int Connect(const OrbisNetSockaddr* addr, u32 namelen) override;
int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override;
int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override;
int fstat(Libraries::Kernel::OrbisKernelStat* stat) override;
std::optional<net_socket> Native() override {
return sock;
}
};
} // namespace Libraries::Net

View File

@@ -160,6 +160,11 @@ int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protoc
switch (type) {
case ORBIS_NET_SOCK_STREAM:
case ORBIS_NET_SOCK_DGRAM:
if (family == ORBIS_NET_AF_UNIX) {
socket = std::make_shared<UnixSocket>(family, type, protocol);
break;
}
[[fallthrough]];
case ORBIS_NET_SOCK_RAW:
socket = std::make_shared<PosixSocket>(family, type, protocol);
break;
@@ -188,6 +193,99 @@ int PS4_SYSV_ABI sys_socket(int family, int type, int protocol) {
return sys_socketex(nullptr, family, type, protocol);
}
#ifdef _WIN32
int socketpair(int family, int type, int protocol, net_socket fd[2]) {
if (family != AF_UNIX && family != AF_INET) {
*Libraries::Kernel::__Error() = ORBIS_NET_EPROTONOSUPPORT;
return -1;
}
if (type != SOCK_STREAM) {
*Libraries::Kernel::__Error() = ORBIS_NET_EPROTONOSUPPORT;
return -1;
}
SOCKET listener = INVALID_SOCKET;
SOCKET sock1 = INVALID_SOCKET;
SOCKET sock2 = INVALID_SOCKET;
sockaddr_in addr{};
int addrlen = sizeof(addr);
listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener == INVALID_SOCKET)
goto fail1;
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = 0;
if (bind(listener, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
goto fail1;
if (listen(listener, 1) == SOCKET_ERROR)
goto fail1;
if (getsockname(listener, (sockaddr*)&addr, &addrlen) == SOCKET_ERROR)
goto fail1;
sock1 = socket(AF_INET, SOCK_STREAM, 0);
if (sock1 == INVALID_SOCKET)
goto fail2;
if (connect(sock1, (sockaddr*)&addr, addrlen) == SOCKET_ERROR)
goto fail2;
sock2 = accept(listener, nullptr, nullptr);
if (sock2 == INVALID_SOCKET)
goto fail3;
closesocket(listener);
fd[0] = sock1;
fd[1] = sock2;
return 0;
fail3:
closesocket(sock2);
fail2:
closesocket(sock1);
fail1:
closesocket(listener);
return -1;
}
#endif
int PS4_SYSV_ABI sys_socketpair(int family, int type, int protocol, int sv[2]) {
if (sv == nullptr) {
*Libraries::Kernel::__Error() = ORBIS_NET_EINVAL;
return -1;
}
if (family != ORBIS_NET_AF_UNIX) {
*Libraries::Kernel::__Error() = ORBIS_NET_EPROTONOSUPPORT;
return -1;
}
net_socket fd[2];
if (socketpair(family, type, protocol, fd) != 0) {
LOG_ERROR(Lib_Net, "socketpair failed with {}", Common::GetLastErrorMsg());
return -1;
}
auto fd1 = FDTable::Instance()->CreateHandle();
auto fd2 = FDTable::Instance()->CreateHandle();
auto* sock = FDTable::Instance()->GetFile(fd1);
sock->is_opened = true;
sock->type = Core::FileSys::FileType::Socket;
sock->socket = std::make_shared<UnixSocket>(fd[0]);
sock->m_guest_name = "anon_sock0";
sock = FDTable::Instance()->GetFile(fd2);
sock->is_opened = true;
sock->type = Core::FileSys::FileType::Socket;
sock->socket = std::make_shared<UnixSocket>(fd[1]);
sock->m_guest_name = "anon_sock1";
sv[0] = fd1;
sv[1] = fd2;
return 0;
}
int PS4_SYSV_ABI sys_netabort(OrbisNetId s, int flags) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
@@ -208,6 +306,10 @@ int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) {
return -1;
}
int PS4_SYSV_ABI sys_send(OrbisNetId s, const void* buf, u64 len, int flags) {
return sys_sendto(s, buf, len, flags, nullptr, 0);
}
int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags,
const OrbisNetSockaddr* addr, u32 addrlen) {
auto file = FDTable::Instance()->GetSocket(s);
@@ -240,6 +342,10 @@ int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags)
return -1;
}
s64 PS4_SYSV_ABI sys_recv(OrbisNetId s, void* buf, u64 len, int flags) {
return sys_recvfrom(s, buf, len, flags, nullptr, nullptr);
}
s64 PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr,
u32* paddrlen) {
auto file = FDTable::Instance()->GetSocket(s);

View File

@@ -20,11 +20,14 @@ int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void
int PS4_SYSV_ABI sys_shutdown(OrbisNetId s, int how);
int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protocol);
int PS4_SYSV_ABI sys_socket(int family, int type, int protocol);
int PS4_SYSV_ABI sys_socketpair(int family, int type, int protocol, int sv[2]);
int PS4_SYSV_ABI sys_netabort(OrbisNetId s, int flags);
int PS4_SYSV_ABI sys_socketclose(OrbisNetId s);
int PS4_SYSV_ABI sys_send(OrbisNetId s, const void* buf, u64 len, int flags);
int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags,
const OrbisNetSockaddr* addr, u32 addrlen);
int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags);
s64 PS4_SYSV_ABI sys_recv(OrbisNetId s, void* buf, u64 len, int flags);
s64 PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr,
u32* paddrlen);
s64 PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags);

View File

@@ -0,0 +1,393 @@
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <common/assert.h>
#include "common/error.h"
#include "core/libraries/kernel/file_system.h"
#include "core/libraries/kernel/kernel.h"
#include "net.h"
#ifndef _WIN32
#include <sys/stat.h>
#include <sys/un.h>
#endif
#include "net_error.h"
#include "sockets.h"
namespace Libraries::Net {
#ifdef _WIN32
#define ERROR_CASE(errname) \
case (WSA##errname): \
*Libraries::Kernel::__Error() = ORBIS_NET_##errname; \
return -1;
#else
#define ERROR_CASE(errname) \
case (errname): \
*Libraries::Kernel::__Error() = ORBIS_NET_##errname; \
return -1;
#endif
static int ConvertReturnErrorCode(int retval) {
if (retval < 0) {
#ifdef _WIN32
switch (WSAGetLastError()) {
#else
switch (errno) {
#endif
#ifndef _WIN32 // These errorcodes don't exist in WinSock
ERROR_CASE(EPERM)
ERROR_CASE(ENOENT)
// ERROR_CASE(ESRCH)
// ERROR_CASE(EIO)
// ERROR_CASE(ENXIO)
// ERROR_CASE(E2BIG)
// ERROR_CASE(ENOEXEC)
// ERROR_CASE(EDEADLK)
ERROR_CASE(ENOMEM)
// ERROR_CASE(ECHILD)
// ERROR_CASE(EBUSY)
ERROR_CASE(EEXIST)
// ERROR_CASE(EXDEV)
ERROR_CASE(ENODEV)
// ERROR_CASE(ENOTDIR)
// ERROR_CASE(EISDIR)
ERROR_CASE(ENFILE)
// ERROR_CASE(ENOTTY)
// ERROR_CASE(ETXTBSY)
// ERROR_CASE(EFBIG)
ERROR_CASE(ENOSPC)
// ERROR_CASE(ESPIPE)
// ERROR_CASE(EROFS)
// ERROR_CASE(EMLINK)
ERROR_CASE(EPIPE)
// ERROR_CASE(EDOM)
// ERROR_CASE(ERANGE)
// ERROR_CASE(ENOLCK)
// ERROR_CASE(ENOSYS)
// ERROR_CASE(EIDRM)
// ERROR_CASE(EOVERFLOW)
// ERROR_CASE(EILSEQ)
// ERROR_CASE(ENOTSUP)
ERROR_CASE(ECANCELED)
// ERROR_CASE(EBADMSG)
ERROR_CASE(ENODATA)
// ERROR_CASE(ENOSR)
// ERROR_CASE(ENOSTR)
// ERROR_CASE(ETIME)
#endif
ERROR_CASE(EINTR)
ERROR_CASE(EBADF)
ERROR_CASE(EACCES)
ERROR_CASE(EFAULT)
ERROR_CASE(EINVAL)
ERROR_CASE(EMFILE)
ERROR_CASE(EWOULDBLOCK)
ERROR_CASE(EINPROGRESS)
ERROR_CASE(EALREADY)
ERROR_CASE(ENOTSOCK)
ERROR_CASE(EDESTADDRREQ)
ERROR_CASE(EMSGSIZE)
ERROR_CASE(EPROTOTYPE)
ERROR_CASE(ENOPROTOOPT)
ERROR_CASE(EPROTONOSUPPORT)
#if defined(__APPLE__) || defined(_WIN32)
ERROR_CASE(EOPNOTSUPP)
#endif
ERROR_CASE(EAFNOSUPPORT)
ERROR_CASE(EADDRINUSE)
ERROR_CASE(EADDRNOTAVAIL)
ERROR_CASE(ENETDOWN)
ERROR_CASE(ENETUNREACH)
ERROR_CASE(ENETRESET)
ERROR_CASE(ECONNABORTED)
ERROR_CASE(ECONNRESET)
ERROR_CASE(ENOBUFS)
ERROR_CASE(EISCONN)
ERROR_CASE(ENOTCONN)
ERROR_CASE(ETIMEDOUT)
ERROR_CASE(ECONNREFUSED)
ERROR_CASE(ELOOP)
ERROR_CASE(ENAMETOOLONG)
ERROR_CASE(EHOSTUNREACH)
ERROR_CASE(ENOTEMPTY)
}
*Libraries::Kernel::__Error() = ORBIS_NET_EINTERNAL;
return -1;
}
// if it is 0 or positive return it as it is
return retval;
}
static int ConvertLevels(int level) {
switch (level) {
case ORBIS_NET_SOL_SOCKET:
return SOL_SOCKET;
case ORBIS_NET_IPPROTO_IP:
return IPPROTO_IP;
case ORBIS_NET_IPPROTO_TCP:
return IPPROTO_TCP;
case ORBIS_NET_IPPROTO_IPV6:
return IPPROTO_IPV6;
}
return -1;
}
static void convertOrbisNetSockaddrToUnix(const OrbisNetSockaddr* src, sockaddr_un* dst) {
if (src == nullptr || dst == nullptr)
return;
memset(dst, 0, sizeof(sockaddr_un));
const OrbisNetSockaddrUn* src_in = (const OrbisNetSockaddrUn*)src;
sockaddr_un* dst_in = (sockaddr_un*)dst;
dst_in->sun_family = src_in->sun_family;
memcpy(&dst_in->sun_path, &src_in->sun_path, src_in->sun_len);
}
static void convertUnixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) {
if (src == nullptr || dst == nullptr)
return;
memset(dst, 0, sizeof(OrbisNetSockaddrUn));
OrbisNetSockaddrUn* dst_in = (OrbisNetSockaddrUn*)dst;
sockaddr_un* src_in = (sockaddr_un*)src;
dst_in->sun_len = strnlen(src_in->sun_path, 108);
dst_in->sun_family = src_in->sun_family;
memcpy(&dst_in->sun_path, &src_in->sun_path, dst_in->sun_len);
}
bool UnixSocket::IsValid() const {
#ifdef _WIN32
return sock != INVALID_SOCKET;
#else
return sock != -1;
#endif
}
int UnixSocket::Close() {
std::scoped_lock lock{m_mutex};
#ifdef _WIN32
auto out = closesocket(sock);
#else
auto out = ::close(sock);
#endif
return ConvertReturnErrorCode(out);
}
int UnixSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) {
std::scoped_lock lock{m_mutex};
sockaddr_un addr2;
convertOrbisNetSockaddrToUnix(addr, &addr2);
return ConvertReturnErrorCode(::bind(sock, (const sockaddr*)&addr2, sizeof(sockaddr_un)));
}
int UnixSocket::Listen(int backlog) {
std::scoped_lock lock{m_mutex};
return ConvertReturnErrorCode(::listen(sock, backlog));
}
int UnixSocket::SendMessage(const OrbisNetMsghdr* msg, int flags) {
std::scoped_lock lock{m_mutex};
#ifdef _WIN32
DWORD bytesSent = 0;
LPFN_WSASENDMSG wsasendmsg = nullptr;
GUID guid = WSAID_WSASENDMSG;
DWORD bytes = 0;
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &wsasendmsg,
sizeof(wsasendmsg), &bytes, nullptr, nullptr) != 0) {
return ConvertReturnErrorCode(-1);
}
int res = wsasendmsg(sock, reinterpret_cast<LPWSAMSG>(const_cast<OrbisNetMsghdr*>(msg)), flags,
&bytesSent, nullptr, nullptr);
if (res == SOCKET_ERROR) {
return ConvertReturnErrorCode(-1);
}
return static_cast<int>(bytesSent);
#else
int res = sendmsg(sock, reinterpret_cast<const msghdr*>(msg), flags);
return ConvertReturnErrorCode(res);
#endif
}
int UnixSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
u32 tolen) {
std::scoped_lock lock{m_mutex};
LOG_ERROR(Lib_Net, "called");
if (to != nullptr) {
sockaddr_un addr;
convertOrbisNetSockaddrToUnix(to, &addr);
return ConvertReturnErrorCode(
sendto(sock, (const char*)msg, len, flags, (sockaddr*)&addr, sizeof(sockaddr_un)));
} else {
return ConvertReturnErrorCode(send(sock, (const char*)msg, len, flags));
}
}
int UnixSocket::ReceiveMessage(OrbisNetMsghdr* msg, int flags) {
std::scoped_lock lock{receive_mutex};
#ifdef _WIN32
LPFN_WSARECVMSG wsarecvmsg = nullptr;
GUID guid = WSAID_WSARECVMSG;
DWORD bytes = 0;
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &wsarecvmsg,
sizeof(wsarecvmsg), &bytes, nullptr, nullptr) != 0) {
return ConvertReturnErrorCode(-1);
}
DWORD bytesReceived = 0;
int res = wsarecvmsg(sock, reinterpret_cast<LPWSAMSG>(msg), &bytesReceived, nullptr, nullptr);
if (res == SOCKET_ERROR) {
return ConvertReturnErrorCode(-1);
}
return static_cast<int>(bytesReceived);
#else
int res = recvmsg(sock, reinterpret_cast<msghdr*>(msg), flags);
return ConvertReturnErrorCode(res);
#endif
}
int UnixSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) {
std::scoped_lock lock{receive_mutex};
LOG_ERROR(Lib_Net, "called");
if (from != nullptr) {
sockaddr_un addr;
int res = recvfrom(sock, (char*)buf, len, flags, (sockaddr*)&addr, (socklen_t*)fromlen);
convertUnixSockaddrToOrbis((sockaddr*)&addr, from);
*fromlen = sizeof(OrbisNetSockaddrUn);
return ConvertReturnErrorCode(res);
} else {
return ConvertReturnErrorCode(recv(sock, (char*)buf, len, flags));
}
}
SocketPtr UnixSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) {
std::scoped_lock lock{m_mutex};
sockaddr_un addr2;
socklen_t len = sizeof(addr2);
net_socket new_socket = ::accept(sock, (sockaddr*)&addr2, &len);
#ifdef _WIN32
if (new_socket != INVALID_SOCKET) {
#else
if (new_socket >= 0) {
#endif
if (addr && addrlen) {
convertUnixSockaddrToOrbis((sockaddr*)&addr2, addr);
*addrlen = sizeof(OrbisNetSockaddrUn);
}
return std::make_shared<UnixSocket>(new_socket);
}
ConvertReturnErrorCode(new_socket);
return nullptr;
}
int UnixSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) {
std::scoped_lock lock{m_mutex};
sockaddr_un addr2;
convertOrbisNetSockaddrToUnix(addr, &addr2);
int result = 0;
do {
result = ::connect(sock, (sockaddr*)&addr2, sizeof(sockaddr_un));
LOG_DEBUG(Lib_Net, "raw connect result = {}, errno = {}", result,
result == -1 ? Common::GetLastErrorMsg() : "none");
} while (result == -1 && (errno == EINTR || errno == EINPROGRESS));
return ConvertReturnErrorCode(result);
}
int UnixSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
std::scoped_lock lock{m_mutex};
sockaddr_un addr;
convertOrbisNetSockaddrToUnix(name, &addr);
if (name != nullptr) {
*namelen = sizeof(sockaddr_un);
}
int res = getsockname(sock, (sockaddr*)&addr, (socklen_t*)namelen);
if (res >= 0) {
convertUnixSockaddrToOrbis((sockaddr*)&addr, name);
*namelen = sizeof(OrbisNetSockaddrUn);
}
return ConvertReturnErrorCode(res);
}
#define CASE_SETSOCKOPT(opt) \
case ORBIS_NET_##opt: \
return ConvertReturnErrorCode( \
setsockopt(sock, native_level, opt, (const char*)optval, optlen))
#define CASE_SETSOCKOPT_VALUE(opt, value) \
case opt: \
if (optlen != sizeof(*value)) { \
*Libraries::Kernel::__Error() = ORBIS_NET_EFAULT; \
return -1; \
} \
memcpy(value, optval, optlen); \
return 0
int UnixSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) {
std::scoped_lock lock{m_mutex};
LOG_ERROR(Lib_Net, "Unknown level = {} optname = {}", level, optname);
return -1;
}
#define CASE_GETSOCKOPT(opt) \
case ORBIS_NET_##opt: { \
socklen_t optlen_temp = *optlen; \
auto retval = ConvertReturnErrorCode( \
getsockopt(sock, native_level, opt, (char*)optval, &optlen_temp)); \
*optlen = optlen_temp; \
return retval; \
}
#define CASE_GETSOCKOPT_VALUE(opt, value) \
case opt: \
if (*optlen < sizeof(value)) { \
*optlen = sizeof(value); \
*Libraries::Kernel::__Error() = ORBIS_NET_EFAULT; \
return -1; \
} \
*optlen = sizeof(value); \
*(decltype(value)*)optval = value; \
return 0;
int UnixSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) {
std::scoped_lock lock{m_mutex};
LOG_ERROR(Lib_Net, "Unknown level = {} optname = {}", level, optname);
return ConvertReturnErrorCode(-1);
}
int UnixSocket::GetPeerName(OrbisNetSockaddr* name, u32* namelen) {
std::scoped_lock lock{m_mutex};
LOG_DEBUG(Lib_Net, "called");
sockaddr_un addr;
convertOrbisNetSockaddrToUnix(name, &addr);
if (name != nullptr) {
*namelen = sizeof(sockaddr_un);
}
int res = ::getpeername(sock, (sockaddr*)&addr, (socklen_t*)namelen);
if (res >= 0) {
convertUnixSockaddrToOrbis((sockaddr*)&addr, name);
*namelen = sizeof(OrbisNetSockaddrUn);
}
return ConvertReturnErrorCode(res);
}
int UnixSocket::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
#ifdef _WIN32
LOG_ERROR(Lib_Net, "(STUBBED) called");
sb->st_mode = 0000777u | 0140000u;
return 0;
#else
struct stat st{};
int result = ::fstat(sock, &st);
sb->st_mode = 0000777u | 0140000u;
sb->st_size = st.st_size;
sb->st_blocks = st.st_blocks;
sb->st_blksize = st.st_blksize;
// sb->st_flags = st.st_flags;
return ConvertReturnErrorCode(result);
#endif
}
} // namespace Libraries::Net