diff --git a/CMakeLists.txt b/CMakeLists.txt index 576fd3d35..18ae7d99d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -293,6 +293,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp src/core/libraries/kernel/posix_error.h src/core/libraries/kernel/aio.cpp src/core/libraries/kernel/aio.h + src/core/libraries/kernel/posix_net.cpp + src/core/libraries/kernel/posix_net.h ) set(NETWORK_LIBS src/core/libraries/network/http.cpp diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp index 2b7735219..7c79b7e69 100644 --- a/src/core/libraries/kernel/kernel.cpp +++ b/src/core/libraries/kernel/kernel.cpp @@ -29,6 +29,7 @@ #endif #include #include "aio.h" +#include "posix_net.h" namespace Libraries::Kernel { @@ -111,6 +112,13 @@ void SetPosixErrno(int e) { case ETIMEDOUT: g_posix_errno = POSIX_ETIMEDOUT; break; + case EBADF: + g_posix_errno = POSIX_EBADF; + break; + case EINTR: + g_posix_errno = POSIX_EINTR; + break; + default: g_posix_errno = e; } @@ -196,10 +204,6 @@ const char* PS4_SYSV_ABI sceKernelGetFsSandboxRandomWord() { return path; } -int PS4_SYSV_ABI posix_connect() { - return -1; -} - int PS4_SYSV_ABI _sigprocmask() { return ORBIS_OK; } @@ -208,6 +212,35 @@ int PS4_SYSV_ABI posix_getpagesize() { return 16_KB; } +int PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, + const timeval* timeout) { + /* int result = select(nfds, readfds, writefds, exceptfds, timeout); + if (result < 0) { +#ifdef _WIN32 + int err = WSAGetLastError(); + switch (err) { + case WSAEINVAL: + SetPosixErrno(EINVAL); + break; + case WSAENOTSOCK: + SetPosixErrno(ENOTSOCK); + break; + case WSAEINTR: + SetPosixErrno(EINTR); + break; + case WSAEINPROGRESS: + SetPosixErrno(EINPROGRESS); + break; + } +#else + SetPosixErrno(result); +#endif + return -1; + } + return result;*/ + return 0; +} + void RegisterKernel(Core::Loader::SymbolsResolver* sym) { service_thread = std::jthread{KernelServiceThread}; @@ -220,11 +253,11 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) { Libraries::Kernel::RegisterProcess(sym); Libraries::Kernel::RegisterException(sym); Libraries::Kernel::RegisterAio(sym); + Libraries::Kernel::RegisterNet(sym); LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl); LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord); - LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, posix_connect); LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask); LIB_FUNCTION("Xjoosiw+XPI", "libkernel", 1, "libkernel", 1, 1, sceKernelUuidCreate); LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail); @@ -236,6 +269,9 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) { sceLibcHeapGetTraceInfo); LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write); LIB_FUNCTION("FN4gaPmuFV8", "libScePosix", 1, "libkernel", 1, 1, ps4__write); + + LIB_FUNCTION("T8fER+tIGgk", "libScePosix", 1, "libkernel", 1, 1, posix_select); + //LIB_FUNCTION("T8fER+tIGgk", "libkernel", 1, "libkernel", 1, 1, posix_socket); } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/posix_net.cpp b/src/core/libraries/kernel/posix_net.cpp new file mode 100644 index 000000000..4b952690f --- /dev/null +++ b/src/core/libraries/kernel/posix_net.cpp @@ -0,0 +1,118 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include "posix_net.h" + +namespace Libraries::Kernel { +int PS4_SYSV_ABI posix_socket(int domain, int type, int protocol) { + auto* netcall = Common::Singleton::Instance(); + int socket = netcall->net_socket(domain, type, protocol); + if (socket < 0) { + LOG_ERROR(Lib_Kernel, "error in socket creation = {}", socket); + } + return socket; +} +int PS4_SYSV_ABI posix_connect(int sockfd, const struct OrbisNetSockaddr* addr, socklen_t addrlen) { + auto* netcall = Common::Singleton::Instance(); + int connect = netcall->net_connect(sockfd, addr, addrlen); + if (connect < 0) { + LOG_ERROR(Lib_Kernel, "error in connect = {}", connect); + } + return connect; +} +u32 PS4_SYSV_ABI posix_htonl(u32 hostlong) { + return htonl(hostlong); +} +u16 PS4_SYSV_ABI posix_htons(u16 hostshort) { + return htons(hostshort); +} +int PS4_SYSV_ABI posix_bind(int sockfd, const struct OrbisNetSockaddr* addr, socklen_t addrlen) { + auto* netcall = Common::Singleton::Instance(); + int bind = netcall->net_bind(sockfd, addr, addrlen); + if (bind < 0) { + LOG_ERROR(Lib_Kernel, "error in binding = {}", bind); + } + return bind; +} +int PS4_SYSV_ABI posix_listen(int sockfd, int backlog) { + auto* netcall = Common::Singleton::Instance(); + int listen = netcall->net_listen(sockfd, backlog); + if (listen < 0) { + LOG_ERROR(Lib_Kernel, "error in listen = {}", listen); + } + return listen; +} +int PS4_SYSV_ABI posix_accept(int sockfd, struct OrbisNetSockaddr* addr, socklen_t* addrlen) { + LOG_ERROR(Lib_Kernel, "(STUBBED) callled"); + return ORBIS_OK; +} + +void RegisterNet(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, posix_connect); + LIB_FUNCTION("TU-d9PfIHPM", "libkernel", 1, "libkernel", 1, 1, posix_socket); + LIB_FUNCTION("K1S8oc61xiM", "libkernel", 1, "libkernel", 1, 1, posix_htonl); + LIB_FUNCTION("jogUIsOV3-U", "libkernel", 1, "libkernel", 1, 1, posix_htons); + LIB_FUNCTION("KuOmgKoqCdY", "libkernel", 1, "libkernel", 1, 1, posix_bind); + LIB_FUNCTION("pxnCmagrtao", "libkernel", 1, "libkernel", 1, 1, posix_listen); + LIB_FUNCTION("3e+4Iv7IJ8U", "libkernel", 1, "libkernel", 1, 1, posix_accept); + LIB_FUNCTION("TU-d9PfIHPM", "libScePosix", 1, "libkernel", 1, 1, posix_socket); + LIB_FUNCTION("XVL8So3QJUk", "libScePosix", 1, "libkernel", 1, 1, posix_connect); +} + +int NetPosixInternal::net_socket(int domain, int type, int protocol) { + std::scoped_lock lock{m_mutex}; + s_socket sock = ::socket(domain, type, protocol); + auto id = ++next_id; + socks.emplace(id, sock); + LOG_INFO(Lib_Kernel, "socket created with id = {}", id); + return id; +} + +static void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst) { + if (src == nullptr || dst == nullptr) + return; + memset(dst, 0, sizeof(sockaddr)); + const OrbisNetSockaddrIn* src_in = (const OrbisNetSockaddrIn*)src; + sockaddr_in* dst_in = (sockaddr_in*)dst; + dst_in->sin_family = src_in->sin_family; + dst_in->sin_port = src_in->sin_port; + memcpy(&dst_in->sin_addr, &src_in->sin_addr, 4); +} + +int NetPosixInternal::net_bind(int sockfd, const struct OrbisNetSockaddr* addr, socklen_t addrlen) { + std::scoped_lock lock{m_mutex}; + const auto it = socks.find(sockfd); + if (it != socks.end()) { + s_socket sock = it->second; + sockaddr addr2; + convertOrbisNetSockaddrToPosix(addr, &addr2); + return ::bind(sock, &addr2, sizeof(sockaddr_in)); + } + return 0; // TODO logging and error return +} +int NetPosixInternal::net_listen(int sockfd, int backlog) { + std::scoped_lock lock{m_mutex}; + const auto it = socks.find(sockfd); + if (it != socks.end()) { + s_socket sock = it->second; + return ::listen(sock, backlog); + } + return 0; // TODO logging and error return +} + +int NetPosixInternal::net_connect(int sockfd, const OrbisNetSockaddr* addr, socklen_t addrlen) { + std::scoped_lock lock{m_mutex}; + const auto it = socks.find(sockfd); + if (it != socks.end()) { + s_socket sock = it->second; + sockaddr addr2; + convertOrbisNetSockaddrToPosix(addr, &addr2); + return ::connect(sock, &addr2, sizeof(sockaddr_in)); + } + return 0; // TODO logging and error return +} + +} // namespace Libraries::Kernel \ No newline at end of file diff --git a/src/core/libraries/kernel/posix_net.h b/src/core/libraries/kernel/posix_net.h new file mode 100644 index 000000000..3f879f356 --- /dev/null +++ b/src/core/libraries/kernel/posix_net.h @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include "common/types.h" + +#ifdef WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#include +#include +#include +typedef SOCKET s_socket; +#else +#include +#include +#include +#include +#include +#include +#include +#include +typedef int s_socket; +#endif +#include +#include + +namespace Common { +class NativeClock; +} + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::Kernel { +struct OrbisNetSockaddr { + u8 sa_len; + u8 sa_family; + char sa_data[14]; +}; + +struct OrbisNetSockaddrIn { + u8 sin_len; + u8 sin_family; + u16 sin_port; + u32 sin_addr; + u16 sin_vport; + char sin_zero[6]; +}; + +int PS4_SYSV_ABI posix_socket(int domain, int type, int protocol); +int PS4_SYSV_ABI posix_connect(int sockfd, const struct OrbisNetSockaddr* addr, socklen_t addrlen); +u32 PS4_SYSV_ABI posix_htonl(u32 hostlong); +u16 PS4_SYSV_ABI posix_htons(u16 hostshort); +int PS4_SYSV_ABI posix_bind(int sockfd, const struct OrbisNetSockaddr* addr, socklen_t addrlen); +int PS4_SYSV_ABI posix_listen(int sockfd, int backlog); +int PS4_SYSV_ABI posix_accept(int sockfd, struct OrbisNetSockaddr* addr, socklen_t* addrlen); + +void RegisterNet(Core::Loader::SymbolsResolver* sym); + +class NetPosixInternal { +public: + explicit NetPosixInternal() = default; + ~NetPosixInternal() = default; + int net_socket(int domain, int type, int protocol); + int net_bind(int sockfd, const struct OrbisNetSockaddr* addr, socklen_t addrlen); + int net_listen(int sockfd, int backlog); + int net_connect(int sockfd, const struct OrbisNetSockaddr* addr, socklen_t addrlen); + +public: + s_socket sock; + std::mutex m_mutex; + typedef std::map NetSockets; + NetSockets socks; + int next_id = 0; +}; + +} // namespace Libraries::Kernel