diff --git a/CMakeLists.txt b/CMakeLists.txt index c1ec7b7b951..b7e34fccd71 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -310,6 +310,14 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp src/core/libraries/network/ssl.h src/core/libraries/network/ssl2.cpp src/core/libraries/network/ssl2.h + src/core/libraries/network/posix_sockets.cpp + src/core/libraries/network/p2p_sockets.cpp + src/core/libraries/network/sockets.h + src/core/libraries/network/net_error.h + src/core/libraries/network/epoll.cpp + src/core/libraries/network/epoll.h + src/core/libraries/network/net_util.cpp + src/core/libraries/network/net_util.h ) set(AVPLAYER_LIB src/core/libraries/avplayer/avplayer_common.cpp diff --git a/src/core/libraries/network/epoll.cpp b/src/core/libraries/network/epoll.cpp new file mode 100644 index 00000000000..da15cf37d8c --- /dev/null +++ b/src/core/libraries/network/epoll.cpp @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "epoll.h" +#include "net_error.h" + +namespace Libraries::Net { +int NetEpoll::Add(int id, net_socket sock, OrbisNetEpollEvent* ev) { + if (!eventEntries.try_emplace(id, EpollSocket{ev->events, ev->data, sock}).second) { + return ORBIS_NET_ERROR_EEXIST; + } + return 0; +} + +int NetEpoll::Del(int id, net_socket sock, OrbisNetEpollEvent* ev) { + if (eventEntries.erase(id) == 0) { + return ORBIS_NET_ERROR_ENOENT; + } + return 0; +} + +int NetEpoll::Mod(int id, net_socket sock, OrbisNetEpollEvent* ev) { + auto it = eventEntries.find(id); + if (it == eventEntries.end()) { + return ORBIS_NET_ERROR_ENOENT; + } + it->second.events = ev->events; + it->second.data = ev->data; + return 0; +} + +int NetEpoll::Wait(OrbisNetEpollEvent* events, int maxevents, int timeout) { + return 0; +} + +} // namespace Libraries::Net \ No newline at end of file diff --git a/src/core/libraries/network/epoll.h b/src/core/libraries/network/epoll.h new file mode 100644 index 00000000000..ec6b5c61da5 --- /dev/null +++ b/src/core/libraries/network/epoll.h @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" +#ifdef _WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#include +#include +#include +typedef SOCKET net_socket; +typedef int socklen_t; +#else +#include +#include +#include +#include +#include +#include +#include +#include +typedef int net_socket; +#endif +#include +#include +#include + +namespace Libraries::Net { + +union OrbisNetEpollData { + void* ptr; + u32 _u32; + int fd; + u64 _u64; +}; + +struct OrbisNetEpollEvent { + u32 events; + u32 reserved; + u32 ident; + OrbisNetEpollData data; +}; + +struct EpollSocket { + unsigned int events; + OrbisNetEpollData data; + net_socket sock; +}; + +enum SceNetEpollControlFlag : u32 { + ORBIS_NET_EPOLL_CTL_ADD = 1, + ORBIS_NET_EPOLL_CTL_MOD, + ORBIS_NET_EPOLL_CTL_DEL +}; + +struct NetEpoll { + std::map eventEntries; + + int Add(int id, net_socket sock, OrbisNetEpollEvent* ev); + int Del(int id, net_socket sock, OrbisNetEpollEvent* ev); + int Mod(int id, net_socket sock, OrbisNetEpollEvent* ev); + int Wait(OrbisNetEpollEvent* events, int maxevents, int timeout); +}; + +typedef std::shared_ptr EpollPtr; + +class NetEpollInternal { +public: + explicit NetEpollInternal() = default; + ~NetEpollInternal() = default; + EpollPtr FindEpoll(int sockid) { + std::scoped_lock lock{m_mutex}; + const auto it = epolls.find(sockid); + if (it != epolls.end()) { + return it->second; + } + return 0; + } + int EraseEpoll(int eid) { + std::scoped_lock lock{m_mutex}; + return epolls.erase(eid); + } + +public: + std::mutex m_mutex; + typedef std::map NetEpolls; + NetEpolls epolls; + int next_epool_sock_id = 0; +}; +} // namespace Libraries::Net \ No newline at end of file diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 161fc521476..332ecca9580 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -12,14 +12,25 @@ #include "common/assert.h" #include "common/logging/log.h" +#include "common/singleton.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/network/net.h" +#include "net_error.h" +#include "netctl.h" +#include "sockets.h" + namespace Libraries::Net { static thread_local int32_t net_errno = 0; +int setErrnoFromOrbis(int code) { + if (code != 0) { + net_errno = code + ORBIS_NET_ERROR_EPERM + 1; + } + return code; +} int PS4_SYSV_ABI in6addr_any() { LOG_ERROR(Lib_Net, "(STUBBED) called"); return ORBIS_OK; @@ -61,8 +72,21 @@ int PS4_SYSV_ABI sce_net_in6addr_nodelocal_allnodes() { } OrbisNetId PS4_SYSV_ABI sceNetAccept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; + auto* netcall = Common::Singleton::Instance(); + auto sock = netcall->FindSocket(s); + if (!sock) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); + return ORBIS_NET_ERROR_EBADF; + } + auto new_sock = sock->Accept(addr, paddrlen); + if (!new_sock) { + LOG_ERROR(Lib_Net, "error creating new socket for accepting"); + return -1; + } + auto id = ++netcall->next_sock_id; + netcall->socks.emplace(id, new_sock); + return id; } int PS4_SYSV_ABI sceNetAddrConfig6GetInfo() { @@ -121,8 +145,14 @@ int PS4_SYSV_ABI sceNetBandwidthControlSetPolicy() { } int PS4_SYSV_ABI sceNetBind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; + auto* netcall = Common::Singleton::Instance(); + auto sock = netcall->FindSocket(s); + if (!sock) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); + return ORBIS_NET_ERROR_EBADF; + } + return setErrnoFromOrbis(sock->Bind(addr, addrlen)); } int PS4_SYSV_ABI sceNetClearDnsCache() { @@ -545,18 +575,87 @@ int PS4_SYSV_ABI sceNetEpollAbort() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetEpollControl() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; -} +int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId eid, int op, OrbisNetId id, + OrbisNetEpollEvent* event) { + auto* net_epoll = Common::Singleton::Instance(); + auto epoll = net_epoll->FindEpoll(eid); + if (!epoll) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "epoll id is invalid = {}", eid); + return ORBIS_NET_ERROR_EBADF; + } + if (id == 100) { + UNREACHABLE_MSG("Hitted resolver id not supported"); + } + auto* socket_call = Common::Singleton::Instance(); + auto sock = socket_call->FindSocket(id); + if (!sock) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", id); + return ORBIS_NET_ERROR_EBADF; + } + auto posixSocket = std::dynamic_pointer_cast(sock); + if (!posixSocket) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "Can't create posix socket"); + return ORBIS_NET_ERROR_EBADF; + } -int PS4_SYSV_ABI sceNetEpollCreate() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; + switch (op) { + case ORBIS_NET_EPOLL_CTL_ADD: { + int add = epoll->Add(id, posixSocket->sock, event); + if (add == ORBIS_NET_ERROR_EEXIST) { + net_errno = ORBIS_NET_EEXIST; + LOG_ERROR(Lib_Net, "epoll event already added"); + return ORBIS_NET_ERROR_EEXIST; + } + return ORBIS_OK; + } + case ORBIS_NET_EPOLL_CTL_DEL: { + int del = epoll->Del(id, posixSocket->sock, event); + if (del == ORBIS_NET_ERROR_ENOENT) { + net_errno = ORBIS_NET_ENOENT; + LOG_ERROR(Lib_Net, "no epoll event in wait state"); + return ORBIS_NET_ERROR_ENOENT; + } + return ORBIS_OK; + } + case ORBIS_NET_EPOLL_CTL_MOD: { + int mod = epoll->Mod(id, posixSocket->sock, event); + if (mod == ORBIS_NET_ERROR_ENOENT) { + net_errno = ORBIS_NET_ENOENT; + LOG_ERROR(Lib_Net, "no epoll event in wait state"); + return ORBIS_NET_ERROR_ENOENT; + } + return ORBIS_OK; + } + default: + net_errno = ORBIS_NET_EINVAL; + LOG_ERROR(Lib_Net, "Unknown operation = {}", op); + return ORBIS_NET_ERROR_EINVAL; + } } -int PS4_SYSV_ABI sceNetEpollDestroy() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetEpollCreate(const char* name, int flags) { + if (name == nullptr) { + LOG_DEBUG(Lib_Net, "name = no-name flags= {}", flags); + } else { + LOG_DEBUG(Lib_Net, "name = {} flags= {}", std::string(name), flags); + } + auto* net_epoll = Common::Singleton::Instance(); + auto epoll = std::make_shared(); + auto id = ++net_epoll->next_epool_sock_id; + net_epoll->epolls.emplace(id, epoll); + return id; +} + +int PS4_SYSV_ABI sceNetEpollDestroy(int eid) { + auto* net_epoll = Common::Singleton::Instance(); + if (net_epoll->EraseEpoll(eid) == 0) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "Error deleting eid = {}", eid); + return ORBIS_NET_ERROR_EBADF; + } return ORBIS_OK; } @@ -640,8 +739,23 @@ int PS4_SYSV_ABI sceNetGetIfnameNumList() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetGetMacAddress() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetGetMacAddress(Libraries::NetCtl::OrbisNetEtherAddr* addr, int flags) { + if (addr == nullptr) { + LOG_ERROR(Lib_Net, "addr is null!"); + return ORBIS_NET_EINVAL; + } +#ifdef _WIN32 + IP_ADAPTER_INFO AdapterInfo[16]; + DWORD dwBufLen = sizeof(AdapterInfo); + if (GetAdaptersInfo(AdapterInfo, &dwBufLen) != ERROR_SUCCESS) { + LOG_ERROR(Lib_Net, "Can't retrieve adapter info"); + return ORBIS_NET_EINVAL; + } else { + memcpy(addr->data, AdapterInfo[0].Address, 6); + } +#else + LOG_ERROR(Lib_Net, "FixMe no support for MacOS,linux"); +#endif return ORBIS_OK; } @@ -781,9 +895,15 @@ int PS4_SYSV_ABI sceNetIoctl() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetListen() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetListen(OrbisNetId s, int backlog) { + auto* netcall = Common::Singleton::Instance(); + auto sock = netcall->FindSocket(s); + if (!sock) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); + return ORBIS_NET_ERROR_EBADF; + } + return setErrnoFromOrbis(sock->Listen(backlog)); } int PS4_SYSV_ABI sceNetMemoryAllocate() { @@ -836,8 +956,14 @@ int PS4_SYSV_ABI sceNetRecv() { int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, size_t len, int flags, OrbisNetSockaddr* addr, u32* paddrlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; + auto* netcall = Common::Singleton::Instance(); + auto sock = netcall->FindSocket(s); + if (!sock) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); + return ORBIS_NET_ERROR_EBADF; + } + return setErrnoFromOrbis(sock->ReceivePacket(buf, len, flags, addr, paddrlen)); } int PS4_SYSV_ABI sceNetRecvmsg() { @@ -870,9 +996,9 @@ int PS4_SYSV_ABI sceNetResolverConnectDestroy() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverCreate() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetResolverCreate(const char* name, int memid, int flags) { + LOG_ERROR(Lib_Net, "(DUMMY) name = {} memid ={} flags={}", std::string(name), memid, flags); + return 100; // return a fake resolver id } int PS4_SYSV_ABI sceNetResolverDestroy() { @@ -885,8 +1011,16 @@ int PS4_SYSV_ABI sceNetResolverGetError() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverStartAton() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetResolverStartAton(int rid, const u32* addr, char* hostname, int hostname_len, + int timeout, int retry, int flags) { + LOG_ERROR(Lib_Net, "rid = {} , hostname_len ={} timeout={} retry={} flags={}", rid, + hostname_len, timeout, retry, flags); + struct hostent* resolved = gethostbyaddr((const char*)addr, hostname_len, AF_INET); + if (resolved != nullptr) { + strcpy(hostname, resolved->h_name); + } else { + strcpy(hostname, "localhost"); // dummy + } return ORBIS_OK; } @@ -925,9 +1059,16 @@ int PS4_SYSV_ABI sceNetSendmsg() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetSendto() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u32 len, int flags, + const OrbisNetSockaddr* addr, u32 addrlen) { + auto* netcall = Common::Singleton::Instance(); + auto sock = netcall->FindSocket(s); + if (!sock) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); + return ORBIS_NET_ERROR_EBADF; + } + return setErrnoFromOrbis(sock->SendPacket(buf, len, flags, addr, addrlen)); } int PS4_SYSV_ABI sceNetSetDns6Info() { @@ -950,9 +1091,17 @@ int PS4_SYSV_ABI sceNetSetDnsInfoToKernel() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetSetsockopt() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval, + u32 optlen) { + LOG_INFO(Lib_Net, "s = {} level = {} optname = {} optlen = {}", s, level, optname, optlen); + auto* netcall = Common::Singleton::Instance(); + auto sock = netcall->FindSocket(s); + if (!sock) { + net_errno = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); + return ORBIS_NET_ERROR_EBADF; + } + return setErrnoFromOrbis(sock->SetSocketOptions(level, optname, optval, optlen)); } int PS4_SYSV_ABI sceNetShowIfconfig() { @@ -1040,9 +1189,32 @@ int PS4_SYSV_ABI sceNetShutdown() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +OrbisNetId PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol) { + if (name == nullptr) { + LOG_INFO(Lib_Net, "name = no-named family = {} type = {} protocol = {}", family, type, + protocol); + } else { + LOG_INFO(Lib_Net, "name = {} family = {} type = {} protocol = {}", std::string(name), + family, type, protocol); + } + SocketPtr sock; + switch (type) { + case ORBIS_NET_SOCK_STREAM: + case ORBIS_NET_SOCK_DGRAM: + case ORBIS_NET_SOCK_RAW: + sock = std::make_shared(family, type, protocol); + break; + case ORBIS_NET_SOCK_DGRAM_P2P: + case ORBIS_NET_SOCK_STREAM_P2P: + sock = std::make_shared(family, type, protocol); + break; + default: + UNREACHABLE_MSG("Unknown type {}", type); + } + auto* netcall = Common::Singleton::Instance(); + auto id = ++netcall->next_sock_id; + netcall->socks.emplace(id, sock); + return id; } int PS4_SYSV_ABI sceNetSocketAbort() { diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index beef38b5619..0d58dbebee0 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -4,6 +4,8 @@ #pragma once #include "common/types.h" +#include "epoll.h" +#include "netctl.h" namespace Core::Loader { class SymbolsResolver; @@ -21,12 +23,78 @@ namespace Libraries::Net { using OrbisNetId = s32; +enum OrbisNetProtocol : u32 { + ORBIS_NET_IPPROTO_IP = 0, + ORBIS_NET_IPPROTO_ICMP = 1, + ORBIS_NET_IPPROTO_IGMP = 2, + ORBIS_NET_IPPROTO_TCP = 6, + ORBIS_NET_IPPROTO_UDP = 17, + ORBIS_NET_SOL_SOCKET = 0xFFFF +}; + +enum OrbisNetSocketType : u32 { + ORBIS_NET_SOCK_STREAM = 1, + ORBIS_NET_SOCK_DGRAM = 2, + ORBIS_NET_SOCK_RAW = 3, + ORBIS_NET_SOCK_DGRAM_P2P = 6, + ORBIS_NET_SOCK_STREAM_P2P = 10 +}; + +enum OrbisNetSocketOption : u32 { + /* IP */ + ORBIS_NET_IP_HDRINCL = 2, + ORBIS_NET_IP_TOS = 3, + ORBIS_NET_IP_TTL = 4, + ORBIS_NET_IP_MULTICAST_IF = 9, + ORBIS_NET_IP_MULTICAST_TTL = 10, + ORBIS_NET_IP_MULTICAST_LOOP = 11, + ORBIS_NET_IP_ADD_MEMBERSHIP = 12, + ORBIS_NET_IP_DROP_MEMBERSHIP = 13, + ORBIS_NET_IP_TTLCHK = 23, + ORBIS_NET_IP_MAXTTL = 24, + /* TCP */ + ORBIS_NET_TCP_NODELAY = 1, + ORBIS_NET_TCP_MAXSEG = 2, + ORBIS_NET_TCP_MSS_TO_ADVERTISE = 3, + /* SOCKET */ + ORBIS_NET_SO_REUSEADDR = 0x00000004, + ORBIS_NET_SO_KEEPALIVE = 0x00000008, + ORBIS_NET_SO_BROADCAST = 0x00000020, + ORBIS_NET_SO_LINGER = 0x00000080, + ORBIS_NET_SO_REUSEPORT = 0x00000200, + ORBIS_NET_SO_ONESBCAST = 0x00010000, + ORBIS_NET_SO_USECRYPTO = 0x00020000, + ORBIS_NET_SO_USESIGNATURE = 0x00040000, + ORBIS_NET_SO_SNDBUF = 0x1001, + ORBIS_NET_SO_RCVBUF = 0x1002, + ORBIS_NET_SO_ERROR = 0x1007, + ORBIS_NET_SO_TYPE = 0x1008, + ORBIS_NET_SO_SNDTIMEO = 0x1105, + ORBIS_NET_SO_RCVTIMEO = 0x1106, + ORBIS_NET_SO_ERROR_EX = 0x1107, + ORBIS_NET_SO_ACCEPTTIMEO = 0x1108, + ORBIS_NET_SO_CONNECTTIMEO = 0x1109, + ORBIS_NET_SO_NBIO = 0x1200, + ORBIS_NET_SO_POLICY = 0x1201, + ORBIS_NET_SO_NAME = 0x1202, + ORBIS_NET_SO_PRIORITY = 0x1203 +}; + 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 in6addr_any(); int PS4_SYSV_ABI in6addr_loopback(); int PS4_SYSV_ABI sce_net_dummy(); @@ -132,9 +200,10 @@ int PS4_SYSV_ABI sceNetDumpRead(); int PS4_SYSV_ABI sceNetDuplicateIpStart(); int PS4_SYSV_ABI sceNetDuplicateIpStop(); int PS4_SYSV_ABI sceNetEpollAbort(); -int PS4_SYSV_ABI sceNetEpollControl(); -int PS4_SYSV_ABI sceNetEpollCreate(); -int PS4_SYSV_ABI sceNetEpollDestroy(); +int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId eid, int op, OrbisNetId id, + OrbisNetEpollEvent* event); +int PS4_SYSV_ABI sceNetEpollCreate(const char* name, int flags); +int PS4_SYSV_ABI sceNetEpollDestroy(int eid); int PS4_SYSV_ABI sceNetEpollWait(); int* PS4_SYSV_ABI sceNetErrnoLoc(); int PS4_SYSV_ABI sceNetEtherNtostr(); @@ -151,7 +220,7 @@ int PS4_SYSV_ABI sceNetGetIfList(); int PS4_SYSV_ABI sceNetGetIfListOnce(); int PS4_SYSV_ABI sceNetGetIfName(); int PS4_SYSV_ABI sceNetGetIfnameNumList(); -int PS4_SYSV_ABI sceNetGetMacAddress(); +int PS4_SYSV_ABI sceNetGetMacAddress(Libraries::NetCtl::OrbisNetEtherAddr* addr, int flags); int PS4_SYSV_ABI sceNetGetMemoryPoolStats(); int PS4_SYSV_ABI sceNetGetNameToIndex(); int PS4_SYSV_ABI sceNetGetpeername(); @@ -177,7 +246,7 @@ int PS4_SYSV_ABI sceNetInfoDumpStop(); int PS4_SYSV_ABI sceNetInit(); int PS4_SYSV_ABI sceNetInitParam(); int PS4_SYSV_ABI sceNetIoctl(); -int PS4_SYSV_ABI sceNetListen(); +int PS4_SYSV_ABI sceNetListen(OrbisNetId s, int backlog); int PS4_SYSV_ABI sceNetMemoryAllocate(); int PS4_SYSV_ABI sceNetMemoryFree(); u32 PS4_SYSV_ABI sceNetNtohl(u32 net32); @@ -196,10 +265,11 @@ int PS4_SYSV_ABI sceNetResolverConnect(); int PS4_SYSV_ABI sceNetResolverConnectAbort(); int PS4_SYSV_ABI sceNetResolverConnectCreate(); int PS4_SYSV_ABI sceNetResolverConnectDestroy(); -int PS4_SYSV_ABI sceNetResolverCreate(); +int PS4_SYSV_ABI sceNetResolverCreate(const char* name, int memid, int flags); int PS4_SYSV_ABI sceNetResolverDestroy(); int PS4_SYSV_ABI sceNetResolverGetError(); -int PS4_SYSV_ABI sceNetResolverStartAton(); +int PS4_SYSV_ABI sceNetResolverStartAton(int rid, const u32* addr, char* hostname, int hostname_len, + int timeout, int retry, int flags); int PS4_SYSV_ABI sceNetResolverStartAton6(); int PS4_SYSV_ABI sceNetResolverStartNtoa(); int PS4_SYSV_ABI sceNetResolverStartNtoa6(); @@ -207,12 +277,14 @@ int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(); int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx(); int PS4_SYSV_ABI sceNetSend(); int PS4_SYSV_ABI sceNetSendmsg(); -int PS4_SYSV_ABI sceNetSendto(); +int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u32 len, int flags, + const OrbisNetSockaddr* addr, u32 addrlen); int PS4_SYSV_ABI sceNetSetDns6Info(); int PS4_SYSV_ABI sceNetSetDns6InfoToKernel(); int PS4_SYSV_ABI sceNetSetDnsInfo(); int PS4_SYSV_ABI sceNetSetDnsInfoToKernel(); -int PS4_SYSV_ABI sceNetSetsockopt(); +int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval, + u32 optlen); int PS4_SYSV_ABI sceNetShowIfconfig(); int PS4_SYSV_ABI sceNetShowIfconfigForBuffer(); int PS4_SYSV_ABI sceNetShowIfconfigWithMemory(); @@ -230,7 +302,7 @@ int PS4_SYSV_ABI sceNetShowRoute6WithMemory(); int PS4_SYSV_ABI sceNetShowRouteForBuffer(); int PS4_SYSV_ABI sceNetShowRouteWithMemory(); int PS4_SYSV_ABI sceNetShutdown(); -int PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol); +OrbisNetId PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol); int PS4_SYSV_ABI sceNetSocketAbort(); int PS4_SYSV_ABI sceNetSocketClose(); int PS4_SYSV_ABI sceNetSyncCreate(); diff --git a/src/core/libraries/network/net_error.h b/src/core/libraries/network/net_error.h new file mode 100644 index 00000000000..fd2f4035136 --- /dev/null +++ b/src/core/libraries/network/net_error.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +// net errno codes +constexpr int ORBIS_NET_ENOENT = 2; +constexpr int ORBIS_NET_EBADF = 9; +constexpr int ORBIS_NET_EFAULT = 14; +constexpr int ORBIS_NET_EEXIST = 17; +constexpr int ORBIS_NET_EINVAL = 22; + +// error codes +constexpr int ORBIS_NET_ERROR_EPERM = 0x80410101; +constexpr int ORBIS_NET_ERROR_ENOENT = 0x80410102; +constexpr int ORBIS_NET_ERROR_EBADF = 0x80410109; +constexpr int ORBIS_NET_ERROR_EFAULT = 0x8041010e; +constexpr int ORBIS_NET_ERROR_EEXIST = 0x80410111; +constexpr int ORBIS_NET_ERROR_EINVAL = 0x80410116; +constexpr int ORBIS_NET_ERROR_ENOPROTOOPT = 0x8041012a; diff --git a/src/core/libraries/network/net_obj.cpp b/src/core/libraries/network/net_obj.cpp deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/core/libraries/network/net_obj.h b/src/core/libraries/network/net_obj.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp new file mode 100644 index 00000000000..d0f0a81da89 --- /dev/null +++ b/src/core/libraries/network/net_util.cpp @@ -0,0 +1,110 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifdef _WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#include +#include +#include +typedef SOCKET net_socket; +typedef int socklen_t; +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +typedef int net_socket; +#endif +#if defined(__APPLE__) +#include +#include +#endif + +#include +#include +#include +#include +#include +#include "net_util.h" + +namespace NetUtil { + +const std::array& NetUtilInternal::GetEthernetAddr() const { + return ether_address; +} + +bool NetUtilInternal::RetrieveEthernetAddr() { + std::scoped_lock lock{m_mutex}; +#ifdef _WIN32 + std::vector adapter_infos(sizeof(IP_ADAPTER_INFO)); + ULONG size_infos = sizeof(IP_ADAPTER_INFO); + + if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), &size_infos) == + ERROR_BUFFER_OVERFLOW) + adapter_infos.resize(size_infos); + + if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), &size_infos) == + NO_ERROR && + size_infos) { + PIP_ADAPTER_INFO info = reinterpret_cast(adapter_infos.data()); + memcpy(ether_address.data(), info[0].Address, 6); + return true; + } +#elif defined(__APPLE__) + ifaddrs* ifap; + + if (getifaddrs(&ifap) == 0) { + ifaddrs* p; + for (p = ifap; p; p = p->ifa_next) { + if (p->ifa_addr->sa_family == AF_LINK) { + sockaddr_dl* sdp = reinterpret_cast(p->ifa_addr); + memcpy(ether_address.data(), sdp->sdl_data + sdp->sdl_nlen, 6); + freeifaddrs(ifap); + return true; + } + } + freeifaddrs(ifap); + } +#else + ifreq ifr; + ifconf ifc; + char buf[1024]; + int success = 0; + + int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sock == -1) + return false; + + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) + return false; + + ifreq* it = ifc.ifc_req; + const ifreq* const end = it + (ifc.ifc_len / sizeof(ifreq)); + + for (; it != end; ++it) { + strcpy(ifr.ifr_name, it->ifr_name); + if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) { + if (!(ifr.ifr_flags & IFF_LOOPBACK)) { + if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) { + success = 1; + break; + } + } + } + } + + if (success) { + memcpy(ether_address.data(), ifr.ifr_hwaddr.sa_data, 6); + return true; + } +#endif + return false; +} +} // namespace NetUtil \ No newline at end of file diff --git a/src/core/libraries/network/net_util.h b/src/core/libraries/network/net_util.h new file mode 100644 index 00000000000..be9dc15a1f1 --- /dev/null +++ b/src/core/libraries/network/net_util.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "common/types.h" + +namespace NetUtil { + +class NetUtilInternal { +public: + explicit NetUtilInternal() = default; + ~NetUtilInternal() = default; + +private: + std::array ether_address{}; + std::mutex m_mutex; + +public: + const std::array& GetEthernetAddr() const; + bool RetrieveEthernetAddr(); +}; +} // namespace NetUtil \ No newline at end of file diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 00d980663ae..e3afd6ddee5 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -12,11 +12,13 @@ #include #endif +#include #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/network/net_ctl_codes.h" #include "core/libraries/network/netctl.h" +#include "net_util.h" namespace Libraries::NetCtl { @@ -162,6 +164,11 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { case ORBIS_NET_CTL_INFO_DEVICE: info->device = ORBIS_NET_CTL_DEVICE_WIRED; break; + case ORBIS_NET_CTL_INFO_ETHER_ADDR: { + auto* netinfo = Common::Singleton::Instance(); + netinfo->RetrieveEthernetAddr(); + memcpy(info->ether_addr.data, netinfo->GetEthernetAddr().data(), 6); + } break; case ORBIS_NET_CTL_INFO_LINK: info->link = ORBIS_NET_CTL_LINK_DISCONNECTED; break; @@ -181,8 +188,10 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { } } } + } break; + case ORBIS_NET_CTL_INFO_MTU: + info->mtu = 1500; // default value break; - } default: LOG_ERROR(Lib_NetCtl, "{} unsupported code", code); } diff --git a/src/core/libraries/network/netctl.h b/src/core/libraries/network/netctl.h index 4992fffa9b6..203c75822da 100644 --- a/src/core/libraries/network/netctl.h +++ b/src/core/libraries/network/netctl.h @@ -49,8 +49,26 @@ union OrbisNetCtlInfo { // GetInfo codes constexpr int ORBIS_NET_CTL_INFO_DEVICE = 1; +constexpr int ORBIS_NET_CTL_INFO_ETHER_ADDR = 2; +constexpr int ORBIS_NET_CTL_INFO_MTU = 3; constexpr int ORBIS_NET_CTL_INFO_LINK = 4; +constexpr int ORBIS_NET_CTL_INFO_BSSID = 5; +constexpr int ORBIS_NET_CTL_INFO_SSID = 6; +constexpr int ORBIS_NET_CTL_INFO_WIFI_SECURITY = 7; +constexpr int ORBIS_NET_CTL_INFO_RSSI_DBM = 8; +constexpr int ORBIS_NET_CTL_INFO_RSSI_PERCENTAGE = 9; +constexpr int ORBIS_NET_CTL_INFO_CHANNEL = 10; +constexpr int ORBIS_NET_CTL_INFO_IP_CONFIG = 11; +constexpr int ORBIS_NET_CTL_INFO_DHCP_HOSTNAME = 12; +constexpr int ORBIS_NET_CTL_INFO_PPPOE_AUTH_NAME = 13; constexpr int ORBIS_NET_CTL_INFO_IP_ADDRESS = 14; +constexpr int ORBIS_NET_CTL_INFO_NETMASK = 15; +constexpr int ORBIS_NET_CTL_INFO_DEFAULT_ROUTE = 16; +constexpr int ORBIS_NET_CTL_INFO_PRIMARY_DNS = 17; +constexpr int ORBIS_NET_CTL_INFO_SECONDARY_DNS = 18; +constexpr int ORBIS_NET_CTL_INFO_HTTP_PROXY_CONFIG = 19; +constexpr int ORBIS_NET_CTL_INFO_HTTP_PROXY_SERVER = 20; +constexpr int ORBIS_NET_CTL_INFO_HTTP_PROXY_PORT = 21; int PS4_SYSV_ABI sceNetBweCheckCallbackIpcInt(); int PS4_SYSV_ABI sceNetBweClearEventIpcInt(); diff --git a/src/core/libraries/network/p2p_sockets.cpp b/src/core/libraries/network/p2p_sockets.cpp new file mode 100644 index 00000000000..584d22f4baa --- /dev/null +++ b/src/core/libraries/network/p2p_sockets.cpp @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "net.h" +#include "net_error.h" +#include "sockets.h" + +namespace Libraries::Net { +int P2PSocket::SetSocketOptions(int level, int optname, const void* optval, unsigned int optlen) { + return 0; +} + +int P2PSocket::Bind(const OrbisNetSockaddr* addr, unsigned int addrlen) { + return 0; +} + +int P2PSocket::Listen(int backlog) { + return 0; +} + +int P2PSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to, + u32 tolen) { + return -1; // fake value makes peggle2 work +} + +int P2PSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) { + return -1; // fake it +} + +SocketPtr P2PSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) { + return nullptr; +} + +} // namespace Libraries::Net \ No newline at end of file diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp new file mode 100644 index 00000000000..c5b74aab0ed --- /dev/null +++ b/src/core/libraries/network/posix_sockets.cpp @@ -0,0 +1,179 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "net.h" +#include "net_error.h" +#include "sockets.h" + +namespace Libraries::Net { + +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; + } + return -1; +} + +static int ConvertReturnErrorCode(int retval) { + if (retval < 0) { +#ifdef _WIN32 + int err = WSAGetLastError(); + LOG_ERROR(Lib_Net, "Error occured {}", err); + switch (err) { + case WSAENOPROTOOPT: + return ORBIS_NET_ERROR_ENOPROTOOPT; + case WSAEINVAL: + return ORBIS_NET_ERROR_EINVAL; +#else + LOG_ERROR(Lib_Net, "Error occured {}", errno); + switch (errno) { + case ENOPROTOOPT: + return ORBIS_NET_ERROR_ENOPROTOOPT; + case EINVAL: + return ORBIS_NET_ERROR_EINVAL; +#endif + } + UNREACHABLE_MSG("Function returned an errorCode = {}", retval); + } + // if it is 0 or positive return it as it is + return retval; +} + +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); +} + +static void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) { + if (src == nullptr || dst == nullptr) + return; + memset(dst, 0, sizeof(OrbisNetSockaddr)); + OrbisNetSockaddrIn* dst_in = (OrbisNetSockaddrIn*)dst; + sockaddr_in* src_in = (sockaddr_in*)src; + dst_in->sin_family = static_cast(src_in->sin_family); + dst_in->sin_port = src_in->sin_port; + memcpy(&dst_in->sin_addr, &src_in->sin_addr, 4); +} + +int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, unsigned int optlen) { + level = ConvertLevels(level); + if (level == SOL_SOCKET) { + switch (optname) { + case ORBIS_NET_SO_REUSEADDR: + return ConvertReturnErrorCode( + setsockopt(sock, level, SO_REUSEADDR, (const char*)optval, optlen)); + case ORBIS_NET_SO_BROADCAST: + return ConvertReturnErrorCode( + setsockopt(sock, level, SO_BROADCAST, (const char*)optval, optlen)); + case ORBIS_NET_SO_SNDTIMEO: + return ConvertReturnErrorCode( + setsockopt(sock, level, SO_SNDTIMEO, (const char*)optval, optlen)); + case ORBIS_NET_SO_SNDBUF: + return ConvertReturnErrorCode( + setsockopt(sock, level, SO_SNDBUF, (const char*)optval, optlen)); + case ORBIS_NET_SO_RCVBUF: + return ConvertReturnErrorCode( + setsockopt(sock, level, SO_RCVBUF, (const char*)optval, optlen)); + case ORBIS_NET_SO_LINGER: + return ConvertReturnErrorCode( + setsockopt(sock, level, SO_LINGER, (const char*)optval, optlen)); + case ORBIS_NET_SO_ONESBCAST: { + if (optlen != sizeof(sockopt_so_onesbcast)) { + return ORBIS_NET_ERROR_EFAULT; + } + memcpy(&sockopt_so_onesbcast, optval, optlen); + return 0; + } + case ORBIS_NET_SO_NBIO: { + if (optlen != sizeof(sockopt_so_nbio)) { + return ORBIS_NET_ERROR_EFAULT; + } + memcpy(&sockopt_so_nbio, optval, optlen); +#ifdef _WIN32 + return ConvertReturnErrorCode(ioctlsocket(sock, FIONBIO, (u_long*)&sockopt_so_nbio)); +#else + return ConvertReturnErrorCode(ioctl(sock, FIONBIO, &sockopt_so_nbio)); +#endif + } + } + } + if (level == IPPROTO_TCP) { + switch (optname) { + case ORBIS_NET_TCP_NODELAY: + return ConvertReturnErrorCode( + setsockopt(sock, level, TCP_NODELAY, (const char*)optval, optlen)); + } + } + if (level == IPPROTO_IP) { + switch (optname) { + case ORBIS_NET_IP_HDRINCL: + return ConvertReturnErrorCode( + setsockopt(sock, level, IP_HDRINCL, (const char*)optval, optlen)); + } + } + UNREACHABLE_MSG("Unknown level ={} optname ={}", level, optname); + return 0; +} +int PosixSocket::Bind(const OrbisNetSockaddr* addr, unsigned int addrlen) { + sockaddr addr2; + convertOrbisNetSockaddrToPosix(addr, &addr2); + return ConvertReturnErrorCode(::bind(sock, &addr2, sizeof(sockaddr_in))); +} + +int PosixSocket::Listen(int backlog) { + return ConvertReturnErrorCode(::listen(sock, backlog)); +} + +int PosixSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to, + u32 tolen) { + if (to != nullptr) { + sockaddr addr; + convertOrbisNetSockaddrToPosix(to, &addr); + return ConvertReturnErrorCode( + sendto(sock, (const char*)msg, len, flags, &addr, sizeof(sockaddr_in))); + } else { + return ConvertReturnErrorCode(send(sock, (const char*)msg, len, flags)); + } +} + +int PosixSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, + u32* fromlen) { + if (from != nullptr) { + sockaddr addr; + int res = recvfrom(sock, (char*)buf, len, flags, &addr, (socklen_t*)fromlen); + convertPosixSockaddrToOrbis(&addr, from); + *fromlen = sizeof(OrbisNetSockaddrIn); + return ConvertReturnErrorCode(res); + } else { + return ConvertReturnErrorCode(recv(sock, (char*)buf, len, flags)); + } +} + +SocketPtr PosixSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) { + sockaddr addr2; + net_socket new_socket = ::accept(sock, &addr2, (socklen_t*)addrlen); +#ifdef _WIN32 + if (new_socket != INVALID_SOCKET) { +#else + if (new_socket >= 0) { +#endif + convertPosixSockaddrToOrbis(&addr2, addr); + *addrlen = sizeof(OrbisNetSockaddrIn); + return std::make_shared(new_socket); + } + return nullptr; +} + +} // namespace Libraries::Net \ No newline at end of file diff --git a/src/core/libraries/network/sockets.h b/src/core/libraries/network/sockets.h new file mode 100644 index 00000000000..c0212c6dfa8 --- /dev/null +++ b/src/core/libraries/network/sockets.h @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#ifdef _WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#include +#include +#include +typedef SOCKET net_socket; +typedef int socklen_t; +#else +#include +#include +#include +#include +#include +#include +#include +#include +typedef int net_socket; +#endif +#include +#include +#include + +namespace Libraries::Net { + +struct Socket; + +typedef std::shared_ptr SocketPtr; + +struct Socket { + explicit Socket(int domain, int type, int protocol) {} + virtual ~Socket() = default; + virtual int SetSocketOptions(int level, int optname, const void* optval, + unsigned int optlen) = 0; + virtual int Bind(const OrbisNetSockaddr* addr, unsigned int addrlen) = 0; + virtual int Listen(int backlog) = 0; + virtual int SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to, + u32 tolen) = 0; + virtual SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) = 0; + virtual int ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, + u32* fromlen) = 0; +}; + +struct PosixSocket : public Socket { + net_socket sock; + int sockopt_so_nbio = 0; + int sockopt_so_onesbcast = 0; + explicit PosixSocket(int domain, int type, int protocol) + : Socket(domain, type, protocol), sock(socket(domain, type, protocol)) {} + explicit PosixSocket(net_socket sock) : Socket(0, 0, 0), sock(sock) {} + int SetSocketOptions(int level, int optname, const void* optval, unsigned int optlen) override; + int Bind(const OrbisNetSockaddr* addr, unsigned int addrlen) override; + int Listen(int backlog) override; + int SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to, + u32 tolen) override; + int ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) override; + SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override; +}; + +struct P2PSocket : public Socket { + explicit P2PSocket(int domain, int type, int protocol) : Socket(domain, type, protocol) {} + int SetSocketOptions(int level, int optname, const void* optval, unsigned int optlen) override; + int Bind(const OrbisNetSockaddr* addr, unsigned int addrlen) override; + int Listen(int backlog) override; + int SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to, + u32 tolen) override; + int ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) override; + SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override; +}; + +class NetInternal { +public: + explicit NetInternal() = default; + ~NetInternal() = default; + SocketPtr FindSocket(int sockid) { + std::scoped_lock lock{m_mutex}; + const auto it = socks.find(sockid); + if (it != socks.end()) { + return it->second; + } + return 0; + } + +public: + std::mutex m_mutex; + typedef std::map NetSockets; + NetSockets socks; + int next_sock_id = 0; +}; +} // namespace Libraries::Net \ No newline at end of file diff --git a/src/emulator.cpp b/src/emulator.cpp index cd981add2ae..a2926131e18 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -16,6 +16,9 @@ #ifdef ENABLE_DISCORD_RPC #include "common/discord_rpc_handler.h" #endif +#ifdef _WIN32 +#include +#endif #include "common/elf_info.h" #include "common/ntapi.h" #include "common/path_util.h" @@ -48,6 +51,10 @@ Emulator::Emulator() { #ifdef _WIN32 Common::NtApi::Initialize(); SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); + // need to init this in order for winsock2 to work + WORD versionWanted = MAKEWORD(2, 2); + WSADATA wsaData; + WSAStartup(versionWanted, &wsaData); #endif // Start logger.