#pragma once #ifdef _WIN32 #include #include #else #ifdef __clang__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" #endif #include #ifdef __clang__ #pragma GCC diagnostic pop #endif #endif #include "lv2_socket_p2p.h" constexpr be_t P2PS_U2S_SIG = (static_cast('U') << 24 | static_cast('2') << 16 | static_cast('S') << 8 | static_cast('0')); struct p2ps_encapsulated_tcp { be_t signature = P2PS_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 p2ps_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) }; enum p2ps_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), }; void initialize_tcp_timeout_monitor(); u16 u2s_tcp_checksum(const u16* buffer, usz size); std::vector generate_u2s_packet(const p2ps_encapsulated_tcp& header, const u8* data, const u32 datasize); class lv2_socket_p2ps final : public lv2_socket_p2p { public: lv2_socket_p2ps(lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol); lv2_socket_p2ps(socket_type socket, u16 port, u16 vport, u32 op_addr, u16 op_port, u16 op_vport, u64 cur_seq, u64 data_beg_seq); p2ps_stream_status get_status() const; void set_status(p2ps_stream_status new_status); bool handle_connected(p2ps_encapsulated_tcp* tcp_header, u8* data, ::sockaddr_storage* op_addr); bool handle_listening(p2ps_encapsulated_tcp* tcp_header, u8* data, ::sockaddr_storage* op_addr); void send_u2s_packet(std::vector data, const ::sockaddr_in* dst, u32 seq, bool require_ack); std::tuple, sys_net_sockaddr> accept(bool is_lock = true) override; s32 bind(const sys_net_sockaddr& addr, s32 ps3_id) override; std::optional connect(const sys_net_sockaddr& addr) override; std::pair getsockname() override; s32 listen(s32 backlog) override; std::optional, sys_net_sockaddr>> recvfrom(s32 flags, u32 len, bool is_lock = true) override; std::optional sendto(s32 flags, const std::vector& buf, std::optional opt_sn_addr, bool is_lock = true) override; void close() override; s32 shutdown(s32 how) override; s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; std::tuple select(bs_t selected, pollfd& native_pfd) override; protected: static constexpr usz MAX_RECEIVED_BUFFER = (1024 * 1024 * 10); p2ps_stream_status status = p2ps_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 u64 data_available = 0; // Amount of continuous data available(calculated on ACK send) std::map> received_data; // holds seq/data of data received u64 cur_seq = 0; // SEQ of next packet to be sent };