mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Translate all input parameters to socket().
This commit is contained in:
parent
66b801c1ef
commit
4bc79481da
2 changed files with 258 additions and 76 deletions
|
@ -203,34 +203,59 @@ static int setBlockingMode(int nativeSocketId, bool nonblocking) {
|
|||
}
|
||||
|
||||
static int sceNetInetInit() {
|
||||
ERROR_LOG(SCENET, "UNTESTED sceNetInetInit()");
|
||||
return SceNetInet::Init() ? 0 : ERROR_NET_INET_ALREADY_INITIALIZED;
|
||||
ERROR_LOG(SCENET, "UNTESTED sceNetInetInit()");
|
||||
return SceNetInet::Init() ? 0 : ERROR_NET_INET_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
int sceNetInetTerm() {
|
||||
ERROR_LOG(SCENET, "UNTESTED sceNetInetTerm()");
|
||||
ERROR_LOG(SCENET, "UNTESTED sceNetInetTerm()");
|
||||
SceNetInet::Shutdown();
|
||||
return 0;
|
||||
return hleLogSuccessI(SCENET, 0);
|
||||
}
|
||||
|
||||
static int sceNetInetSocket(int domain, int type, int protocol) {
|
||||
WARN_LOG_ONCE(sceNetInetSocket, SCENET, "UNTESTED sceNetInetSocket(%i, %i, %i)", domain, type, protocol);
|
||||
static int sceNetInetSocket(int inetAddressFamily, int inetType, int inetProtocol) {
|
||||
WARN_LOG_ONCE(sceNetInetSocket, SCENET, "UNTESTED sceNetInetSocket(%i, %i, %i)", inetAddressFamily, inetType, inetProtocol);
|
||||
auto sceNetInet = SceNetInet::Get();
|
||||
if (!sceNetInet) {
|
||||
return hleLogError(SCENET, ERROR_NET_INET_CONFIG_INVALID_ARG, "Inet Subsystem Not Running - Use sceNetInetInit");
|
||||
}
|
||||
|
||||
// TODO: translate domain, type and protocol if applicable
|
||||
// Translate address family, type, and protocol. There is some complexity around the type in particular where
|
||||
// flags are able to be encoded in the most significant bits.
|
||||
|
||||
int nativeAddressFamily;
|
||||
if (!SceNetInet::TranslateInetAddressFamilyToNative(nativeAddressFamily, inetAddressFamily)) {
|
||||
sceNetInet->SetLastError(EAFNOSUPPORT);
|
||||
return hleLogError(SCENET, -1, "%s: Unable to translate inet address family %i", __func__, inetAddressFamily);
|
||||
}
|
||||
|
||||
int nativeType;
|
||||
bool nonBlocking;
|
||||
if (!SceNetInet::TranslateInetSocketTypeToNative(nativeType, nonBlocking, inetType)) {
|
||||
sceNetInet->SetLastError(EINVAL);
|
||||
return hleLogError(SCENET, -1, "%s: Unable to translate inet type %08x", __func__, inetType);
|
||||
}
|
||||
|
||||
int nativeProtocol;
|
||||
if (!SceNetInet::TranslateInetProtocolToNative(nativeProtocol, inetProtocol)) {
|
||||
sceNetInet->SetLastError(EPROTONOSUPPORT);
|
||||
return hleLogError(SCENET, -1, "%s: Unable to translate inet protocol %i", __func__, inetProtocol);
|
||||
}
|
||||
|
||||
// Attempt to open socket
|
||||
const int nativeSocketId = socket(domain, type, protocol);
|
||||
const int nativeSocketId = socket(nativeAddressFamily, nativeType, nativeProtocol);
|
||||
if (nativeSocketId < 0) {
|
||||
const auto error = sceNetInet->SetLastErrorToMatchPlatform();
|
||||
return hleLogError(SCENET, -1, "%s: Unable to open socket(%i, %i, %i) with error %i: %s", __func__, domain, type, protocol, error, strerror(error));
|
||||
return hleLogError(SCENET, -1, "%s: Unable to open socket(%i, %i, %i) with error %i: %s", __func__, nativeAddressFamily, nativeType, nativeProtocol, error, strerror(error));
|
||||
}
|
||||
|
||||
// Map opened socket to an inet socket which is 1-indexed
|
||||
const auto inetSocket = sceNetInet->CreateAndAssociateInetSocket(nativeSocketId);
|
||||
const auto inetSocket = sceNetInet->CreateAndAssociateInetSocket(nativeSocketId, nonBlocking);
|
||||
|
||||
// Set non-blocking mode since the translation function does not translate non-blocking mode due to platform incompatibilities
|
||||
if (nonBlocking) {
|
||||
setBlockingMode(nativeSocketId, true);
|
||||
}
|
||||
|
||||
// Close opened socket if such a socket exists
|
||||
if (!inetSocket) {
|
||||
|
@ -241,8 +266,8 @@ static int sceNetInetSocket(int domain, int type, int protocol) {
|
|||
return inetSocket->GetInetSocketId();
|
||||
}
|
||||
|
||||
static int sceNetInetGetsockopt(int socket, int level, int inetOptname, u32 optvalPtr, u32 optlenPtr) {
|
||||
WARN_LOG(SCENET, "UNTESTED sceNetInetGetsockopt(%i, %i, %i, %08x, %08x)", socket, level, inetOptname, optvalPtr, optlenPtr);
|
||||
static int sceNetInetGetsockopt(int socket, int inetSocketLevel, int inetOptname, u32 optvalPtr, u32 optlenPtr) {
|
||||
WARN_LOG(SCENET, "UNTESTED sceNetInetGetsockopt(%i, %i, %i, %08x, %08x)", socket, inetSocketLevel, inetOptname, optvalPtr, optlenPtr);
|
||||
|
||||
const auto sceNetInet = SceNetInet::Get();
|
||||
if (!sceNetInet) {
|
||||
|
@ -255,6 +280,14 @@ static int sceNetInetGetsockopt(int socket, int level, int inetOptname, u32 optv
|
|||
return hleLogError(SCENET, -1, "%s: Attempting to operate on unmapped socket %i", __func__, socket);
|
||||
}
|
||||
|
||||
const auto nativeSocketId = inetSocket->GetNativeSocketId();
|
||||
|
||||
int nativeSocketLevel;
|
||||
if (!SceNetInet::TranslateInetSocketLevelToNative(nativeSocketLevel, inetSocketLevel)) {
|
||||
sceNetInet->SetLastError(EINVAL);
|
||||
return hleLogError(SCENET, -1, "[%i] %s: Unknown socket level %04x", nativeSocketId, __func__, inetSocketLevel);
|
||||
}
|
||||
|
||||
if (!inetSocket->IsSockoptNameAllowed(inetOptname)) {
|
||||
sceNetInet->SetLastError(EINVAL);
|
||||
return hleLogError(SCENET, ERROR_NET_INET_CONFIG_INVALID_ARG, "Unknown optname %04x", inetOptname);
|
||||
|
@ -265,8 +298,6 @@ static int sceNetInetGetsockopt(int socket, int level, int inetOptname, u32 optv
|
|||
DEBUG_LOG(SCENET, "sceNetInetSetsockopt: Translated optname %04x into %04x", inetOptname, optname);
|
||||
}
|
||||
|
||||
const auto nativeSocketId = inetSocket->GetNativeSocketId();
|
||||
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
auto optlen = reinterpret_cast<int*>(Memory::GetPointerWrite(optlenPtr));
|
||||
#else
|
||||
|
@ -283,18 +314,31 @@ static int sceNetInetGetsockopt(int socket, int level, int inetOptname, u32 optv
|
|||
return hleLogError(SCENET, -1, "[%i] %s: Invalid pointer range %08x (size %i)", nativeSocketId, __func__, optvalPtr, *optlen);
|
||||
}
|
||||
|
||||
// TODO: implement non-blocking getsockopt
|
||||
// TODO: implement SOL
|
||||
const int ret = getsockopt(nativeSocketId, SOL_SOCKET, optname, optval, optlen);
|
||||
if (ret < 0) {
|
||||
const auto error = sceNetInet->SetLastErrorToMatchPlatform();
|
||||
return hleLogError(SCENET, ret, "[%i] %s: returned error %i: %s", nativeSocketId, __func__, error, strerror(error));
|
||||
switch (optname) {
|
||||
// No direct equivalents
|
||||
case INET_SO_NONBLOCK: {
|
||||
if (*optlen != sizeof(u32)) {
|
||||
sceNetInet->SetLastError(EFAULT);
|
||||
return hleLogError(SCENET, -1, "[%i] %s: Invalid optlen %i for INET_SO_NONBLOCK", nativeSocketId, __func__, *optlen);
|
||||
}
|
||||
Memory::Write_U32(optvalPtr, inetSocket->IsNonBlocking() ? 1 : 0);
|
||||
return hleLogSuccessI(SCENET, 0);
|
||||
}
|
||||
// Direct 1:1 mappings
|
||||
default: {
|
||||
// TODO: implement non-blocking getsockopt
|
||||
const int ret = getsockopt(nativeSocketId, nativeSocketLevel, optname, optval, optlen);
|
||||
if (ret < 0) {
|
||||
const auto error = sceNetInet->SetLastErrorToMatchPlatform();
|
||||
return hleLogError(SCENET, ret, "[%i] %s: returned error %i: %s", nativeSocketId, __func__, error, strerror(error));
|
||||
}
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sceNetInetSetsockopt(int socket, int level, int inetOptname, u32 optvalPtr, int optlen) {
|
||||
WARN_LOG_ONCE(sceNetInetSetsockopt, SCENET, "UNTESTED sceNetInetSetsockopt(%i, %i, %i, %08x, %i)", socket, level, inetOptname, optvalPtr, optlen);
|
||||
static int sceNetInetSetsockopt(int socket, int inetSocketLevel, int inetOptname, u32 optvalPtr, int optlen) {
|
||||
WARN_LOG_ONCE(sceNetInetSetsockopt, SCENET, "UNTESTED sceNetInetSetsockopt(%i, %i, %i, %08x, %i)", socket, inetSocketLevel, inetOptname, optvalPtr, optlen);
|
||||
|
||||
const auto sceNetInet = SceNetInet::Get();
|
||||
if (!sceNetInet) {
|
||||
|
@ -309,6 +353,12 @@ static int sceNetInetSetsockopt(int socket, int level, int inetOptname, u32 optv
|
|||
|
||||
const auto nativeSocketId = inetSocket->GetNativeSocketId();
|
||||
|
||||
int nativeSocketLevel;
|
||||
if (!SceNetInet::TranslateInetSocketLevelToNative(nativeSocketLevel, inetSocketLevel)) {
|
||||
sceNetInet->SetLastError(EINVAL);
|
||||
return hleLogError(SCENET, -1, "[%i] %s: Unknown socket level %04x", nativeSocketId, __func__, inetSocketLevel);
|
||||
}
|
||||
|
||||
if (!inetSocket->IsSockoptNameAllowed(inetOptname)) {
|
||||
sceNetInet->SetLastError(EINVAL);
|
||||
return hleLogError(SCENET, -1, "[%i] %s: Unknown optname %04x", nativeSocketId, __func__, inetOptname);
|
||||
|
@ -331,7 +381,7 @@ static int sceNetInetSetsockopt(int socket, int level, int inetOptname, u32 optv
|
|||
}
|
||||
|
||||
auto optval = Memory::Read_U32(optvalPtr);
|
||||
DEBUG_LOG(SCENET, "[%i] setsockopt(%i, %i, %i, %i)", nativeSocketId, nativeSocketId, level, optname, optval);
|
||||
DEBUG_LOG(SCENET, "[%i] setsockopt(%i, %i, %i, %i)", nativeSocketId, nativeSocketId, nativeSocketLevel, optname, optval);
|
||||
|
||||
switch (optname) {
|
||||
// Unmatched PSP functions - no direct equivalent
|
||||
|
@ -343,18 +393,18 @@ static int sceNetInetSetsockopt(int socket, int level, int inetOptname, u32 optv
|
|||
const auto error = sceNetInet->SetLastErrorToMatchPlatform();
|
||||
ERROR_LOG(SCENET, "[%i] %s: Failed to set to non-blocking with error %i: %s", nativeSocketId, __func__, error, strerror(error));
|
||||
}
|
||||
return 0;
|
||||
return hleLogSuccessI(SCENET, 0);
|
||||
}
|
||||
// Functions with identical structs to native functions
|
||||
default: {
|
||||
INFO_LOG(SCENET, "UNTESTED sceNetInetSetsockopt(%i, %i, %i, %u, %i)", nativeSocketId, level, optname, optval, 4);
|
||||
const int ret = setsockopt(nativeSocketId, SOL_SOCKET, optname, reinterpret_cast<netBufferType*>(&optval), sizeof(optval));
|
||||
INFO_LOG(SCENET, "UNTESTED sceNetInetSetsockopt(%i, %i, %i, %u, %i)", nativeSocketId, nativeSocketLevel, optname, optval, 4);
|
||||
const int ret = setsockopt(nativeSocketId, nativeSocketLevel, optname, reinterpret_cast<netBufferType*>(&optval), sizeof(optval));
|
||||
INFO_LOG(SCENET, "setsockopt_u32: setsockopt returned %i for %i", ret, nativeSocketId);
|
||||
if (ret < 0) {
|
||||
const auto error = sceNetInet->SetLastErrorToMatchPlatform();
|
||||
return hleLogError(SCENET, ret, "[%i] %s: Failed to set optname %04x to %08x with error %i: %s", nativeSocketId, __func__, optname, optval, error, strerror(error));
|
||||
}
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -441,7 +491,7 @@ static int sceNetInetAccept(int socket, u32 addrPtr, u32 addrLenPtr) {
|
|||
error != ERROR_WHEN_NONBLOCKING_CALL_OCCURS) {
|
||||
hleLogError(SCENET, ret, "[%i] %s: Encountered error %i: %s", nativeSocketId, __func__, error, strerror(error));
|
||||
}
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
// Don't call writeSockAddrInToInetSockAddr when addrPtr is 0, otherwise do and send false to EFAULT
|
||||
|
@ -573,7 +623,7 @@ static int sceNetInetClose(int socket) {
|
|||
sceNetInet->SetLastError(EFAULT);
|
||||
return hleLogError(SCENET, -1, "%s: Unable to clear mapping of inetSocketId->nativeSocketId, was there contention?", __func__);
|
||||
}
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
static u32 sceNetInetInetAddr(const char *hostname) {
|
||||
|
@ -585,7 +635,6 @@ static u32 sceNetInetInetAddr(const char *hostname) {
|
|||
}
|
||||
|
||||
in_addr inAddr{};
|
||||
// TODO: de-dupe
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
const int ret = inet_pton(AF_INET, hostname, &inAddr);
|
||||
#else
|
||||
|
@ -595,7 +644,7 @@ static u32 sceNetInetInetAddr(const char *hostname) {
|
|||
sceNetInet->SetLastErrorToMatchPlatform();
|
||||
return inAddr.s_addr;
|
||||
}
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
static int sceNetInetInetAton(const char *hostname, u32 addrPtr) {
|
||||
|
@ -632,11 +681,11 @@ static int sceNetInetInetAton(const char *hostname, u32 addrPtr) {
|
|||
|
||||
// Write back to addrPtr if ret is != 0
|
||||
Memory::Write_U32(inAddr.s_addr, addrPtr);
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
static u32 sceNetInetInetNtop(int addressFamily, u32 srcPtr, u32 dstBufPtr, u32 dstBufSize) {
|
||||
WARN_LOG_ONCE(sceNetInetInetNtop, SCENET, "UNTESTED %s(%i, %08x, %08x, %i)", __func__, addressFamily, srcPtr, dstBufPtr, dstBufSize);
|
||||
static u32 sceNetInetInetNtop(int inetAddressFamily, u32 srcPtr, u32 dstBufPtr, u32 dstBufSize) {
|
||||
WARN_LOG_ONCE(sceNetInetInetNtop, SCENET, "UNTESTED %s(%i, %08x, %08x, %i)", __func__, inetAddressFamily, srcPtr, dstBufPtr, dstBufSize);
|
||||
|
||||
const auto sceNetInet = SceNetInet::Get();
|
||||
if (!sceNetInet) {
|
||||
|
@ -660,15 +709,20 @@ static u32 sceNetInetInetNtop(int addressFamily, u32 srcPtr, u32 dstBufPtr, u32
|
|||
return hleLogError(SCENET, 0, "%s: dstBufSize must be > 0", __func__);
|
||||
}
|
||||
|
||||
// TODO: convert address family
|
||||
if (inet_ntop(addressFamily, reinterpret_cast<netBufferType*>(srcSockaddrIn), dstBuf, dstBufSize) == nullptr) {
|
||||
int nativeAddressFamily;
|
||||
if (!SceNetInet::TranslateInetAddressFamilyToNative(nativeAddressFamily, inetAddressFamily)) {
|
||||
sceNetInet->SetLastError(EAFNOSUPPORT);
|
||||
return hleLogError(SCENET, 0, "%s: Unknown address family %04x", __func__, inetAddressFamily);
|
||||
}
|
||||
|
||||
if (inet_ntop(nativeAddressFamily, reinterpret_cast<netBufferType*>(srcSockaddrIn), dstBuf, dstBufSize) == nullptr) {
|
||||
// Allow partial output in case it's desired for some reason
|
||||
}
|
||||
return hleLogSuccessX(SCENET, dstBufPtr);
|
||||
}
|
||||
|
||||
static int sceNetInetInetPton(int addressFamily, const char *hostname, u32 dstPtr) {
|
||||
WARN_LOG_ONCE(sceNetInetInetPton, SCENET, "UNTESTED %s(%i, %s, %08x)", __func__, addressFamily, hostname, dstPtr);
|
||||
static int sceNetInetInetPton(int inetAddressFamily, const char *hostname, u32 dstPtr) {
|
||||
WARN_LOG_ONCE(sceNetInetInetPton, SCENET, "UNTESTED %s(%i, %s, %08x)", __func__, inetAddressFamily, hostname, dstPtr);
|
||||
|
||||
const auto sceNetInet = SceNetInet::Get();
|
||||
if (!sceNetInet) {
|
||||
|
@ -687,9 +741,14 @@ static int sceNetInetInetPton(int addressFamily, const char *hostname, u32 dstPt
|
|||
return hleLogError(SCENET, 0, "%s: Invalid memory range for dstPtr %08x, size %i", __func__, dstPtr, sizeof(u32));
|
||||
}
|
||||
|
||||
// TODO: convert address family
|
||||
// TODO: If af does not contain a valid address family, -1 is returned and errno is set to EAFNOSUPPORT.
|
||||
const int ret = inet_pton(addressFamily, hostname, dst);
|
||||
// Translate inet address family to native
|
||||
int nativeAddressFamily;
|
||||
if (!SceNetInet::TranslateInetAddressFamilyToNative(nativeAddressFamily, inetAddressFamily)) {
|
||||
sceNetInet->SetLastError(EAFNOSUPPORT);
|
||||
return hleLogError(SCENET, 0, "%s: Unknown address family %04x", __func__, inetAddressFamily);
|
||||
}
|
||||
|
||||
const int ret = inet_pton(inetAddressFamily, hostname, dst);
|
||||
if (ret < 0) {
|
||||
const auto error = sceNetInet->SetLastErrorToMatchPlatform();
|
||||
return hleLogError(SCENET, ret, "%s: inet_pton returned %i: %s", __func__, sceNetInet->GetLastError(), strerror(error));
|
||||
|
@ -729,7 +788,7 @@ static int sceNetInetGetpeername(int socket, u32 addrPtr, u32 addrLenPtr) {
|
|||
sceNetInet->SetLastError(EFAULT);
|
||||
return hleLogError(SCENET, -1, "[%i] %s: Failed to write results of getpeername to SceNetInetSockaddrIn", nativeSocketId, __func__);
|
||||
}
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
static int sceNetInetGetsockname(int socket, u32 addrPtr, u32 addrLenPtr) {
|
||||
|
@ -759,7 +818,7 @@ static int sceNetInetGetsockname(int socket, u32 addrPtr, u32 addrLenPtr) {
|
|||
sceNetInet->SetLastError(EFAULT);
|
||||
return hleLogError(SCENET, -1, "[%i] %s: Failed to write results of getsockname to SceNetInetSockaddrIn", nativeSocketId, __func__);
|
||||
}
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
static int sceNetInetRecv(int socket, u32 bufPtr, u32 bufLen, int flags) {
|
||||
|
@ -790,7 +849,7 @@ static int sceNetInetRecv(int socket, u32 bufPtr, u32 bufLen, int flags) {
|
|||
ERROR_LOG(SCENET, "[%i]: %s: recv() encountered error %i: %s", socket, __func__, error, strerror(error));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
static int sceNetInetRecvfrom(int socket, u32 bufPtr, u32 bufLen, int flags, u32 fromAddr, u32 fromLenAddr) {
|
||||
|
@ -905,7 +964,7 @@ static int sceNetInetSendto(int socket, u32 bufPtr, u32 bufLen, int flags, u32 t
|
|||
WARN_LOG(SCENET, "[%i] %s: Got error %i=%s", nativeSocketId, __func__, error, strerror(error));
|
||||
}
|
||||
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
static int sceNetInetGetErrno() {
|
||||
|
@ -938,28 +997,6 @@ static int sceNetInetBind(int socket, u32 addrPtr, u32 addrLen) {
|
|||
|
||||
const int nativeSocketId = inetSocket->GetNativeSocketId();
|
||||
|
||||
#if PPSSPP_PLATFORM(LINUX)
|
||||
// Set broadcast
|
||||
// TODO: move broadcast InetSocket
|
||||
int broadcastEnabled = 1;
|
||||
int sockoptRet = setsockopt(nativeSocketId, SOL_SOCKET, SO_BROADCAST, &broadcastEnabled, sizeof(broadcastEnabled));
|
||||
|
||||
// Set reuseport / reuseaddr by default
|
||||
// TODO: evaluate
|
||||
int opt = 1;
|
||||
#if defined(SO_REUSEPORT)
|
||||
setsockopt(nativeSocketId, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
|
||||
#endif
|
||||
setsockopt(nativeSocketId, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
#elif PPSSPP_PLATFORM(WINDOWS)
|
||||
// Set broadcast
|
||||
// TODO: move broadcast InetSocket
|
||||
int broadcastEnabled = 1;
|
||||
int sockoptRet = setsockopt(nativeSocketId, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&broadcastEnabled), sizeof(broadcastEnabled));
|
||||
int opt = 1;
|
||||
setsockopt(nativeSocketId, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(opt));
|
||||
#endif
|
||||
|
||||
// Convert PSP bind addr to native bind addr
|
||||
sockaddr_in convertedSockaddr{};
|
||||
if (!inetSockaddrToNativeSocketAddr(convertedSockaddr, addrPtr, addrLen)) {
|
||||
|
@ -978,7 +1015,7 @@ static int sceNetInetBind(int socket, u32 addrPtr, u32 addrLen) {
|
|||
|
||||
// TODO: check whether setting to blocking and then non-blocking is valid
|
||||
setBlockingMode(nativeSocketId, false);
|
||||
INFO_LOG(SCENET, "[%i] Binding to family %i, port %i, addr %s sockoptRet %i", nativeSocketId, convertedSockaddr.sin_family, ntohs(convertedSockaddr.sin_port), ip2str(convertedSockaddr.sin_addr, false).c_str(), sockoptRet);
|
||||
INFO_LOG(SCENET, "[%i] Binding to family %i, port %i, addr %s", nativeSocketId, convertedSockaddr.sin_family, ntohs(convertedSockaddr.sin_port), ip2str(convertedSockaddr.sin_addr, false).c_str());
|
||||
const int ret = bind(nativeSocketId, reinterpret_cast<sockaddr*>(&convertedSockaddr), socklen);
|
||||
INFO_LOG(SCENET, "Bind returned %i for fd=%i", ret, nativeSocketId);
|
||||
setBlockingMode(nativeSocketId, inetSocket->IsNonBlocking());
|
||||
|
@ -1000,7 +1037,7 @@ static int sceNetInetBind(int socket, u32 addrPtr, u32 addrLen) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return hleLogSuccessI(SCENET, ret);
|
||||
}
|
||||
|
||||
// TODO: fix retmasks
|
||||
|
@ -1040,6 +1077,32 @@ const HLEFunction sceNetInet[] = {
|
|||
|
||||
std::shared_ptr<SceNetInet> SceNetInet::gInstance;
|
||||
std::shared_mutex SceNetInet::gLock;
|
||||
std::unordered_map<PspInetAddressFamily, int> SceNetInet::gInetAddressFamilyToNativeAddressFamily =
|
||||
{
|
||||
{ PSP_NET_INET_AF_UNSPEC, AF_UNSPEC },
|
||||
{ PSP_NET_INET_AF_LOCAL, AF_UNIX },
|
||||
{ PSP_NET_INET_AF_INET, AF_INET },
|
||||
};
|
||||
std::unordered_map<PspInetSocketType, int> SceNetInet::gInetSocketTypeToNativeSocketType =
|
||||
{
|
||||
{ PSP_NET_INET_SOCK_STREAM, SOCK_STREAM },
|
||||
{ PSP_NET_INET_SOCK_DGRAM, SOCK_DGRAM },
|
||||
{ PSP_NET_INET_SOCK_RAW, SOCK_RAW },
|
||||
{ PSP_NET_INET_SOCK_RDM, SOCK_RDM },
|
||||
{ PSP_NET_INET_SOCK_SEQPACKET, SOCK_SEQPACKET },
|
||||
};
|
||||
std::unordered_map<PspInetProtocol, int> SceNetInet::gInetProtocolToNativeProtocol =
|
||||
{
|
||||
{ PSP_NET_INET_IPPROTO_IP, IPPROTO_IP },
|
||||
{ PSP_NET_INET_IPPROTO_ICMP, IPPROTO_ICMP },
|
||||
{ PSP_NET_INET_IPPROTO_IGMP, IPPROTO_IGMP },
|
||||
{ PSP_NET_INET_IPPROTO_TCP, IPPROTO_TCP },
|
||||
{ PSP_NET_INET_IPPROTO_EGP, IPPROTO_EGP },
|
||||
{ PSP_NET_INET_IPPROTO_PUP, IPPROTO_PUP },
|
||||
{ PSP_NET_INET_IPPROTO_UDP, IPPROTO_UDP },
|
||||
{ PSP_NET_INET_IPPROTO_IDP, IPPROTO_IDP },
|
||||
{ PSP_NET_INET_IPPROTO_RAW, IPPROTO_RAW },
|
||||
};
|
||||
|
||||
bool SceNetInet::Init() {
|
||||
auto lock = std::unique_lock(gLock);
|
||||
|
@ -1060,6 +1123,69 @@ bool SceNetInet::Shutdown() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SceNetInet::TranslateInetAddressFamilyToNative(int &destAddressFamily, int srcAddressFamily) {
|
||||
const auto it = gInetAddressFamilyToNativeAddressFamily.find(static_cast<PspInetAddressFamily>(srcAddressFamily));
|
||||
if (it == gInetAddressFamilyToNativeAddressFamily.end()) {
|
||||
return false;
|
||||
}
|
||||
destAddressFamily = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SceNetInet::TranslateInetSocketLevelToNative(int &destSocketLevel, int srcSocketLevel) {
|
||||
if (srcSocketLevel != PSP_NET_INET_SOL_SOCKET) {
|
||||
return false;
|
||||
}
|
||||
destSocketLevel = SOL_SOCKET;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SceNetInet::TranslateInetSocketTypeToNative(int &destSocketType, bool &destNonBlocking, int srcSocketType) {
|
||||
// First, take the base socket type
|
||||
const int baseSocketType = static_cast<PspInetSocketType>(srcSocketType & PSP_NET_INET_SOCK_TYPE_MASK);
|
||||
const auto it = gInetSocketTypeToNativeSocketType.find(static_cast<PspInetSocketType>(baseSocketType));
|
||||
if (it == gInetSocketTypeToNativeSocketType.end()) {
|
||||
return false;
|
||||
}
|
||||
// Set base value for dest
|
||||
destSocketType = it->second;
|
||||
// Find any flags which are set, noting that this highly depends on the native platform and unknowns are ignored
|
||||
const int srcFlags = srcSocketType & PSP_NET_INET_SOCK_FLAGS_MASK;
|
||||
#if defined(SOCK_DCCP)
|
||||
if ((srcFlags & PSP_NET_INET_SOCK_DCCP) != 0) {
|
||||
destSocketType |= SOCK_DCCP;
|
||||
}
|
||||
#endif
|
||||
#if defined(SOCK_PACKET)
|
||||
if ((srcFlags & PSP_NET_INET_SOCK_PACKET) != 0) {
|
||||
destSocketType |= SOCK_PACKET;
|
||||
}
|
||||
#endif
|
||||
#if defined(SOCK_CLOEXEC)
|
||||
if ((srcFlags & PSP_NET_INET_SOCK_CLOEXEC) != 0) {
|
||||
destSocketType |= SOCK_CLOEXEC;
|
||||
}
|
||||
#endif
|
||||
if ((srcFlags & PSP_NET_INET_SOCK_NONBLOCK) != 0) {
|
||||
destNonBlocking = true;
|
||||
}
|
||||
#if defined(SOCK_NOSIGPIPE)
|
||||
if ((srcFlags & PSP_NET_INET_SOCK_NOSIGPIPE) != 0) {
|
||||
destSocketType |= SOCK_NOSIGPIPE;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SceNetInet::TranslateInetProtocolToNative(int &destProtocol, int srcProtocol) {
|
||||
const auto it = gInetProtocolToNativeProtocol.find(static_cast<PspInetProtocol>(srcProtocol));
|
||||
if (it == gInetProtocolToNativeProtocol.end()) {
|
||||
return false;
|
||||
}
|
||||
destProtocol = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
int SceNetInet::GetLastError() {
|
||||
auto lock = std::shared_lock(mLock);
|
||||
return mLastError;
|
||||
|
@ -1081,7 +1207,7 @@ int SceNetInet::SetLastErrorToMatchPlatform() {
|
|||
return error;
|
||||
}
|
||||
|
||||
std::shared_ptr<InetSocket> SceNetInet::CreateAndAssociateInetSocket(int nativeSocketId) {
|
||||
std::shared_ptr<InetSocket> SceNetInet::CreateAndAssociateInetSocket(int nativeSocketId, bool nonBlocking) {
|
||||
auto lock = std::unique_lock(mLock);
|
||||
|
||||
int inetSocketId = ++mCurrentInetSocketId;
|
||||
|
@ -1090,6 +1216,7 @@ std::shared_ptr<InetSocket> SceNetInet::CreateAndAssociateInetSocket(int nativeS
|
|||
return nullptr;
|
||||
}
|
||||
auto inetSocket = std::make_shared<InetSocket>(inetSocketId, nativeSocketId);
|
||||
inetSocket->SetNonBlocking(nonBlocking);
|
||||
mInetSocketIdToNativeSocket.emplace(inetSocketId, inetSocket);
|
||||
return inetSocket;
|
||||
}
|
||||
|
@ -1102,14 +1229,14 @@ std::shared_ptr<InetSocket> SceNetInet::GetInetSocket(int inetSocketId) {
|
|||
WARN_LOG(SCENET, "%s: Attempted to get unassociated socket from inetSocketId: %i", __func__, inetSocketId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool SceNetInet::GetNativeSocketIdForInetSocketId(int& nativeSocketId, int inetSocketId) {
|
||||
const auto inetSocket = GetInetSocket(inetSocketId);
|
||||
if (!inetSocket)
|
||||
if (!inetSocket) {
|
||||
return false;
|
||||
}
|
||||
nativeSocketId = inetSocket->GetNativeSocketId();
|
||||
return true;
|
||||
}
|
||||
|
@ -1160,9 +1287,10 @@ bool SceNetInet::TranslateInetFdSetToNativeFdSet(int &maxFd, fd_set& destFdSet,
|
|||
|
||||
void SceNetInet::CloseAllRemainingSockets() const {
|
||||
for (const auto &[first, second] : mInetSocketIdToNativeSocket) {
|
||||
if (second) {
|
||||
close(second->GetNativeSocketId());
|
||||
if (!second) {
|
||||
continue;
|
||||
}
|
||||
close(second->GetNativeSocketId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,48 @@ enum {
|
|||
ERROR_NET_INET_INVALID_ARG = 0x8041020b,
|
||||
};
|
||||
|
||||
enum PspInetAddressFamily {
|
||||
PSP_NET_INET_AF_UNSPEC = 0,
|
||||
PSP_NET_INET_AF_LOCAL = 1,
|
||||
PSP_NET_INET_AF_INET = 2,
|
||||
};
|
||||
|
||||
enum PspInetSocketLevel {
|
||||
PSP_NET_INET_SOL_SOCKET = 0xFFFF,
|
||||
};
|
||||
|
||||
enum PspInetSocketType {
|
||||
PSP_NET_INET_SOCK_STREAM = 1,
|
||||
PSP_NET_INET_SOCK_DGRAM = 2,
|
||||
PSP_NET_INET_SOCK_RAW = 3,
|
||||
PSP_NET_INET_SOCK_RDM = 4,
|
||||
PSP_NET_INET_SOCK_SEQPACKET = 5,
|
||||
PSP_NET_INET_SOCK_DCCP = 6,
|
||||
PSP_NET_INET_SOCK_PACKET = 10,
|
||||
PSP_NET_INET_SOCK_TYPE_MASK = 0xF,
|
||||
};
|
||||
|
||||
enum PspInetSocketTypeFlag {
|
||||
PSP_NET_INET_SOCK_CLOEXEC = 0x10000000,
|
||||
PSP_NET_INET_SOCK_NONBLOCK = 0x20000000,
|
||||
PSP_NET_INET_SOCK_NOSIGPIPE = 0x40000000,
|
||||
PSP_NET_INET_SOCK_FLAGS_MASK = 0xF0000000,
|
||||
};
|
||||
|
||||
// TODO: revisit protocols, not all are necessary
|
||||
enum PspInetProtocol {
|
||||
PSP_NET_INET_IPPROTO_IP = 0, // dummy for IP
|
||||
PSP_NET_INET_IPPROTO_UNSPEC = 0, // 0 will defaulted to the only existing protocol for that particular domain/family and type
|
||||
PSP_NET_INET_IPPROTO_ICMP = 1, // control message protocol
|
||||
PSP_NET_INET_IPPROTO_IGMP = 2, // group mgmt protocol
|
||||
PSP_NET_INET_IPPROTO_TCP = 6, // tcp
|
||||
PSP_NET_INET_IPPROTO_EGP = 8, // exterior gateway protocol
|
||||
PSP_NET_INET_IPPROTO_PUP = 12, // pup
|
||||
PSP_NET_INET_IPPROTO_UDP = 17, // user datagram protocol
|
||||
PSP_NET_INET_IPPROTO_IDP = 22, // xns idp
|
||||
PSP_NET_INET_IPPROTO_RAW = 255, // raw IP packet
|
||||
};
|
||||
|
||||
class SceNetInet {
|
||||
public:
|
||||
static bool Init();
|
||||
|
@ -57,12 +99,20 @@ public:
|
|||
return gInstance;
|
||||
}
|
||||
|
||||
// TODO: document that errno should be set to EAFNOSUPPORT when this returns false
|
||||
static bool TranslateInetAddressFamilyToNative(int &destAddressFamily, int srcAddressFamily);
|
||||
static inline bool TranslateInetSocketLevelToNative(int &destSocketLevel, int srcSocketLevel);
|
||||
// TODO: document that errno should be set to ESOMETHING when this returns false
|
||||
static bool TranslateInetSocketTypeToNative(int &destSocketType, bool &destNonBlocking, int srcSocketType);
|
||||
// TODO: document that errno should be set to EPROTONOSUPPORT when this returns false
|
||||
static bool TranslateInetProtocolToNative(int &destProtocol, int srcProtocol);
|
||||
|
||||
// TODO: document
|
||||
|
||||
int GetLastError();
|
||||
void SetLastError(int error);
|
||||
int SetLastErrorToMatchPlatform();
|
||||
std::shared_ptr<InetSocket> CreateAndAssociateInetSocket(int nativeSocketId);
|
||||
std::shared_ptr<InetSocket> CreateAndAssociateInetSocket(int nativeSocketId, bool nonBlocking);
|
||||
std::shared_ptr<InetSocket> GetInetSocket(int inetSocketId);
|
||||
bool GetNativeSocketIdForInetSocketId(int &nativeSocketId, int inetSocketId);
|
||||
bool EraseNativeSocket(int inetSocketId);
|
||||
|
@ -73,6 +123,10 @@ private:
|
|||
|
||||
static std::shared_ptr<SceNetInet> gInstance;
|
||||
static std::shared_mutex gLock;
|
||||
static std::unordered_map<PspInetAddressFamily, int> gInetAddressFamilyToNativeAddressFamily;
|
||||
// TODO: document that this does not include flags
|
||||
static std::unordered_map<PspInetSocketType, int> gInetSocketTypeToNativeSocketType;
|
||||
static std::unordered_map<PspInetProtocol, int> gInetProtocolToNativeProtocol;
|
||||
|
||||
int mLastError = 0;
|
||||
std::unordered_map<int, std::shared_ptr<InetSocket>> mInetSocketIdToNativeSocket;
|
||||
|
|
Loading…
Add table
Reference in a new issue