modules/SceNet: Implement Getpeername and fix accept return P2P sock.

- Implement get peer address for both socket.
- refactor, improve and rename variable of get socket address.
- convert PosixSocket to P2PSocket when is created by one P2PSocket.
- Handle SCE_NET_MSG_WAITALL correctly: only enable for stream sockets.
This commit is contained in:
Zangetsu38
2025-11-19 19:53:49 +01:00
committed by bookmist
parent 59250a64e7
commit 3c7d2be6d7
4 changed files with 75 additions and 40 deletions
+7 -6
View File
@@ -322,16 +322,17 @@ EXPORT(int, sceNetGetStatisticsInfo) {
return UNIMPLEMENTED();
}
EXPORT(int, sceNetGetpeername) {
TRACY_FUNC(sceNetGetpeername);
return UNIMPLEMENTED();
EXPORT(int, sceNetGetpeername, int sid, SceNetSockaddr *addr, unsigned int *addrlen) {
TRACY_FUNC(sceNetGetpeername, sid, addr, addrlen);
auto sock = lock_and_find(sid, emuenv.net.socks, emuenv.kernel.mutex);
RET_NET_ERRNO(sock ? sock->get_peer_address(addr, addrlen) : SCE_NET_ERROR_EBADF);
}
EXPORT(int, sceNetGetsockname, int sid, SceNetSockaddr *name, unsigned int *namelen) {
TRACY_FUNC(sceNetGetsockname, sid, name, namelen);
EXPORT(int, sceNetGetsockname, int sid, SceNetSockaddr *addr, unsigned int *addrlen) {
TRACY_FUNC(sceNetGetsockname, sid, addr, addrlen);
auto sock = lock_and_find(sid, emuenv.net.socks, emuenv.kernel.mutex);
RET_NET_ERRNO(sock ? sock->get_socket_address(name, namelen) : SCE_NET_ERROR_EBADF);
RET_NET_ERRNO(sock ? sock->get_socket_address(addr, addrlen) : SCE_NET_ERROR_EBADF);
}
EXPORT(int, sceNetGetsockopt, int sid, int level, int optname, void *optval, unsigned int *optlen) {
+16 -9
View File
@@ -46,8 +46,10 @@ typedef std::shared_ptr<Socket> SocketPtr;
struct Socket {
int sockopt_so_onesbcast = 0;
int sce_type;
explicit Socket(int domain, int type, int protocol) {}
explicit Socket(int domain, int type, int protocol)
: sce_type(type) {}
virtual ~Socket() = default;
@@ -59,10 +61,11 @@ struct Socket {
virtual int recv_packet(void *buf, unsigned int len, int flags, SceNetSockaddr *from, unsigned int *fromlen) = 0;
virtual int set_socket_options(int level, int optname, const void *optval, unsigned int optlen) = 0;
virtual int get_socket_options(int level, int optname, void *optval, unsigned int *optlen) = 0;
virtual int connect(const SceNetSockaddr *addr, unsigned int namelen) = 0;
virtual int connect(const SceNetSockaddr *addr, unsigned int addrlen) = 0;
virtual SocketPtr accept(SceNetSockaddr *addr, unsigned int *addrlen, int &err) = 0;
virtual int listen(int backlog) = 0;
virtual int get_socket_address(SceNetSockaddr *name, unsigned int *namelen) = 0;
virtual int get_peer_address(SceNetSockaddr *addr, unsigned int *addrlen) = 0;
virtual int get_socket_address(SceNetSockaddr *addr, unsigned int *addrlen) = 0;
};
// udp, tcp
@@ -85,8 +88,8 @@ struct PosixSocket : public Socket {
: Socket(domain, type, protocol)
, sock(socket(domain, type, protocol)) {}
explicit PosixSocket(abs_socket sock)
: Socket(0, 0, 0)
explicit PosixSocket(abs_socket sock, int type)
: Socket(0, type, 0)
, sock(sock) {}
static int translate_return_value(int retval);
@@ -99,19 +102,23 @@ struct PosixSocket : public Socket {
int recv_packet(void *buf, unsigned int len, int flags, SceNetSockaddr *from, unsigned int *fromlen) override;
int set_socket_options(int level, int optname, const void *optval, unsigned int optlen) override;
int get_socket_options(int level, int optname, void *optval, unsigned int *optlen) override;
int connect(const SceNetSockaddr *addr, unsigned int namelen) override;
int connect(const SceNetSockaddr *addr, unsigned int addrlen) override;
SocketPtr accept(SceNetSockaddr *addr, unsigned int *addrlen, int &err) override;
int listen(int backlog) override;
int get_socket_address(SceNetSockaddr *name, unsigned int *namelen) override;
int get_peer_address(SceNetSockaddr *addr, unsigned int *addrlen) override;
int get_socket_address(SceNetSockaddr *addr, unsigned int *addrlen) override;
};
struct P2PSocket : public PosixSocket {
explicit P2PSocket(int domain, int type, int protocol);
explicit P2PSocket(abs_socket sock, int type)
: PosixSocket(sock, type) {}
int bind(const SceNetSockaddr *addr, unsigned int addrlen) override;
int send_packet(const void *msg, unsigned int len, int flags, const SceNetSockaddr *to, unsigned int tolen) override;
int recv_packet(void *buf, unsigned int len, int flags, SceNetSockaddr *from, unsigned int *fromlen) override;
int connect(const SceNetSockaddr *addr, unsigned int namelen) override;
int connect(const SceNetSockaddr *addr, unsigned int addrlen) override;
SocketPtr accept(SceNetSockaddr *addr, unsigned int *addrlen, int &err) override;
int get_socket_address(SceNetSockaddr *name, unsigned int *namelen) override;
int get_peer_address(SceNetSockaddr *addr, unsigned int *addrlen) override;
int get_socket_address(SceNetSockaddr *addr, unsigned int *addrlen) override;
};
+21 -8
View File
@@ -67,17 +67,20 @@ static int p2pSocketTypeToPosixSocketType(int type) {
}
P2PSocket::P2PSocket(int domain, int type, int protocol)
: PosixSocket(domain, p2pSocketTypeToPosixSocketType(type), protocol){};
: PosixSocket(domain, p2pSocketTypeToPosixSocketType(type), protocol) { sce_type = type; }
SocketPtr P2PSocket::accept(SceNetSockaddr *addr, unsigned int *addrlen, int &err) {
const auto res = PosixSocket::accept(addr, addrlen, err);
const auto res = std::dynamic_pointer_cast<PosixSocket>(PosixSocket::accept(addr, addrlen, err));
if (!res)
return nullptr;
*addr = convertPosixToP2P(addr);
return res;
return std::make_shared<P2PSocket>(res->sock, res->sce_type);
}
int P2PSocket::connect(const SceNetSockaddr *addr, unsigned int namelen) {
int P2PSocket::connect(const SceNetSockaddr *addr, unsigned int addrlen) {
const auto p2p_addr = convertP2PToPosix(addr);
return PosixSocket::connect(&p2p_addr, namelen);
return PosixSocket::connect(&p2p_addr, addrlen);
}
int P2PSocket::recv_packet(void *buf, unsigned int len, int flags, SceNetSockaddr *from, unsigned int *fromlen) {
@@ -98,8 +101,18 @@ int P2PSocket::bind(const SceNetSockaddr *addr, unsigned int addrlen) {
return PosixSocket::bind(&p2p_addr, addrlen);
}
int P2PSocket::get_socket_address(SceNetSockaddr *name, unsigned int *namelen) {
const auto res = PosixSocket::get_socket_address(name, namelen);
*name = convertPosixToP2P(name);
int P2PSocket::get_peer_address(SceNetSockaddr *addr, unsigned int *addrlen) {
const auto res = PosixSocket::get_peer_address(addr, addrlen);
if (res == 0)
*addr = convertPosixToP2P(addr);
return res;
}
int P2PSocket::get_socket_address(SceNetSockaddr *addr, unsigned int *addrlen) {
const auto res = PosixSocket::get_socket_address(addr, addrlen);
if (res == 0)
*addr = convertPosixToP2P(addr);
return res;
}
+31 -17
View File
@@ -156,7 +156,7 @@ static bool should_abort(int abort_flags, int flags) {
return (abort_flags & flags) != 0;
}
int PosixSocket::connect(const SceNetSockaddr *addr, unsigned int namelen) {
int PosixSocket::connect(const SceNetSockaddr *addr, unsigned int addrlen) {
if (should_abort(abort_flags, SCE_NET_SOCKET_ABORT_FLAG_SND_PRESERVATION))
return SCE_NET_ERROR_EINTR;
@@ -180,18 +180,31 @@ int PosixSocket::listen(int backlog) {
return translate_return_value(::listen(sock, backlog));
}
int PosixSocket::get_socket_address(SceNetSockaddr *name, unsigned int *namelen) {
sockaddr addr;
convertSceSockaddrToPosix(name, &addr);
if (name != nullptr) {
*namelen = sizeof(sockaddr_in);
}
int res = getsockname(sock, &addr, (socklen_t *)namelen);
int PosixSocket::get_peer_address(SceNetSockaddr *addr, unsigned int *addrlen) {
if (!addr || !addrlen)
return SCE_NET_EINVAL;
sockaddr addr2{};
const auto res = ::getpeername(sock, &addr2, (socklen_t *)addrlen);
if (res >= 0) {
convertPosixSockaddrToSce(&addr, name);
*namelen = sizeof(SceNetSockaddrIn);
convertPosixSockaddrToSce(&addr2, addr);
*addrlen = sizeof(SceNetSockaddrIn);
}
return res;
return translate_return_value(res);
}
int PosixSocket::get_socket_address(SceNetSockaddr *addr, unsigned int *addrlen) {
if (!addr || !addrlen)
return SCE_NET_EINVAL;
sockaddr addr2{};
const auto res = ::getsockname(sock, &addr2, (socklen_t *)addrlen);
if (res >= 0) {
convertPosixSockaddrToSce(&addr2, addr);
*addrlen = sizeof(SceNetSockaddrIn);
}
return translate_return_value(res);
}
int PosixSocket::abort(int flags) {
@@ -233,7 +246,7 @@ SocketPtr PosixSocket::accept(SceNetSockaddr *addr, unsigned int *addrlen, int &
return nullptr;
}
sockaddr addr2{};
abs_socket new_socket = ::accept(sock, &addr2, (socklen_t *)addrlen);
const abs_socket new_socket = ::accept(sock, &addr2, (socklen_t *)addrlen);
if (abort_pending(is_aborted)) {
err = SCE_NET_ERROR_EINTR;
return nullptr;
@@ -245,7 +258,7 @@ SocketPtr PosixSocket::accept(SceNetSockaddr *addr, unsigned int *addrlen, int &
#endif
convertPosixSockaddrToSce(&addr2, addr);
*addrlen = sizeof(SceNetSockaddrIn);
return std::make_shared<PosixSocket>(new_socket);
return std::make_shared<PosixSocket>(new_socket, sce_type);
}
err = translate_return_value(new_socket);
return nullptr;
@@ -423,7 +436,7 @@ int PosixSocket::get_socket_options(int level, int optname, void *optval, unsign
return SCE_NET_ERROR_EINVAL;
}
static int convertSceFlagsToPosix(int sce_flags) {
static int convertSceFlagsToPosix(int sock_type, int sce_flags) {
int posix_flags = 0;
if (sce_flags & SCE_NET_MSG_PEEK)
@@ -432,7 +445,8 @@ static int convertSceFlagsToPosix(int sce_flags) {
if (sce_flags & SCE_NET_MSG_DONTWAIT)
posix_flags |= MSG_DONTWAIT;
#endif
if (sce_flags & SCE_NET_MSG_WAITALL)
// MSG_WAITALL is only valid for stream sockets
if ((sce_flags & SCE_NET_MSG_WAITALL) && ((sock_type == SCE_NET_SOCK_STREAM) || (sock_type == SCE_NET_SOCK_STREAM_P2P)))
posix_flags |= MSG_WAITALL;
return posix_flags;
@@ -466,7 +480,7 @@ int PosixSocket::recv_packet(void *buf, unsigned int len, int flags, SceNetSocka
return res;
}
#endif
const auto posix_flags = convertSceFlagsToPosix(flags);
const auto posix_flags = convertSceFlagsToPosix(sce_type, flags);
if (from == nullptr) {
res = recv(sock, (char *)buf, len, posix_flags);
} else {
@@ -495,7 +509,7 @@ int PosixSocket::send_packet(const void *msg, unsigned int len, int flags, const
return res;
}
#endif
const auto posix_flags = convertSceFlagsToPosix(flags);
const auto posix_flags = convertSceFlagsToPosix(sce_type, flags);
if (to == nullptr) {
res = send(sock, (const char *)msg, len, posix_flags);
} else {