Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2178,6 +2178,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/HLE/AtracCtx2.h
Core/HLE/NetInetConstants.cpp
Core/HLE/NetInetConstants.h
Core/HLE/SocketManager.cpp
Core/HLE/SocketManager.h
Core/HLE/sceAtrac.cpp
Core/HLE/sceAtrac.h
Core/HLE/sceAudio.cpp
Expand Down
3 changes: 3 additions & 0 deletions Common/ArmEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
#define IS_SIGNED 1 << 1
#define ROUND_TO_ZERO 1 << 2

// Unclear why we suddenly need this.
#undef VMIN

namespace ArmGen
{
enum ARMReg
Expand Down
2 changes: 2 additions & 0 deletions Core/Core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@
<ClCompile Include="HLE\sceUsbAcc.cpp" />
<ClCompile Include="HLE\sceUsbCam.cpp" />
<ClCompile Include="HLE\sceUsbMic.cpp" />
<ClCompile Include="HLE\SocketManager.cpp" />
<ClCompile Include="HW\Atrac3Standalone.cpp" />
<ClCompile Include="HW\BufferQueue.cpp" />
<ClCompile Include="HW\Camera.cpp" />
Expand Down Expand Up @@ -1199,6 +1200,7 @@
<ClInclude Include="HLE\sceUsbAcc.h" />
<ClInclude Include="HLE\sceUsbCam.h" />
<ClInclude Include="HLE\sceUsbMic.h" />
<ClInclude Include="HLE\SocketManager.h" />
<ClInclude Include="HW\Atrac3Standalone.h" />
<ClInclude Include="HW\Camera.h" />
<ClInclude Include="HW\Display.h" />
Expand Down
6 changes: 6 additions & 0 deletions Core/Core.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,9 @@
<ClCompile Include="HLE\NetInetConstants.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
<ClCompile Include="HLE\SocketManager.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ELF\ElfReader.h">
Expand Down Expand Up @@ -2160,6 +2163,9 @@
<ClInclude Include="HLE\NetInetConstants.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
<ClInclude Include="HLE\SocketManager.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\LICENSE.TXT" />
Expand Down
102 changes: 102 additions & 0 deletions Core/HLE/SocketManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#include "Common/Net/SocketCompat.h"
#include "Core/HLE/NetInetConstants.h"
#include "Core/HLE/SocketManager.h"
#include "Common/Log.h"

#include <mutex>

SocketManager g_socketManager;
static std::mutex g_socketMutex; // TODO: Remove once the adhoc thread is gone

InetSocket *SocketManager::CreateSocket(int *index, int *returned_errno, SocketState state, int domain, int type, int protocol) {
_dbg_assert_(state != SocketState::Unused);

int hostDomain = convertSocketDomainPSP2Host(domain);
int hostType = convertSocketTypePSP2Host(type);
int hostProtocol = convertSocketProtoPSP2Host(protocol);

SOCKET hostSock = ::socket(hostDomain, hostType, hostProtocol);
if (hostSock < 0) {
*returned_errno = socket_errno;
return nullptr;
}

std::lock_guard<std::mutex> guard(g_socketMutex);

for (int i = MIN_VALID_INET_SOCKET; i < ARRAY_SIZE(inetSockets_); i++) {
if (inetSockets_[i].state == SocketState::Unused) {
*index = i;
InetSocket *inetSock = inetSockets_ + i;
inetSock->sock = hostSock;
inetSock->state = state;
inetSock->domain = domain;
inetSock->type = type;
inetSock->protocol = protocol;
inetSock->nonblocking = false;
*returned_errno = 0;
return inetSock;
}
}
_dbg_assert_(false);

ERROR_LOG(Log::sceNet, "Ran out of socket handles! This is BAD.");
closesocket(hostSock);
*index = 0;
*returned_errno = ENOMEM; // or something..
return nullptr;
}

bool SocketManager::Close(InetSocket *inetSocket) {
_dbg_assert_(inetSocket->state != SocketState::Unused);
if (closesocket(inetSocket->sock) != 0) {
ERROR_LOG(Log::sceNet, "closesocket(%d) failed", inetSocket->sock);
return false;
}
inetSocket->state = SocketState::Unused;
inetSocket->sock = 0;
return true;
}

bool SocketManager::GetInetSocket(int sock, InetSocket **inetSocket) {
std::lock_guard<std::mutex> guard(g_socketMutex);
if (sock < MIN_VALID_INET_SOCKET || sock >= ARRAY_SIZE(inetSockets_) || inetSockets_[sock].state == SocketState::Unused) {
*inetSocket = nullptr;
return false;
}
*inetSocket = inetSockets_ + sock;
return true;
}

// Simplified mappers, only really useful in select/poll
SOCKET SocketManager::GetHostSocketFromInetSocket(int sock) {
std::lock_guard<std::mutex> guard(g_socketMutex);
if (sock < MIN_VALID_INET_SOCKET || sock >= ARRAY_SIZE(inetSockets_) || inetSockets_[sock].state == SocketState::Unused) {
_dbg_assert_(false);
return -1;
}
if (sock == 0) {
// Map 0 to 0, special case.
return 0;
}
return inetSockets_[sock].sock;
}

void SocketManager::CloseAll() {
for (auto &sock : inetSockets_) {
if (sock.state != SocketState::Unused) {
closesocket(sock.sock);
}
sock.state = SocketState::Unused;
sock.sock = 0;
}
}

const char *SocketStateToString(SocketState state) {
switch (state) {
case SocketState::Unused: return "unused";
case SocketState::UsedNetInet: return "netInet";
case SocketState::UsedProAdhoc: return "proAdhoc";
default:
return "N/A";
}
}
50 changes: 50 additions & 0 deletions Core/HLE/SocketManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include "Common/Net/SocketCompat.h"

// Keep track of who's using a socket.
enum class SocketState {
Unused = 0,
UsedNetInet,
UsedProAdhoc,
};

const char *SocketStateToString(SocketState state);

// Internal socket state tracking
struct InetSocket {
Copy link
Collaborator

@anr2me anr2me Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should store non-blocking state here too, and probably some other value that can be set using SetSockOpt too just like non-blocking state, but non-blocking state alone should be sufficient (at least for TCP/UDP socket, while PDP/PTP sockets might need some additional info to be stored, you can checked the AdhocSocket struct for this), since we will need to retrieve the non-blocking state in order to simulate blocking mode later.

PS: Sockets are in blocking mode by default after creation, thus the default value should be nonblocking = false.

Copy link
Collaborator

@anr2me anr2me Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, since we have stored the socket protocol here, we can replace these code at sceNetInet.cpp by forwarding only TCP or UDP instead of forwarding both protocol:

// Enable Port-forwarding
	// TODO: Check the socket type/protocol for SOCK_STREAM/SOCK_DGRAM or IPPROTO_TCP/IPPROTO_UDP instead of forwarding both protocol
	// InetSocket* sock = pspSockets.Get<InetSocket>(socket, error);
	// UPnP_Add((sock->type == SOCK_STREAM)? IP_PROTOCOL_TCP: IP_PROTOCOL_UDP, port, port);	
	unsigned short port = ntohs(saddr.in.sin_port);
	UPnP_Add(IP_PROTOCOL_UDP, port, port);
	UPnP_Add(IP_PROTOCOL_TCP, port, port);

I opened both TCP and UDP because i use the native socket directly and there is noway to retrieve the socket protocol (at least the easy way as i remembered).

Edit: oops, you already did this >.<

SOCKET sock; // native socket
SocketState state;
// NOTE: These are the PSP types. Can be converted to the host types if needed.
int domain;
int type;
int protocol;
bool nonblocking;
};

// Only use this for sockets whose ID are exposed to the game.
// Don't really need to bother with the others, as the game doesn't know about them.
class SocketManager {
public:
enum {
VALID_INET_SOCKET_COUNT = 256,
MIN_VALID_INET_SOCKET = 1,
};

InetSocket *CreateSocket(int *index, int *returned_errno, SocketState state, int domain, int type, int protocol);
bool GetInetSocket(int sock, InetSocket **inetSocket);
SOCKET GetHostSocketFromInetSocket(int sock);
bool Close(InetSocket *inetSocket);
void CloseAll();

// For debugger
const InetSocket *Sockets() {
return inetSockets_;
}

private:
// We use this array from MIN_VALID_INET_SOCKET and forward. It's probably not a good idea to return 0 as a socket.
InetSocket inetSockets_[VALID_INET_SOCKET_COUNT];
};

extern SocketManager g_socketManager;
6 changes: 4 additions & 2 deletions Core/HLE/proAdhoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
#include "Core/CoreTiming.h"
#include "Core/Core.h"
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/HLE/sceNetAdhoc.h"
#include "Core/Instance.h"
Expand Down Expand Up @@ -94,7 +93,9 @@ int actionAfterMatchingMipsCall;
// Broadcast MAC
uint8_t broadcastMAC[ETHER_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

// NOTE: This does not need to be managed by the socket manager - not exposed to the game.
std::atomic<int> metasocket((int)INVALID_SOCKET);

SceNetAdhocctlParameter parameter;
SceNetAdhocctlAdhocId product_code;
std::thread friendFinderThread;
Expand Down Expand Up @@ -281,6 +282,7 @@ SceNetAdhocctlPeerInfo* findFriendByIP(uint32_t ip) {
return peer;
}

// fd is a host socket
int IsSocketReady(int fd, bool readfd, bool writefd, int* errorcode, int timeoutUS) {
fd_set readfds, writefds;
timeval tval;
Expand Down Expand Up @@ -1318,7 +1320,7 @@ int GetChatMessageCount() {
}

// TODO: We should probably change this thread into PSPThread (or merging it into the existing AdhocThread PSPThread) as there are too many global vars being used here which also being used within some HLEs
int friendFinder(){
int friendFinder() {
SetCurrentThreadName("FriendFinder");
auto n = GetI18NCategory(I18NCat::NETWORKING);
// Receive Buffer
Expand Down
Loading
Loading