mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -06:00
Feat: Epoll P2P Implementation
This commit is contained in:
parent
26e2689b06
commit
6781dbe8e9
@ -34,7 +34,7 @@ using FDTable = Common::Singleton<Core::FileSys::HandleTable>;
|
||||
|
||||
static thread_local int32_t net_errno = 0;
|
||||
|
||||
static bool g_isNetInitialized = true; // TODO init it properly
|
||||
static bool g_isNetInitialized = false;
|
||||
|
||||
static int ConvertFamilies(int family) {
|
||||
switch (family) {
|
||||
@ -127,6 +127,8 @@ int PS4_SYSV_ABI sce_net_in6addr_nodelocal_allnodes() {
|
||||
}
|
||||
|
||||
OrbisNetId PS4_SYSV_ABI sceNetAccept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) {
|
||||
LOG_DEBUG(Lib_Net, "called, s = {}, addr = {}, paddrlen = {}", s, fmt::ptr(addr),
|
||||
fmt::ptr(paddrlen));
|
||||
if (!g_isNetInitialized) {
|
||||
return ORBIS_NET_ERROR_ENOTINIT;
|
||||
}
|
||||
@ -657,8 +659,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
case Core::FileSys::FileType::Socket: {
|
||||
auto native_handle = file->socket->Native();
|
||||
if (!native_handle) {
|
||||
// P2P socket, cannot be added to epoll
|
||||
LOG_ERROR(Lib_Net, "P2P socket cannot be added to epoll (unimplemented)");
|
||||
LOG_ERROR(Lib_Net, "socket {} has no native handle", id);
|
||||
*sceNetErrnoLoc() = ORBIS_NET_EBADF;
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
@ -666,9 +667,10 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
#ifndef __FreeBSD__
|
||||
epoll_event native_event = {.events = ConvertEpollEventsIn(event->events),
|
||||
.data = {.fd = id}};
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, *native_handle, &native_event) == 0);
|
||||
epoll->events.emplace_back(id, *event);
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, *native_handle,
|
||||
&native_event) == 0);
|
||||
#endif
|
||||
epoll->events.emplace_back(id, *event);
|
||||
break;
|
||||
}
|
||||
case Core::FileSys::FileType::Resolver: {
|
||||
@ -707,8 +709,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
case Core::FileSys::FileType::Socket: {
|
||||
auto native_handle = file->socket->Native();
|
||||
if (!native_handle) {
|
||||
// P2P socket, cannot be modified in epoll
|
||||
LOG_ERROR(Lib_Net, "P2P socket cannot be modified in epoll (unimplemented)");
|
||||
LOG_ERROR(Lib_Net, "socket {} has no native handle", id);
|
||||
*sceNetErrnoLoc() = ORBIS_NET_EBADF;
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
@ -716,9 +717,10 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
#ifndef __FreeBSD__
|
||||
epoll_event native_event = {.events = ConvertEpollEventsIn(event->events),
|
||||
.data = {.fd = id}};
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_MOD, *native_handle, &native_event) == 0);
|
||||
*it = {id, *event};
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_MOD, *native_handle,
|
||||
&native_event) == 0);
|
||||
#endif
|
||||
*it = {id, *event};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -751,15 +753,15 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
case Core::FileSys::FileType::Socket: {
|
||||
auto native_handle = file->socket->Native();
|
||||
if (!native_handle) {
|
||||
// P2P socket, cannot be removed from epoll
|
||||
LOG_ERROR(Lib_Net, "P2P socket cannot be removed from epoll (unimplemented)");
|
||||
LOG_ERROR(Lib_Net, "socket {} has no native handle", id);
|
||||
*sceNetErrnoLoc() = ORBIS_NET_EBADF;
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, *native_handle, nullptr) == 0);
|
||||
epoll->events.erase(it);
|
||||
#endif
|
||||
epoll->events.erase(it);
|
||||
break;
|
||||
}
|
||||
case Core::FileSys::FileType::Resolver: {
|
||||
@ -1700,7 +1702,8 @@ int PS4_SYSV_ABI sceNetSysctl() {
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceNetTerm() {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
LOG_DEBUG(Lib_Net, "called");
|
||||
g_isNetInitialized = false;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <common/assert.h>
|
||||
@ -7,82 +7,308 @@
|
||||
#include "net_error.h"
|
||||
#include "sockets.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
namespace Libraries::Net {
|
||||
|
||||
P2PSocket::P2PSocket(int domain, int type, int protocol) : Socket(domain, type, protocol) {
|
||||
socket_type = type;
|
||||
// Map P2P socket types to real OS socket types
|
||||
int os_type;
|
||||
int os_protocol;
|
||||
if (type == ORBIS_NET_SOCK_DGRAM_P2P) {
|
||||
os_type = SOCK_DGRAM;
|
||||
os_protocol = IPPROTO_UDP;
|
||||
} else {
|
||||
// ORBIS_NET_SOCK_STREAM_P2P
|
||||
os_type = SOCK_STREAM;
|
||||
os_protocol = IPPROTO_TCP;
|
||||
}
|
||||
sock = ::socket(AF_INET, os_type, os_protocol);
|
||||
LOG_INFO(Lib_Net, "P2P socket created: type={} (os_type={}), fd={}", type, os_type, sock);
|
||||
}
|
||||
|
||||
P2PSocket::~P2PSocket() {
|
||||
#ifdef _WIN32
|
||||
if (sock != INVALID_SOCKET) {
|
||||
closesocket(sock);
|
||||
}
|
||||
#else
|
||||
if (sock != -1) {
|
||||
::close(sock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool P2PSocket::IsValid() const {
|
||||
#ifdef _WIN32
|
||||
return sock != INVALID_SOCKET;
|
||||
#else
|
||||
return sock != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int P2PSocket::Close() {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
#ifdef _WIN32
|
||||
auto out = closesocket(sock);
|
||||
sock = INVALID_SOCKET;
|
||||
#else
|
||||
auto out = ::close(sock);
|
||||
sock = -1;
|
||||
#endif
|
||||
return ConvertReturnErrorCode(out);
|
||||
}
|
||||
|
||||
int P2PSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
int native_level = ConvertLevels(level);
|
||||
|
||||
// Handle PS4-specific options that have no OS equivalent
|
||||
if (native_level == SOL_SOCKET) {
|
||||
switch (optname) {
|
||||
case ORBIS_NET_SO_NBIO: {
|
||||
sockopt_so_nbio = *(int*)optval;
|
||||
int val = sockopt_so_nbio;
|
||||
#ifdef _WIN32
|
||||
u_long mode = val;
|
||||
return ConvertReturnErrorCode(ioctlsocket(sock, FIONBIO, &mode));
|
||||
#else
|
||||
return ConvertReturnErrorCode(ioctl(sock, FIONBIO, &val));
|
||||
#endif
|
||||
}
|
||||
case ORBIS_NET_SO_USECRYPTO:
|
||||
case ORBIS_NET_SO_USESIGNATURE:
|
||||
case ORBIS_NET_SO_REUSEPORT:
|
||||
LOG_DEBUG(Lib_Net, "P2P setsockopt: storing PS4-specific option {}", optname);
|
||||
return 0;
|
||||
case ORBIS_NET_SO_SNDTIMEO:
|
||||
case ORBIS_NET_SO_RCVTIMEO: {
|
||||
int us = *(int*)optval;
|
||||
#ifdef _WIN32
|
||||
DWORD timeout_ms = us / 1000;
|
||||
int native_opt = (optname == ORBIS_NET_SO_SNDTIMEO) ? SO_SNDTIMEO : SO_RCVTIMEO;
|
||||
return ConvertReturnErrorCode(
|
||||
::setsockopt(sock, SOL_SOCKET, native_opt, (char*)&timeout_ms, sizeof(timeout_ms)));
|
||||
#else
|
||||
timeval tv{.tv_sec = us / 1000000, .tv_usec = us % 1000000};
|
||||
int native_opt = (optname == ORBIS_NET_SO_SNDTIMEO) ? SO_SNDTIMEO : SO_RCVTIMEO;
|
||||
return ConvertReturnErrorCode(
|
||||
::setsockopt(sock, SOL_SOCKET, native_opt, &tv, sizeof(tv)));
|
||||
#endif
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (native_level < 0) {
|
||||
LOG_WARNING(Lib_Net, "P2P setsockopt: unknown level {}", level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ConvertReturnErrorCode(
|
||||
::setsockopt(sock, native_level, optname, (const char*)optval, optlen));
|
||||
}
|
||||
|
||||
int P2PSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
int native_level = ConvertLevels(level);
|
||||
|
||||
if (native_level == SOL_SOCKET) {
|
||||
switch (optname) {
|
||||
case ORBIS_NET_SO_NBIO:
|
||||
*(int*)optval = sockopt_so_nbio;
|
||||
*optlen = sizeof(int);
|
||||
return 0;
|
||||
case ORBIS_NET_SO_TYPE:
|
||||
*(int*)optval = socket_type;
|
||||
*optlen = sizeof(int);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (native_level < 0) {
|
||||
LOG_WARNING(Lib_Net, "P2P getsockopt: unknown level {}", level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
socklen_t native_optlen = *optlen;
|
||||
int ret = ::getsockopt(sock, native_level, optname, (char*)optval, &native_optlen);
|
||||
*optlen = native_optlen;
|
||||
return ConvertReturnErrorCode(ret);
|
||||
}
|
||||
|
||||
int P2PSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
const auto* orbis_addr = reinterpret_cast<const OrbisNetSockaddrIn*>(addr);
|
||||
if (orbis_addr) {
|
||||
vport = orbis_addr->sin_vport;
|
||||
LOG_INFO(Lib_Net, "P2P bind: port={}, vport={}", ntohs(orbis_addr->sin_port), vport);
|
||||
}
|
||||
sockaddr native_addr;
|
||||
convertOrbisNetSockaddrToPosix(addr, &native_addr);
|
||||
return ConvertReturnErrorCode(::bind(sock, &native_addr, sizeof(sockaddr_in)));
|
||||
}
|
||||
|
||||
int P2PSocket::Listen(int backlog) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
return ConvertReturnErrorCode(::listen(sock, backlog));
|
||||
}
|
||||
|
||||
int P2PSocket::SendMessage(const OrbisNetMsghdr* msg, int flags) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
*Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN;
|
||||
return -1;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
int native_flags = convertOrbisFlagsToPosix(socket_type, flags);
|
||||
#ifdef _WIN32
|
||||
// Windows: loop through buffers with send()
|
||||
int total_sent = 0;
|
||||
for (int i = 0; i < msg->msg_iovlen; i++) {
|
||||
auto& iov = msg->msg_iov[i];
|
||||
int sent = ::send(sock, (const char*)iov.iov_base, iov.iov_len, native_flags);
|
||||
if (sent < 0) {
|
||||
return total_sent > 0 ? total_sent : ConvertReturnErrorCode(sent);
|
||||
}
|
||||
total_sent += sent;
|
||||
}
|
||||
return total_sent;
|
||||
#else
|
||||
return ConvertReturnErrorCode(
|
||||
::sendmsg(sock, reinterpret_cast<const msghdr*>(msg), native_flags));
|
||||
#endif
|
||||
}
|
||||
|
||||
int P2PSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
|
||||
u32 tolen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
*Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN;
|
||||
return -1;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
int native_flags = convertOrbisFlagsToPosix(socket_type, flags);
|
||||
if (to == nullptr) {
|
||||
return ConvertReturnErrorCode(::send(sock, (const char*)msg, len, native_flags));
|
||||
}
|
||||
sockaddr native_addr;
|
||||
convertOrbisNetSockaddrToPosix(to, &native_addr);
|
||||
return ConvertReturnErrorCode(
|
||||
::sendto(sock, (const char*)msg, len, native_flags, &native_addr, sizeof(sockaddr_in)));
|
||||
}
|
||||
|
||||
int P2PSocket::ReceiveMessage(OrbisNetMsghdr* msg, int flags) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
*Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN;
|
||||
return -1;
|
||||
std::scoped_lock lock{receive_mutex};
|
||||
int native_flags = convertOrbisFlagsToPosix(socket_type, flags);
|
||||
#ifdef _WIN32
|
||||
// Windows: loop through buffers with recv()
|
||||
int total_recv = 0;
|
||||
for (int i = 0; i < msg->msg_iovlen; i++) {
|
||||
auto& iov = msg->msg_iov[i];
|
||||
int recvd = ::recv(sock, (char*)iov.iov_base, iov.iov_len, native_flags);
|
||||
if (recvd < 0) {
|
||||
return total_recv > 0 ? total_recv : ConvertReturnErrorCode(recvd);
|
||||
}
|
||||
total_recv += recvd;
|
||||
if (recvd < (int)iov.iov_len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return total_recv;
|
||||
#else
|
||||
return ConvertReturnErrorCode(
|
||||
::recvmsg(sock, reinterpret_cast<msghdr*>(msg), native_flags));
|
||||
#endif
|
||||
}
|
||||
|
||||
int P2PSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
*Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN;
|
||||
return -1;
|
||||
int P2PSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from,
|
||||
u32* fromlen) {
|
||||
std::scoped_lock lock{receive_mutex};
|
||||
int native_flags = convertOrbisFlagsToPosix(socket_type, flags);
|
||||
if (from == nullptr) {
|
||||
return ConvertReturnErrorCode(::recv(sock, (char*)buf, len, native_flags));
|
||||
}
|
||||
sockaddr native_addr;
|
||||
socklen_t native_addrlen = sizeof(native_addr);
|
||||
int ret = ::recvfrom(sock, (char*)buf, len, native_flags, &native_addr, &native_addrlen);
|
||||
if (ret >= 0) {
|
||||
convertPosixSockaddrToOrbis(&native_addr, from);
|
||||
if (fromlen) {
|
||||
*fromlen = sizeof(OrbisNetSockaddrIn);
|
||||
}
|
||||
}
|
||||
return ConvertReturnErrorCode(ret);
|
||||
}
|
||||
|
||||
SocketPtr P2PSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
*Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN;
|
||||
return nullptr;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
sockaddr native_addr;
|
||||
socklen_t len = sizeof(native_addr);
|
||||
auto new_sock = ::accept(sock, &native_addr, &len);
|
||||
#ifdef _WIN32
|
||||
if (new_sock == INVALID_SOCKET) {
|
||||
#else
|
||||
if (new_sock < 0) {
|
||||
#endif
|
||||
ConvertReturnErrorCode(-1);
|
||||
return nullptr;
|
||||
}
|
||||
if (addr) {
|
||||
convertPosixSockaddrToOrbis(&native_addr, addr);
|
||||
if (addrlen) {
|
||||
*addrlen = sizeof(OrbisNetSockaddrIn);
|
||||
}
|
||||
}
|
||||
return std::make_shared<PosixSocket>(new_sock);
|
||||
}
|
||||
|
||||
int P2PSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
const auto* orbis_addr = reinterpret_cast<const OrbisNetSockaddrIn*>(addr);
|
||||
if (orbis_addr) {
|
||||
vport = orbis_addr->sin_vport;
|
||||
LOG_INFO(Lib_Net, "P2P connect: vport={}", vport);
|
||||
}
|
||||
sockaddr native_addr;
|
||||
convertOrbisNetSockaddrToPosix(addr, &native_addr);
|
||||
int ret = ::connect(sock, &native_addr, sizeof(sockaddr_in));
|
||||
#ifdef _WIN32
|
||||
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||
WSASetLastError(WSAEINPROGRESS);
|
||||
}
|
||||
#endif
|
||||
return ConvertReturnErrorCode(ret);
|
||||
}
|
||||
|
||||
int P2PSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
sockaddr native_addr;
|
||||
socklen_t len = sizeof(native_addr);
|
||||
int ret = ::getsockname(sock, &native_addr, &len);
|
||||
if (ret == 0) {
|
||||
convertPosixSockaddrToOrbis(&native_addr, name);
|
||||
if (namelen) {
|
||||
*namelen = sizeof(OrbisNetSockaddrIn);
|
||||
}
|
||||
}
|
||||
return ConvertReturnErrorCode(ret);
|
||||
}
|
||||
|
||||
int P2PSocket::GetPeerName(OrbisNetSockaddr* addr, u32* namelen) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
std::scoped_lock lock{m_mutex};
|
||||
sockaddr native_addr;
|
||||
socklen_t len = sizeof(native_addr);
|
||||
int ret = ::getpeername(sock, &native_addr, &len);
|
||||
if (ret == 0) {
|
||||
convertPosixSockaddrToOrbis(&native_addr, addr);
|
||||
if (namelen) {
|
||||
*namelen = sizeof(OrbisNetSockaddrIn);
|
||||
}
|
||||
}
|
||||
return ConvertReturnErrorCode(ret);
|
||||
}
|
||||
|
||||
int P2PSocket::fstat(Libraries::Kernel::OrbisKernelStat* stat) {
|
||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||
LOG_DEBUG(Lib_Net, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Libraries::Net
|
||||
} // namespace Libraries::Net
|
||||
|
||||
@ -27,7 +27,7 @@ namespace Libraries::Net {
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
static int ConvertReturnErrorCode(int retval) {
|
||||
int ConvertReturnErrorCode(int retval) {
|
||||
if (retval < 0) {
|
||||
#ifdef _WIN32
|
||||
switch (WSAGetLastError()) {
|
||||
@ -118,7 +118,7 @@ static int ConvertReturnErrorCode(int retval) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int ConvertLevels(int level) {
|
||||
int ConvertLevels(int level) {
|
||||
switch (level) {
|
||||
case ORBIS_NET_SOL_SOCKET:
|
||||
return SOL_SOCKET;
|
||||
@ -132,7 +132,7 @@ static int ConvertLevels(int level) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst) {
|
||||
void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst) {
|
||||
if (src == nullptr || dst == nullptr)
|
||||
return;
|
||||
memset(dst, 0, sizeof(sockaddr));
|
||||
@ -143,7 +143,7 @@ static void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr
|
||||
memcpy(&dst_in->sin_addr, &src_in->sin_addr, 4);
|
||||
}
|
||||
|
||||
static void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) {
|
||||
void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) {
|
||||
if (src == nullptr || dst == nullptr)
|
||||
return;
|
||||
memset(dst, 0, sizeof(OrbisNetSockaddr));
|
||||
@ -184,7 +184,7 @@ int PosixSocket::Listen(int backlog) {
|
||||
return ConvertReturnErrorCode(::listen(sock, backlog));
|
||||
}
|
||||
|
||||
static int convertOrbisFlagsToPosix(int sock_type, int sce_flags) {
|
||||
int convertOrbisFlagsToPosix(int sock_type, int sce_flags) {
|
||||
int posix_flags = 0;
|
||||
|
||||
if (sce_flags & ORBIS_NET_MSG_PEEK)
|
||||
|
||||
@ -57,6 +57,13 @@ struct Socket;
|
||||
|
||||
typedef std::shared_ptr<Socket> SocketPtr;
|
||||
|
||||
// Shared socket helper functions defined in posix_sockets.cpp
|
||||
int ConvertReturnErrorCode(int retval);
|
||||
int ConvertLevels(int level);
|
||||
void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst);
|
||||
void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst);
|
||||
int convertOrbisFlagsToPosix(int sock_type, int sce_flags);
|
||||
|
||||
struct OrbisNetLinger {
|
||||
s32 l_onoff;
|
||||
s32 l_linger;
|
||||
@ -126,10 +133,14 @@ struct PosixSocket : public Socket {
|
||||
};
|
||||
|
||||
struct P2PSocket : public Socket {
|
||||
explicit P2PSocket(int domain, int type, int protocol) : Socket(domain, type, protocol) {}
|
||||
bool IsValid() const override {
|
||||
return true;
|
||||
}
|
||||
net_socket sock;
|
||||
int sockopt_so_nbio = 0;
|
||||
int socket_type;
|
||||
u16 vport = 0; // PS4 virtual port
|
||||
|
||||
explicit P2PSocket(int domain, int type, int protocol);
|
||||
~P2PSocket() override;
|
||||
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;
|
||||
@ -146,7 +157,7 @@ struct P2PSocket : public Socket {
|
||||
int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override;
|
||||
int fstat(Libraries::Kernel::OrbisKernelStat* stat) override;
|
||||
std::optional<net_socket> Native() override {
|
||||
return {};
|
||||
return sock;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -15,123 +15,6 @@
|
||||
|
||||
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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user