#include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include #include #include #include extern "C" { int APS5_VABI sceNetInit_nid_postfix(void); int APS5_VABI sceNetSocket(const char*, int, int, int); int APS5_VABI sceNetBind_nid_postfix(int, const void*, std::uint32_t); int APS5_VABI sceNetListen(int, int); int APS5_VABI sceNetGetsockname(int, void*, std::uint32_t*); int APS5_VABI sceNetConnect(int, const void*, std::uint32_t); int APS5_VABI sceNetAccept(int, void*, std::uint32_t*); std::int64_t APS5_VABI sceNetSend(int, const void*, std::size_t, int); std::int64_t APS5_VABI sceNetRecv(int, void*, std::size_t, int); std::int64_t APS5_VABI sceNetSendto(int, const void*, std::size_t, int, const void*, std::uint32_t); std::int64_t APS5_VABI sceNetRecvfrom(int, void*, std::size_t, int, void*, std::uint32_t*); int APS5_VABI sceNetSocketClose(int); int APS5_VABI sceNetEpollCreate(const char*, int); int APS5_VABI sceNetEpollControl(int, int, int, const NetEpollEvent*); int APS5_VABI sceNetEpollWait(int, NetEpollEvent*, int, int); int APS5_VABI sceNetEpollDestroy(int); int APS5_VABI sceNetResolverCreate(const char*, int, int); int APS5_VABI sceNetResolverStartNtoa(int, const char*, void*, int, int, int); int APS5_VABI sceNetResolverDestroy(int); int APS5_VABI sceNetCtlGetState(int*); int APS5_VABI sceNetInetPton(int, const char*, void*); const char* APS5_VABI sceNetInetNtop(int, const void*, char*, std::uint32_t); } static void Require(bool condition) { if (!condition) std::abort(); } int main() { Require(sceNetInit_nid_postfix() == 0); const int listener = sceNetSocket(nullptr, 2, 1, 6); Require(listener >= 0); std::array address{16, 2, 0, 0, 127, 0, 0, 1}; Require(sceNetBind_nid_postfix(listener, address.data(), address.size()) == 0); Require(sceNetListen(listener, 4) == 0); std::uint32_t address_size = address.size(); Require(sceNetGetsockname(listener, address.data(), &address_size) == 0 && address_size == 16); Require(address[2] != 0 || address[3] != 0); const int client = sceNetSocket(nullptr, 2, 1, 6); Require(client >= 0); Require(sceNetConnect(client, address.data(), address.size()) == 0); std::array peer{}; address_size = peer.size(); const int accepted = sceNetAccept(listener, peer.data(), &address_size); Require(accepted >= 0 && address_size == 16); const int epoll = sceNetEpollCreate("guest-sce-net", 0); Require(epoll >= 0); NetEpollEvent registration{}; registration.events = 1; registration.ident = static_cast(accepted); registration.data.u32 = 77; Require(sceNetEpollControl(epoll, 1, accepted, ®istration) == 0); const char request[] = "guest tcp loopback"; char response[sizeof(request)]{}; Require(sceNetSend(client, request, sizeof(request), 0) == sizeof(request)); NetEpollEvent ready{}; const int ready_count = sceNetEpollWait(epoll, &ready, 1, 1000000); Require(ready_count == 1 && (ready.events & 1) && ready.ident == static_cast(accepted)); Require(sceNetRecv(accepted, response, sizeof(response), 0) == sizeof(response)); Require(std::strcmp(request, response) == 0); Require(sceNetEpollDestroy(epoll) == 0); Require(sceNetSocketClose(accepted) == 0); Require(sceNetSocketClose(client) == 0); Require(sceNetSocketClose(listener) == 0); const int udp_receiver = sceNetSocket(nullptr, 2, 2, 17); const int udp_sender = sceNetSocket(nullptr, 2, 2, 17); Require(udp_receiver >= 0 && udp_sender >= 0); address = {16, 2, 0, 0, 127, 0, 0, 1}; Require(sceNetBind_nid_postfix(udp_receiver, address.data(), address.size()) == 0); address_size = address.size(); Require(sceNetGetsockname(udp_receiver, address.data(), &address_size) == 0); const char datagram[] = "guest udp loopback"; char datagram_result[sizeof(datagram)]{}; Require(sceNetSendto(udp_sender, datagram, sizeof(datagram), 0, address.data(), address.size()) == sizeof(datagram)); std::array source{}; address_size = source.size(); Require(sceNetRecvfrom(udp_receiver, datagram_result, sizeof(datagram_result), 0, source.data(), &address_size) == sizeof(datagram_result)); Require(std::strcmp(datagram, datagram_result) == 0 && source[1] == 2); Require(sceNetSocketClose(udp_sender) == 0); Require(sceNetSocketClose(udp_receiver) == 0); const int resolver = sceNetResolverCreate("guest-sce-net", 0, 0); Require(resolver >= 0); std::array ipv4{}; Require(sceNetResolverStartNtoa(resolver, "localhost", ipv4.data(), 5000000, 1, 0) == 0); Require(ipv4[0] == 127); Require(sceNetResolverDestroy(resolver) == 0); std::array ipv6{}; Require(sceNetInetPton(28, "::1", ipv6.data()) == 1); char text[64]{}; Require(sceNetInetNtop(28, ipv6.data(), text, sizeof(text)) == text); Require(std::strcmp(text, "::1") == 0); int state = -1; Require(sceNetCtlGetState(&state) == 0); Require(state == 0 || state == 3); }