#pragma once #include "Utilities/bit_set.h" #include "Utilities/mutex.h" #include "Emu/Memory/vm_ptr.h" #include "Emu/Cell/ErrorCodes.h" #include #include #include #include // Error codes enum sys_net_error : s32 { SYS_NET_ENOENT = 2, SYS_NET_EINTR = 4, SYS_NET_EBADF = 9, SYS_NET_ENOMEM = 12, SYS_NET_EACCES = 13, SYS_NET_EFAULT = 14, SYS_NET_EBUSY = 16, SYS_NET_EINVAL = 22, SYS_NET_EMFILE = 24, SYS_NET_ENOSPC = 28, SYS_NET_EPIPE = 32, SYS_NET_EAGAIN = 35, SYS_NET_EWOULDBLOCK = SYS_NET_EAGAIN, SYS_NET_EINPROGRESS = 36, SYS_NET_EALREADY = 37, SYS_NET_EDESTADDRREQ = 39, SYS_NET_EMSGSIZE = 40, SYS_NET_EPROTOTYPE = 41, SYS_NET_ENOPROTOOPT = 42, SYS_NET_EPROTONOSUPPORT = 43, SYS_NET_EOPNOTSUPP = 45, SYS_NET_EPFNOSUPPORT = 46, SYS_NET_EAFNOSUPPORT = 47, SYS_NET_EADDRINUSE = 48, SYS_NET_EADDRNOTAVAIL = 49, SYS_NET_ENETDOWN = 50, SYS_NET_ENETUNREACH = 51, SYS_NET_ECONNABORTED = 53, SYS_NET_ECONNRESET = 54, SYS_NET_ENOBUFS = 55, SYS_NET_EISCONN = 56, SYS_NET_ENOTCONN = 57, SYS_NET_ESHUTDOWN = 58, SYS_NET_ETOOMANYREFS = 59, SYS_NET_ETIMEDOUT = 60, SYS_NET_ECONNREFUSED = 61, SYS_NET_EHOSTDOWN = 64, SYS_NET_EHOSTUNREACH = 65, }; static constexpr sys_net_error operator-(sys_net_error v) { return sys_net_error{-+v}; } // Socket types (prefixed with SYS_NET_) enum lv2_socket_type : s32 { SYS_NET_SOCK_STREAM = 1, SYS_NET_SOCK_DGRAM = 2, SYS_NET_SOCK_RAW = 3, SYS_NET_SOCK_DGRAM_P2P = 6, SYS_NET_SOCK_STREAM_P2P = 10, }; // Socket options (prefixed with SYS_NET_) enum { SYS_NET_SO_SNDBUF = 0x1001, SYS_NET_SO_RCVBUF = 0x1002, SYS_NET_SO_SNDLOWAT = 0x1003, SYS_NET_SO_RCVLOWAT = 0x1004, SYS_NET_SO_SNDTIMEO = 0x1005, SYS_NET_SO_RCVTIMEO = 0x1006, SYS_NET_SO_ERROR = 0x1007, SYS_NET_SO_TYPE = 0x1008, SYS_NET_SO_NBIO = 0x1100, // Non-blocking IO SYS_NET_SO_TPPOLICY = 0x1101, SYS_NET_SO_REUSEADDR = 0x0004, SYS_NET_SO_KEEPALIVE = 0x0008, SYS_NET_SO_BROADCAST = 0x0020, SYS_NET_SO_LINGER = 0x0080, SYS_NET_SO_OOBINLINE = 0x0100, SYS_NET_SO_REUSEPORT = 0x0200, SYS_NET_SO_ONESBCAST = 0x0800, SYS_NET_SO_USECRYPTO = 0x1000, SYS_NET_SO_USESIGNATURE = 0x2000, SYS_NET_SOL_SOCKET = 0xffff, }; // Family (prefixed with SYS_NET_) enum lv2_socket_family : s32 { SYS_NET_AF_UNSPEC = 0, SYS_NET_AF_LOCAL = 1, SYS_NET_AF_UNIX = SYS_NET_AF_LOCAL, SYS_NET_AF_INET = 2, SYS_NET_AF_INET6 = 24, }; // Flags (prefixed with SYS_NET_) enum { SYS_NET_MSG_OOB = 0x1, SYS_NET_MSG_PEEK = 0x2, SYS_NET_MSG_DONTROUTE = 0x4, SYS_NET_MSG_EOR = 0x8, SYS_NET_MSG_TRUNC = 0x10, SYS_NET_MSG_CTRUNC = 0x20, SYS_NET_MSG_WAITALL = 0x40, SYS_NET_MSG_DONTWAIT = 0x80, SYS_NET_MSG_BCAST = 0x100, SYS_NET_MSG_MCAST = 0x200, SYS_NET_MSG_USECRYPTO = 0x400, SYS_NET_MSG_USESIGNATURE= 0x800, }; // Shutdown types (prefixed with SYS_NET_) enum { SYS_NET_SHUT_RD = 0, SYS_NET_SHUT_WR = 1, SYS_NET_SHUT_RDWR = 2, }; // TCP options (prefixed with SYS_NET_) enum { SYS_NET_TCP_NODELAY = 1, SYS_NET_TCP_MAXSEG = 2, SYS_NET_TCP_MSS_TO_ADVERTISE = 3, }; // IP protocols (prefixed with SYS_NET_) enum { SYS_NET_IPPROTO_IP = 0, SYS_NET_IPPROTO_ICMP = 1, SYS_NET_IPPROTO_IGMP = 2, SYS_NET_IPPROTO_TCP = 6, SYS_NET_IPPROTO_UDP = 17, SYS_NET_IPPROTO_ICMPV6 = 58, }; // Poll events (prefixed with SYS_NET_) enum { SYS_NET_POLLIN = 0x0001, SYS_NET_POLLPRI = 0x0002, SYS_NET_POLLOUT = 0x0004, SYS_NET_POLLERR = 0x0008, /* revent only */ SYS_NET_POLLHUP = 0x0010, /* revent only */ SYS_NET_POLLNVAL = 0x0020, /* revent only */ SYS_NET_POLLRDNORM = 0x0040, SYS_NET_POLLWRNORM = SYS_NET_POLLOUT, SYS_NET_POLLRDBAND = 0x0080, SYS_NET_POLLWRBAND = 0x0100, }; // in_addr_t type prefixed with sys_net_ using sys_net_in_addr_t = u32; // in_port_t type prefixed with sys_net_ using sys_net_in_port_t = u16; // sa_family_t type prefixed with sys_net_ using sys_net_sa_family_t = u8; // socklen_t type prefixed with sys_net_ using sys_net_socklen_t = u32; // fd_set prefixed with sys_net_ struct sys_net_fd_set { be_t fds_bits[32]; u32 bit(s32 s) { return (fds_bits[(s >> 5) & 31] >> (s & 31)) & 1u; } void set(s32 s) { fds_bits[(s >> 5) & 31] |= (1u << (s & 31)); } }; // hostent prefixed with sys_net_ struct sys_net_hostent { vm::bptr h_name; vm::bpptr h_aliases; be_t h_addrtype; be_t h_length; vm::bpptr h_addr_list; }; // in_addr prefixed with sys_net_ struct sys_net_in_addr { be_t _s_addr; }; // iovec prefixed with sys_net_ struct sys_net_iovec { be_t zero1; vm::bptr iov_base; be_t zero2; be_t iov_len; }; // ip_mreq prefixed with sys_net_ struct sys_net_ip_mreq { be_t imr_multiaddr; be_t imr_interface; }; // msghdr prefixed with sys_net_ struct sys_net_msghdr { be_t zero1; vm::bptr msg_name; be_t msg_namelen; be_t pad1; be_t zero2; vm::bptr msg_iov; be_t msg_iovlen; be_t pad2; be_t zero3; vm::bptr msg_control; be_t msg_controllen; be_t msg_flags; }; // pollfd prefixed with sys_net_ struct sys_net_pollfd { be_t fd; be_t events; be_t revents; }; // sockaddr prefixed with sys_net_ struct sys_net_sockaddr { u8 sa_len; u8 sa_family; char sa_data[14]; }; // sockaddr_dl prefixed with sys_net_ struct sys_net_sockaddr_dl { u8 sdl_len; u8 sdl_family; be_t sdl_index; u8 sdl_type; u8 sdl_nlen; u8 sdl_alen; u8 sdl_slen; char sdl_data[12]; }; // sockaddr_in prefixed with sys_net_ struct sys_net_sockaddr_in { u8 sin_len; u8 sin_family; be_t sin_port; be_t sin_addr; be_t sin_zero; }; // sockaddr_in_p2p prefixed with sys_net_ struct sys_net_sockaddr_in_p2p { u8 sin_len; u8 sin_family; be_t sin_port; be_t sin_addr; be_t sin_vport; char sin_zero[6]; }; // timeval prefixed with sys_net_ struct sys_net_timeval { be_t tv_sec; be_t tv_usec; }; // linger prefixed with sys_net_ struct sys_net_linger { be_t l_onoff; be_t l_linger; }; // Custom structure for sockets // We map host sockets to sequential IDs to return as descriptors because syscalls expect socket IDs to be under 1024. struct lv2_socket final { #ifdef _WIN32 using socket_type = uptr; #else using socket_type = int; #endif static const u32 id_base = 24; static const u32 id_step = 1; static const u32 id_count = 1000; // Poll events enum class poll { read, write, error, __bitset_enum_max }; lv2_socket(socket_type s, s32 s_type, s32 family); ~lv2_socket(); shared_mutex mutex; #ifdef _WIN32 // Tracks connect for WSAPoll workaround bool is_connecting = false; #endif // Native socket (must be non-blocking) socket_type socket; // Events selected for polling atomic_bs_t events{}; // Non-blocking IO option s32 so_nbio = 0; // Connection result s32 so_error = 0; // Unsupported option s32 so_tcp_maxseg = 1500; const lv2_socket_type type; const lv2_socket_family family; // SYS_NET_SOCK_DGRAM_P2P and SYS_NET_SOCK_STREAM_P2P socket specific information struct p2p_i { // Port(actual bound port) and Virtual Port(indicated by u16 at the start of the packet) u16 port = 0, vport = 0; // Queue containing received packets from network_thread for SYS_NET_SOCK_DGRAM_P2P sockets std::queue>> data{}; } p2p; struct p2ps_i { enum tcp_flags : u8 { FIN = (1 << 0), SYN = (1 << 1), RST = (1 << 2), PSH = (1 << 3), ACK = (1 << 4), URG = (1 << 5), ECE = (1 << 6), CWR = (1 << 7), }; static constexpr be_t U2S_sig = (static_cast('U') << 24 | static_cast('2') << 16 | static_cast('S') << 8 | static_cast('0')); static constexpr usz MAX_RECEIVED_BUFFER = (1024*1024*10); // P2P stream socket specific struct encapsulated_tcp { be_t signature = lv2_socket::p2ps_i::U2S_sig; // Signature to verify it's P2P Stream data be_t length = 0; // Length of data be_t seq = 0; // This should be u32 but changed to u64 for simplicity be_t ack = 0; be_t src_port = 0; // fake source tcp port be_t dst_port = 0; // fake dest tcp port(should be == vport) be_t checksum = 0; u8 flags = 0; }; enum stream_status { stream_closed, // Default when port is not listening nor connected stream_listening, // Stream is listening, accepting SYN packets stream_handshaking, // Currently handshaking stream_connected, // This is an established connection(after tcp handshake) }; stream_status status = stream_status::stream_closed; usz max_backlog = 0; // set on listen std::queue backlog; u16 op_port = 0, op_vport = 0; u32 op_addr = 0; u64 data_beg_seq = 0; // Seq of first byte of received_data u32 data_available = 0; // Amount of continuous data available(calculated on ACK send) std::map> received_data; // holds seq/data of data received u32 cur_seq = 0; // SEQ of next packet to be sent } p2ps; // Value keepers #ifdef _WIN32 s32 so_reuseaddr = 0; s32 so_reuseport = 0; #endif // Event processing workload (pair of thread id and the processing function) std::vector)>>> queue; }; class ppu_thread; // Syscalls error_code sys_net_bnet_accept(ppu_thread&, s32 s, vm::ptr addr, vm::ptr paddrlen); error_code sys_net_bnet_bind(ppu_thread&, s32 s, vm::cptr addr, u32 addrlen); error_code sys_net_bnet_connect(ppu_thread&, s32 s, vm::ptr addr, u32 addrlen); error_code sys_net_bnet_getpeername(ppu_thread&, s32 s, vm::ptr addr, vm::ptr paddrlen); error_code sys_net_bnet_getsockname(ppu_thread&, s32 s, vm::ptr addr, vm::ptr paddrlen); error_code sys_net_bnet_getsockopt(ppu_thread&, s32 s, s32 level, s32 optname, vm::ptr optval, vm::ptr optlen); error_code sys_net_bnet_listen(ppu_thread&, s32 s, s32 backlog); error_code sys_net_bnet_recvfrom(ppu_thread&, s32 s, vm::ptr buf, u32 len, s32 flags, vm::ptr addr, vm::ptr paddrlen); error_code sys_net_bnet_recvmsg(ppu_thread&, s32 s, vm::ptr msg, s32 flags); error_code sys_net_bnet_sendmsg(ppu_thread&, s32 s, vm::cptr msg, s32 flags); error_code sys_net_bnet_sendto(ppu_thread&, s32 s, vm::cptr buf, u32 len, s32 flags, vm::cptr addr, u32 addrlen); error_code sys_net_bnet_setsockopt(ppu_thread&, s32 s, s32 level, s32 optname, vm::cptr optval, u32 optlen); error_code sys_net_bnet_shutdown(ppu_thread&, s32 s, s32 how); error_code sys_net_bnet_socket(ppu_thread&, s32 family, s32 type, s32 protocol); error_code sys_net_bnet_close(ppu_thread&, s32 s); error_code sys_net_bnet_poll(ppu_thread&, vm::ptr fds, s32 nfds, s32 ms); error_code sys_net_bnet_select(ppu_thread&, s32 nfds, vm::ptr readfds, vm::ptr writefds, vm::ptr exceptfds, vm::ptr timeout); error_code _sys_net_open_dump(ppu_thread&, s32 len, s32 flags); error_code _sys_net_read_dump(ppu_thread&, s32 id, vm::ptr buf, s32 len, vm::ptr pflags); error_code _sys_net_close_dump(ppu_thread&, s32 id, vm::ptr pflags); error_code _sys_net_write_dump(ppu_thread&, s32 id, vm::cptr buf, s32 len, u32 unknown); error_code sys_net_abort(ppu_thread&, s32 type, u64 arg, s32 flags); error_code sys_net_infoctl(ppu_thread&, s32 cmd, vm::ptr arg); error_code sys_net_control(ppu_thread&, u32 arg1, s32 arg2, vm::ptr arg3, s32 arg4); error_code sys_net_bnet_ioctl(ppu_thread&, s32 arg1, u32 arg2, u32 arg3); error_code sys_net_bnet_sysctl(ppu_thread&, u32 arg1, u32 arg2, u32 arg3, vm::ptr arg4, u32 arg5, u32 arg6); error_code sys_net_eurus_post_command(ppu_thread&, s32 arg1, u32 arg2, u32 arg3);