#pragma once #include #include #include #include "Utilities/mutex.h" #ifdef _WIN32 #include #include #else #include #include #include #endif #include "Emu/Memory/vm.h" #include "Emu/Memory/vm_ptr.h" #include "Emu/Cell/Modules/sceNp.h" #include "Emu/Cell/Modules/sceNp2.h" #include "generated/np2_structs_generated.h" #include class vec_stream { public: vec_stream() = delete; vec_stream(std::vector& _vec, usz initial_index = 0) : vec(_vec) , i(initial_index){}; bool is_error() const { return error; } // Getters template T get() { if (sizeof(T) + i > vec.size()) { error = true; return 0; } T res = reinterpret_cast&>(vec[i]); i += sizeof(T); return res; } std::string get_string(bool empty) { std::string res{}; while (i < vec.size() && vec[i] != 0) { res.push_back(vec[i]); i++; } i++; if (!empty && res.size() == 0) { error = true; } return res; } std::vector get_rawdata() { std::vector ret; u32 size = get(); if ((vec.begin() + i + size) <= vec.end()) std::copy(vec.begin() + i, vec.begin() + i + size, std::back_inserter(ret)); else error = true; return ret; } // Setters template void insert(T value) { value = reinterpret_cast>(value); // resize + memcpy instead? for (usz index = 0; index < sizeof(T); index++) { vec.push_back(*(reinterpret_cast(&value) + index)); } } void insert_string(const std::string& str) { std::copy(str.begin(), str.end(), std::back_inserter(vec)); vec.push_back(0); } protected: std::vector& vec; usz i = 0; bool error = false; }; enum CommandType : u16 { Login, Terminate, Create, SendToken, GetServerList, GetWorldList, CreateRoom, JoinRoom, LeaveRoom, SearchRoom, SetRoomDataExternal, GetRoomDataInternal, SetRoomDataInternal, PingRoomOwner, SendRoomMessage, RequestSignalingInfos, RequestTicket, }; class rpcn_client { enum PacketType : u8 { Request, Reply, Notification, ServerInfo, }; enum ErrorType : u8 { NoError, Malformed, Invalid, InvalidInput, ErrorLogin, ErrorCreate, AlreadyLoggedIn, AlreadyJoined, DbFail, NotFound, Unsupported, __error_last }; public: rpcn_client(bool in_config = false); ~rpcn_client(); bool connect(const std::string& host); bool login(const std::string& npid, const std::string& password, const std::string& token); bool create_user(const std::string& npid, const std::string& password, const std::string& online_name, const std::string& avatar_url, const std::string& email); void disconnect(); bool manage_connection(); std::vector>> get_notifications(); std::unordered_map>> get_replies(); void abort(); // Synchronous requests bool get_server_list(u32 req_id, const SceNpCommunicationId& communication_id, std::vector& server_list); // Asynchronous requests bool get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id); bool createjoin_room(u32 req_id,const SceNpCommunicationId& communication_id, const SceNpMatching2CreateJoinRoomRequest* req); bool join_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2JoinRoomRequest* req); bool leave_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2LeaveRoomRequest* req); bool search_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SearchRoomRequest* req); bool set_roomdata_external(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataExternalRequest* req); bool get_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataInternalRequest* req); bool set_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataInternalRequest* req); bool ping_room_owner(u32 req_id, const SceNpCommunicationId& communication_id, u64 room_id); bool send_room_message(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SendRoomMessageRequest* req); bool req_sign_infos(u32 req_id, const std::string& npid); bool req_ticket(u32 req_id, const std::string& service_id); const std::string& get_online_name() const { return online_name; } const std::string& get_avatar_url() const { return avatar_url; }; u32 get_addr_sig() const { return addr_sig.load(); } u16 get_port_sig() const { return port_sig.load(); } protected: enum class recvn_result { recvn_success, recvn_nodata, recvn_timeout, recvn_noconn, recvn_fatal, }; recvn_result recvn(u8* buf, usz n); bool get_reply(u32 expected_id, std::vector& data); std::vector forge_request(u16 command, u32 packet_id, const std::vector& data) const; bool send_packet(const std::vector& packet); bool forge_send(u16 command, u32 packet_id, const std::vector& data); bool forge_send_reply(u16 command, u32 packet_id, const std::vector& data, std::vector& reply_data); bool is_error(ErrorType err) const; bool error_and_disconnect(const std::string& error_mgs); bool is_abort(); std::string get_wolfssl_error(int error); protected: atomic_t connected = false; atomic_t authentified = false; WOLFSSL_CTX* wssl_ctx = nullptr; WOLFSSL* wssl = nullptr; bool in_config = false; bool abort_config = false; atomic_t server_info_received = false; u32 received_version = 0; // UDP Signaling related steady_clock::time_point last_ping_time{}, last_pong_time{}; sockaddr_in addr_rpcn{}; sockaddr_in addr_rpcn_udp{}; int sockfd = 0; shared_mutex mutex_socket; shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync; std::vector>> notifications; // notif type / data std::unordered_map>> replies; // req id / (command / data) std::unordered_map>> replies_sync; // same but for sync replies(Login, Create, GetServerList) std::string online_name{}; std::string avatar_url{}; s64 user_id = 0; atomic_t addr_sig{}; atomic_t port_sig{}; };