mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
RPCN v1.4
This commit is contained in:
parent
a9b0f76698
commit
159370446f
41 changed files with 2150 additions and 1197 deletions
|
@ -462,6 +462,7 @@ target_sources(rpcs3_emu PRIVATE
|
|||
NP/rpcn_countries.cpp
|
||||
NP/upnp_config.cpp
|
||||
NP/upnp_handler.cpp
|
||||
NP/ip_address.cpp
|
||||
)
|
||||
|
||||
# Memory
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Emu/NP/rpcn_types.h"
|
||||
#include "cellRtc.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "util/shared_ptr.hpp"
|
||||
|
@ -1826,7 +1827,7 @@ public:
|
|||
virtual ~SendMessageDialogBase() = default;
|
||||
|
||||
virtual error_code Exec(message_data& msg_data, std::set<std::string>& npids) = 0;
|
||||
virtual void callback_handler(u16 ntype, const std::string& username, bool status) = 0;
|
||||
virtual void callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status) = 0;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<rpcn::rpcn_client> m_rpcn;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#ifdef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
|
|
|
@ -35,7 +35,7 @@ std::size_t lv2_socket::get_queue_size() const
|
|||
}
|
||||
socket_type lv2_socket::get_socket() const
|
||||
{
|
||||
return socket;
|
||||
return native_socket;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Utilities/mutex.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/lv2/sys_net.h"
|
||||
#include "Emu/NP/ip_address.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
|
@ -21,12 +22,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
using socket_type = uptr;
|
||||
#else
|
||||
using socket_type = int;
|
||||
#endif
|
||||
|
||||
enum class thread_state : u32;
|
||||
|
||||
class lv2_socket
|
||||
|
@ -126,7 +121,7 @@ protected:
|
|||
shared_mutex mutex;
|
||||
s32 lv2_id = 0;
|
||||
|
||||
socket_type socket = 0;
|
||||
socket_type native_socket = 0;
|
||||
|
||||
lv2_socket_family family{};
|
||||
lv2_socket_type type{};
|
||||
|
|
|
@ -87,9 +87,9 @@ s32 lv2_socket_native::create_socket()
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
void lv2_socket_native::set_socket(socket_type socket, lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol)
|
||||
void lv2_socket_native::set_socket(socket_type native_socket, lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol)
|
||||
{
|
||||
this->socket = socket;
|
||||
this->native_socket = native_socket;
|
||||
this->family = family;
|
||||
this->type = type;
|
||||
this->protocol = protocol;
|
||||
|
@ -115,12 +115,12 @@ std::tuple<bool, s32, shared_ptr<lv2_socket>, sys_net_sockaddr> lv2_socket_nativ
|
|||
sys_net.error("Calling socket::accept() from a previously connected socket!");
|
||||
}
|
||||
|
||||
socket_type native_socket = ::accept(socket, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen);
|
||||
socket_type client_socket = ::accept(native_socket, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen);
|
||||
|
||||
if (native_socket != invalid_socket)
|
||||
if (client_socket != invalid_socket)
|
||||
{
|
||||
auto newsock = make_single<lv2_socket_native>(family, type, protocol);
|
||||
newsock->set_socket(native_socket, family, type, protocol);
|
||||
newsock->set_socket(client_socket, family, type, protocol);
|
||||
|
||||
// Sockets inherit non blocking behaviour from their parent
|
||||
newsock->so_nbio = so_nbio;
|
||||
|
@ -173,7 +173,7 @@ s32 lv2_socket_native::bind(const sys_net_sockaddr& addr)
|
|||
|
||||
sys_net.warning("[Native] Trying to bind %s:%d", native_addr.sin_addr, std::bit_cast<be_t<u16>, u16>(native_addr.sin_port));
|
||||
|
||||
if (::bind(socket, reinterpret_cast<struct sockaddr*>(&native_addr), native_addr_len) == 0)
|
||||
if (::bind(native_socket, reinterpret_cast<struct sockaddr*>(&native_addr), native_addr_len) == 0)
|
||||
{
|
||||
// Only UPNP port forward binds to 0.0.0.0
|
||||
if (saddr == 0)
|
||||
|
@ -182,7 +182,7 @@ s32 lv2_socket_native::bind(const sys_net_sockaddr& addr)
|
|||
{
|
||||
sockaddr_in client_addr;
|
||||
socklen_t client_addr_size = sizeof(client_addr);
|
||||
ensure(::getsockname(socket, reinterpret_cast<struct sockaddr*>(&client_addr), &client_addr_size) == 0);
|
||||
ensure(::getsockname(native_socket, reinterpret_cast<struct sockaddr*>(&client_addr), &client_addr_size) == 0);
|
||||
bound_port = std::bit_cast<u16, be_t<u16>>(client_addr.sin_port);
|
||||
}
|
||||
else
|
||||
|
@ -245,7 +245,7 @@ std::optional<s32> lv2_socket_native::connect(const sys_net_sockaddr& addr)
|
|||
return -SYS_NET_EALREADY;
|
||||
}
|
||||
|
||||
if (::connect(socket, reinterpret_cast<struct sockaddr*>(&native_addr), native_addr_len) == 0)
|
||||
if (::connect(native_socket, reinterpret_cast<struct sockaddr*>(&native_addr), native_addr_len) == 0)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ std::optional<s32> lv2_socket_native::connect(const sys_net_sockaddr& addr)
|
|||
{
|
||||
int native_error;
|
||||
::socklen_t size = sizeof(native_error);
|
||||
if (::getsockopt(socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&native_error), &size) != 0 || size != sizeof(int))
|
||||
if (::getsockopt(native_socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&native_error), &size) != 0 || size != sizeof(int))
|
||||
{
|
||||
so_error = 1;
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ s32 lv2_socket_native::connect_followup()
|
|||
{
|
||||
int native_error;
|
||||
::socklen_t size = sizeof(native_error);
|
||||
if (::getsockopt(socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&native_error), &size) != 0 || size != sizeof(int))
|
||||
if (::getsockopt(native_socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&native_error), &size) != 0 || size != sizeof(int))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ std::pair<s32, sys_net_sockaddr> lv2_socket_native::getpeername()
|
|||
::sockaddr_storage native_addr;
|
||||
::socklen_t native_addrlen = sizeof(native_addr);
|
||||
|
||||
if (::getpeername(socket, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen) == 0)
|
||||
if (::getpeername(native_socket, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen) == 0)
|
||||
{
|
||||
ensure(native_addr.ss_family == AF_INET);
|
||||
|
||||
|
@ -339,7 +339,7 @@ std::pair<s32, sys_net_sockaddr> lv2_socket_native::getsockname()
|
|||
::sockaddr_storage native_addr;
|
||||
::socklen_t native_addrlen = sizeof(native_addr);
|
||||
|
||||
if (::getsockname(socket, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen) == 0)
|
||||
if (::getsockname(native_socket, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen) == 0)
|
||||
{
|
||||
ensure(native_addr.ss_family == AF_INET);
|
||||
|
||||
|
@ -581,7 +581,7 @@ std::tuple<s32, lv2_socket::sockopt_data, u32> lv2_socket_native::getsockopt(s32
|
|||
return {-SYS_NET_EINVAL, {}, {}};
|
||||
}
|
||||
|
||||
if (::getsockopt(socket, native_level, native_opt, native_val.ch, &native_len) != 0)
|
||||
if (::getsockopt(native_socket, native_level, native_opt, native_val.ch, &native_len) != 0)
|
||||
{
|
||||
return {-get_last_error(false), {}, {}};
|
||||
}
|
||||
|
@ -864,7 +864,7 @@ s32 lv2_socket_native::setsockopt(s32 level, s32 optname, const std::vector<u8>&
|
|||
return -SYS_NET_EINVAL;
|
||||
}
|
||||
|
||||
if (::setsockopt(socket, native_level, native_opt, static_cast<const char*>(native_val), native_len) == 0)
|
||||
if (::setsockopt(native_socket, native_level, native_opt, static_cast<const char*>(native_val), native_len) == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
@ -876,7 +876,7 @@ s32 lv2_socket_native::listen(s32 backlog)
|
|||
{
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
if (::listen(socket, backlog) == 0)
|
||||
if (::listen(native_socket, backlog) == 0)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -930,7 +930,7 @@ std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> lv2_socket_nat
|
|||
native_flags |= MSG_WAITALL;
|
||||
}
|
||||
|
||||
auto native_result = ::recvfrom(socket, reinterpret_cast<char*>(res_buf.data()), len, native_flags, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen);
|
||||
auto native_result = ::recvfrom(native_socket, reinterpret_cast<char*>(res_buf.data()), len, native_flags, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen);
|
||||
|
||||
if (native_result >= 0)
|
||||
{
|
||||
|
@ -1021,7 +1021,7 @@ std::optional<s32> lv2_socket_native::sendto(s32 flags, const std::vector<u8>& b
|
|||
}
|
||||
}
|
||||
|
||||
native_result = ::sendto(socket, reinterpret_cast<const char*>(buf.data()), ::narrow<int>(buf.size()), native_flags, native_addr ? reinterpret_cast<struct sockaddr*>(&native_addr.value()) : nullptr, native_addr ? sizeof(sockaddr_in) : 0);
|
||||
native_result = ::sendto(native_socket, reinterpret_cast<const char*>(buf.data()), ::narrow<int>(buf.size()), native_flags, native_addr ? reinterpret_cast<struct sockaddr*>(&native_addr.value()) : nullptr, native_addr ? sizeof(sockaddr_in) : 0);
|
||||
|
||||
if (native_result >= 0)
|
||||
{
|
||||
|
@ -1075,7 +1075,7 @@ std::optional<s32> lv2_socket_native::sendmsg(s32 flags, const sys_net_msghdr& m
|
|||
const u32 len = msg.msg_iov[i].iov_len;
|
||||
const std::vector<u8> buf_copy(vm::_ptr<const char>(iov_base.addr()), vm::_ptr<const char>(iov_base.addr()) + len);
|
||||
|
||||
native_result = ::send(socket, reinterpret_cast<const char*>(buf_copy.data()), ::narrow<int>(buf_copy.size()), native_flags);
|
||||
native_result = ::send(native_socket, reinterpret_cast<const char*>(buf_copy.data()), ::narrow<int>(buf_copy.size()), native_flags);
|
||||
|
||||
if (native_result >= 0)
|
||||
{
|
||||
|
@ -1096,15 +1096,9 @@ std::optional<s32> lv2_socket_native::sendmsg(s32 flags, const sys_net_msghdr& m
|
|||
void lv2_socket_native::close()
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
if (socket)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::closesocket(socket);
|
||||
#else
|
||||
::close(socket);
|
||||
#endif
|
||||
socket = {};
|
||||
}
|
||||
|
||||
np::close_socket(native_socket);
|
||||
native_socket = {};
|
||||
|
||||
if (auto dnshook = g_fxo->try_get<np::dnshook>())
|
||||
{
|
||||
|
@ -1141,7 +1135,7 @@ s32 lv2_socket_native::shutdown(s32 how)
|
|||
SHUT_RDWR;
|
||||
#endif
|
||||
|
||||
if (::shutdown(socket, native_how) == 0)
|
||||
if (::shutdown(native_socket, native_how) == 0)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -1163,7 +1157,7 @@ s32 lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd)
|
|||
sys_net.warning("sys_net_bnet_poll(fd=%d): events=0x%x", sn_pfd.fd, sn_pfd.events);
|
||||
}
|
||||
|
||||
native_pfd.fd = socket;
|
||||
native_pfd.fd = native_socket;
|
||||
|
||||
if (sn_pfd.events & SYS_NET_POLLIN)
|
||||
{
|
||||
|
@ -1179,7 +1173,7 @@ s32 lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd)
|
|||
|
||||
std::tuple<bool, bool, bool> lv2_socket_native::select(bs_t<lv2_socket::poll_t> selected, pollfd& native_pfd)
|
||||
{
|
||||
native_pfd.fd = socket;
|
||||
native_pfd.fd = native_socket;
|
||||
if (selected & lv2_socket::poll_t::read)
|
||||
{
|
||||
native_pfd.events |= POLLIN;
|
||||
|
@ -1196,12 +1190,12 @@ void lv2_socket_native::set_default_buffers()
|
|||
{
|
||||
// Those are the default PS3 values
|
||||
u32 default_RCVBUF = (type == SYS_NET_SOCK_STREAM) ? 65535 : 9216;
|
||||
if (::setsockopt(socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&default_RCVBUF), sizeof(default_RCVBUF)) != 0)
|
||||
if (::setsockopt(native_socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&default_RCVBUF), sizeof(default_RCVBUF)) != 0)
|
||||
{
|
||||
sys_net.error("Error setting default SO_RCVBUF on sys_net_bnet_socket socket");
|
||||
}
|
||||
u32 default_SNDBUF = 131072;
|
||||
if (::setsockopt(socket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&default_SNDBUF), sizeof(default_SNDBUF)) != 0)
|
||||
if (::setsockopt(native_socket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&default_SNDBUF), sizeof(default_SNDBUF)) != 0)
|
||||
{
|
||||
sys_net.error("Error setting default SO_SNDBUF on sys_net_bnet_socket socket");
|
||||
}
|
||||
|
@ -1212,12 +1206,7 @@ void lv2_socket_native::set_non_blocking()
|
|||
// Set non-blocking
|
||||
// This is done to avoid having threads stuck on blocking socket functions
|
||||
// Blocking functions just put the thread to sleep and delegate the waking up to network_thread which polls the sockets
|
||||
#ifdef _WIN32
|
||||
u_long _true = 1;
|
||||
::ioctlsocket(socket, FIONBIO, &_true);
|
||||
#else
|
||||
::fcntl(socket, F_SETFL, ::fcntl(socket, F_GETFL, 0) | O_NONBLOCK);
|
||||
#endif
|
||||
np::set_socket_non_blocking(native_socket);
|
||||
}
|
||||
|
||||
bool lv2_socket_native::is_socket_connected()
|
||||
|
@ -1232,7 +1221,7 @@ bool lv2_socket_native::is_socket_connected()
|
|||
int listening = 0;
|
||||
socklen_t len = sizeof(listening);
|
||||
|
||||
if (::getsockopt(socket, SOL_SOCKET, SO_ACCEPTCONN, reinterpret_cast<char*>(&listening), &len) == -1)
|
||||
if (::getsockopt(native_socket, SOL_SOCKET, SO_ACCEPTCONN, reinterpret_cast<char*>(&listening), &len) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1248,8 +1237,8 @@ bool lv2_socket_native::is_socket_connected()
|
|||
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&writefds);
|
||||
FD_SET(socket, &readfds);
|
||||
FD_SET(socket, &writefds);
|
||||
FD_SET(native_socket, &readfds);
|
||||
FD_SET(native_socket, &writefds);
|
||||
|
||||
// Use select to check for readability and writability
|
||||
const int result = ::select(1, &readfds, &writefds, NULL, &timeout);
|
||||
|
@ -1261,5 +1250,5 @@ bool lv2_socket_native::is_socket_connected()
|
|||
}
|
||||
|
||||
// Socket is connected if it's readable or writable
|
||||
return FD_ISSET(socket, &readfds) || FD_ISSET(socket, &writefds);
|
||||
return FD_ISSET(native_socket, &readfds) || FD_ISSET(native_socket, &writefds);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#ifdef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
|
@ -61,7 +60,7 @@ public:
|
|||
s32 shutdown(s32 how) override;
|
||||
|
||||
private:
|
||||
void set_socket(socket_type socket, lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol);
|
||||
void set_socket(socket_type native_socket, lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol);
|
||||
void set_default_buffers();
|
||||
void set_non_blocking();
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ s32 lv2_socket_p2p::bind(const sys_net_sockaddr& addr)
|
|||
std::lock_guard lock(mutex);
|
||||
port = p2p_port;
|
||||
vport = p2p_vport;
|
||||
socket = real_socket;
|
||||
native_socket = real_socket;
|
||||
bound_addr = psa_in_p2p->sin_addr;
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ std::pair<s32, sys_net_sockaddr> lv2_socket_p2p::getsockname()
|
|||
std::lock_guard lock(mutex);
|
||||
|
||||
// Unbound socket
|
||||
if (!socket)
|
||||
if (!native_socket)
|
||||
{
|
||||
return {CELL_OK, {}};
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ std::optional<s32> lv2_socket_p2p::sendto(s32 flags, const std::vector<u8>& buf,
|
|||
native_flags |= MSG_WAITALL;
|
||||
}
|
||||
|
||||
auto native_result = ::sendto(socket, reinterpret_cast<const char*>(p2p_data.data()), ::size32(p2p_data), native_flags, reinterpret_cast<struct sockaddr*>(&native_addr), sizeof(native_addr));
|
||||
auto native_result = np::sendto_possibly_ipv6(native_socket, reinterpret_cast<const char*>(p2p_data.data()), ::size32(p2p_data), &native_addr, native_flags);
|
||||
|
||||
if (native_result >= 0)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include "Utilities/Thread.h"
|
||||
#include "util/asm.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include "lv2_socket_p2ps.h"
|
||||
#include "Emu/NP/np_helpers.h"
|
||||
|
@ -275,10 +274,10 @@ lv2_socket_p2ps::lv2_socket_p2ps(lv2_socket_family family, lv2_socket_type type,
|
|||
sockopts[(static_cast<u64>(SYS_NET_SOL_SOCKET) << 32ull) | SYS_NET_SO_TYPE] = cache_type;
|
||||
}
|
||||
|
||||
lv2_socket_p2ps::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, s32 so_nbio)
|
||||
lv2_socket_p2ps::lv2_socket_p2ps(socket_type native_socket, u16 port, u16 vport, u32 op_addr, u16 op_port, u16 op_vport, u64 cur_seq, u64 data_beg_seq, s32 so_nbio)
|
||||
: lv2_socket_p2p(SYS_NET_AF_INET, SYS_NET_SOCK_STREAM_P2P, SYS_NET_IPPROTO_IP)
|
||||
{
|
||||
this->socket = socket;
|
||||
this->native_socket = native_socket;
|
||||
this->port = port;
|
||||
this->vport = vport;
|
||||
this->op_addr = op_addr;
|
||||
|
@ -467,7 +466,7 @@ bool lv2_socket_p2ps::handle_listening(p2ps_encapsulated_tcp* tcp_header, [[mayb
|
|||
const u16 new_op_vport = tcp_header->src_port;
|
||||
const u64 new_cur_seq = send_hdr.seq + 1;
|
||||
const u64 new_data_beg_seq = send_hdr.ack;
|
||||
auto sock_lv2 = make_shared<lv2_socket_p2ps>(socket, port, vport, new_op_addr, new_op_port, new_op_vport, new_cur_seq, new_data_beg_seq, so_nbio);
|
||||
auto sock_lv2 = make_shared<lv2_socket_p2ps>(native_socket, port, vport, new_op_addr, new_op_port, new_op_vport, new_cur_seq, new_data_beg_seq, so_nbio);
|
||||
const s32 new_sock_id = idm::import_existing<lv2_socket>(sock_lv2);
|
||||
sock_lv2->set_lv2_id(new_sock_id);
|
||||
const u64 key_connected = (reinterpret_cast<struct sockaddr_in*>(op_addr)->sin_addr.s_addr) | (static_cast<u64>(tcp_header->src_port) << 48) | (static_cast<u64>(tcp_header->dst_port) << 32);
|
||||
|
@ -518,8 +517,9 @@ void lv2_socket_p2ps::send_u2s_packet(std::vector<u8> data, const ::sockaddr_in*
|
|||
{
|
||||
char ip_str[16];
|
||||
inet_ntop(AF_INET, &dst->sin_addr, ip_str, sizeof(ip_str));
|
||||
sys_net.trace("[P2PS] Sending U2S packet on socket %d(id:%d): data(%d, seq %d, require_ack %d) to %s:%d", socket, lv2_id, data.size(), seq, require_ack, ip_str, std::bit_cast<u16, be_t<u16>>(dst->sin_port));
|
||||
while (::sendto(socket, reinterpret_cast<char*>(data.data()), ::size32(data), 0, reinterpret_cast<const sockaddr*>(dst), sizeof(sockaddr_in)) == -1)
|
||||
sys_net.trace("[P2PS] Sending U2S packet on socket %d(id:%d): data(%d, seq %d, require_ack %d) to %s:%d", native_socket, lv2_id, data.size(), seq, require_ack, ip_str, std::bit_cast<u16, be_t<u16>>(dst->sin_port));
|
||||
|
||||
while (np::sendto_possibly_ipv6(native_socket, reinterpret_cast<char*>(data.data()), ::size32(data), dst, 0) == -1)
|
||||
{
|
||||
const sys_net_error err = get_last_error(false);
|
||||
// concurrency on the socket can result in EAGAIN error in which case we try again
|
||||
|
@ -707,7 +707,7 @@ s32 lv2_socket_p2ps::bind(const sys_net_sockaddr& addr)
|
|||
|
||||
port = p2p_port;
|
||||
vport = p2p_vport;
|
||||
socket = real_socket;
|
||||
native_socket = real_socket;
|
||||
bound_addr = psa_in_p2p->sin_addr;
|
||||
}
|
||||
}
|
||||
|
@ -720,7 +720,7 @@ std::pair<s32, sys_net_sockaddr> lv2_socket_p2ps::getsockname()
|
|||
std::lock_guard lock(mutex);
|
||||
|
||||
// Unbound socket
|
||||
if (!socket)
|
||||
if (!native_socket)
|
||||
{
|
||||
return {CELL_OK, {}};
|
||||
}
|
||||
|
@ -783,7 +783,7 @@ std::optional<s32> lv2_socket_p2ps::connect(const sys_net_sockaddr& addr)
|
|||
}
|
||||
}
|
||||
|
||||
socket = real_socket;
|
||||
native_socket = real_socket;
|
||||
|
||||
send_hdr.src_port = vport;
|
||||
send_hdr.dst_port = dst_vport;
|
||||
|
|
|
@ -1,35 +1,73 @@
|
|||
#include "Emu/NP/ip_address.h"
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
#include "Emu/Cell/Modules/sceNp.h" // for SCE_NP_PORT
|
||||
|
||||
#include "network_context.h"
|
||||
#include "Emu/system_config.h"
|
||||
#include "sys_net_helpers.h"
|
||||
|
||||
LOG_CHANNEL(sys_net);
|
||||
|
||||
// Used by RPCN to send signaling packets to RPCN server(for UDP hole punching)
|
||||
s32 send_packet_from_p2p_port(const std::vector<u8>& data, const sockaddr_in& addr)
|
||||
bool send_packet_from_p2p_port_ipv4(const std::vector<u8>& data, const sockaddr_in& addr)
|
||||
{
|
||||
s32 res{};
|
||||
auto& nc = g_fxo->get<p2p_context>();
|
||||
{
|
||||
std::lock_guard list_lock(nc.list_p2p_ports_mutex);
|
||||
if (nc.list_p2p_ports.contains(SCE_NP_PORT))
|
||||
{
|
||||
auto& def_port = ::at32(nc.list_p2p_ports, SCE_NP_PORT);
|
||||
res = ::sendto(def_port.p2p_socket, reinterpret_cast<const char*>(data.data()), ::size32(data), 0, reinterpret_cast<const sockaddr*>(&addr), sizeof(sockaddr_in));
|
||||
|
||||
if (res == -1)
|
||||
sys_net.error("Failed to send signaling packet: %s", get_last_error(false, false));
|
||||
if (def_port.is_ipv6)
|
||||
{
|
||||
const auto addr6 = np::sockaddr_to_sockaddr6(addr);
|
||||
|
||||
if (::sendto(def_port.p2p_socket, reinterpret_cast<const char*>(data.data()), ::size32(data), 0, reinterpret_cast<const sockaddr*>(&addr6), sizeof(sockaddr_in6)) == -1)
|
||||
{
|
||||
sys_net.error("Failed to send IPv4 signaling packet on IPv6 socket: %s", get_last_error(false, false));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (::sendto(def_port.p2p_socket, reinterpret_cast<const char*>(data.data()), ::size32(data), 0, reinterpret_cast<const sockaddr*>(&addr), sizeof(sockaddr_in)) == -1)
|
||||
{
|
||||
sys_net.error("Failed to send signaling packet on IPv4 socket: %s", get_last_error(false, false));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_net.error("send_packet_from_p2p_port: port %d not present", +SCE_NP_PORT);
|
||||
sys_net.error("send_packet_from_p2p_port_ipv4: port %d not present", +SCE_NP_PORT);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_packet_from_p2p_port_ipv6(const std::vector<u8>& data, const sockaddr_in6& addr)
|
||||
{
|
||||
auto& nc = g_fxo->get<p2p_context>();
|
||||
{
|
||||
std::lock_guard list_lock(nc.list_p2p_ports_mutex);
|
||||
if (nc.list_p2p_ports.contains(SCE_NP_PORT))
|
||||
{
|
||||
auto& def_port = ::at32(nc.list_p2p_ports, SCE_NP_PORT);
|
||||
ensure(def_port.is_ipv6);
|
||||
|
||||
if (::sendto(def_port.p2p_socket, reinterpret_cast<const char*>(data.data()), ::size32(data), 0, reinterpret_cast<const sockaddr*>(&addr), sizeof(sockaddr_in6)) == -1)
|
||||
{
|
||||
sys_net.error("Failed to send signaling packet on IPv6 socket: %s", get_last_error(false, false));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_net.error("send_packet_from_p2p_port_ipv6: port %d not present", +SCE_NP_PORT);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::vector<u8>> get_rpcn_msgs()
|
||||
|
@ -241,13 +279,18 @@ void p2p_thread::operator()()
|
|||
auto num_p2p_sockets = 0;
|
||||
std::memset(p2p_fd.data(), 0, p2p_fd.size() * sizeof(::pollfd));
|
||||
{
|
||||
std::lock_guard lock(list_p2p_ports_mutex);
|
||||
for (const auto& p2p_port : list_p2p_ports)
|
||||
auto set_fd = [&](socket_type socket)
|
||||
{
|
||||
p2p_fd[num_p2p_sockets].events = POLLIN;
|
||||
p2p_fd[num_p2p_sockets].revents = 0;
|
||||
p2p_fd[num_p2p_sockets].fd = p2p_port.second.p2p_socket;
|
||||
p2p_fd[num_p2p_sockets].fd = socket;
|
||||
num_p2p_sockets++;
|
||||
};
|
||||
|
||||
std::lock_guard lock(list_p2p_ports_mutex);
|
||||
for (const auto& [_, p2p_port] : list_p2p_ports)
|
||||
{
|
||||
set_fd(p2p_port.p2p_socket);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,14 +303,20 @@ void p2p_thread::operator()()
|
|||
{
|
||||
std::lock_guard lock(list_p2p_ports_mutex);
|
||||
auto fd_index = 0;
|
||||
for (auto& p2p_port : list_p2p_ports)
|
||||
|
||||
auto process_fd = [&](nt_p2p_port& p2p_port)
|
||||
{
|
||||
if ((p2p_fd[fd_index].revents & POLLIN) == POLLIN || (p2p_fd[fd_index].revents & POLLRDNORM) == POLLRDNORM)
|
||||
{
|
||||
while (p2p_port.second.recv_data())
|
||||
while (p2p_port.recv_data())
|
||||
;
|
||||
}
|
||||
fd_index++;
|
||||
};
|
||||
|
||||
for (auto& [_, p2p_port] : list_p2p_ports)
|
||||
{
|
||||
process_fd(p2p_port);
|
||||
}
|
||||
|
||||
wake_threads();
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "Emu/NP/ip_address.h"
|
||||
#include "nt_p2p_port.h"
|
||||
#include "lv2_socket_native.h"
|
||||
#include "lv2_socket_p2ps.h"
|
||||
#include "util/asm.hpp"
|
||||
#include "sys_net_helpers.h"
|
||||
#include "Emu/NP/signaling_handler.h"
|
||||
#include "sys_net_helpers.h"
|
||||
|
@ -44,9 +40,10 @@ namespace sys_net_helpers
|
|||
nt_p2p_port::nt_p2p_port(u16 port)
|
||||
: port(port)
|
||||
{
|
||||
// Creates and bind P2P Socket
|
||||
p2p_socket = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
is_ipv6 = np::is_ipv6_supported();
|
||||
|
||||
// Creates and bind P2P Socket
|
||||
p2p_socket = is_ipv6 ? ::socket(AF_INET6, SOCK_DGRAM, 0) : ::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
#ifdef _WIN32
|
||||
if (p2p_socket == INVALID_SOCKET)
|
||||
#else
|
||||
|
@ -54,22 +51,30 @@ nt_p2p_port::nt_p2p_port(u16 port)
|
|||
#endif
|
||||
fmt::throw_exception("Failed to create DGRAM socket for P2P socket: %s!", get_last_error(true));
|
||||
|
||||
#ifdef _WIN32
|
||||
u_long _true = 1;
|
||||
::ioctlsocket(p2p_socket, FIONBIO, &_true);
|
||||
#else
|
||||
::fcntl(p2p_socket, F_SETFL, ::fcntl(p2p_socket, F_GETFL, 0) | O_NONBLOCK);
|
||||
#endif
|
||||
np::set_socket_non_blocking(p2p_socket);
|
||||
|
||||
u32 optval = 131072; // value obtained from DECR for a SOCK_DGRAM_P2P socket(should maybe be bigger for actual socket?)
|
||||
if (setsockopt(p2p_socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&optval), sizeof(optval)) != 0)
|
||||
fmt::throw_exception("Error setsockopt SO_RCVBUF on P2P socket: %s", get_last_error(true));
|
||||
|
||||
::sockaddr_in p2p_saddr{};
|
||||
p2p_saddr.sin_family = AF_INET;
|
||||
p2p_saddr.sin_port = std::bit_cast<u16, be_t<u16>>(port); // htons(port);
|
||||
p2p_saddr.sin_addr.s_addr = 0; // binds to 0.0.0.0
|
||||
const auto ret_bind = ::bind(p2p_socket, reinterpret_cast<sockaddr*>(&p2p_saddr), sizeof(p2p_saddr));
|
||||
int ret_bind = 0;
|
||||
const u16 be_port = std::bit_cast<u16, be_t<u16>>(port);
|
||||
|
||||
if (is_ipv6)
|
||||
{
|
||||
// Some OS(Windows, maybe more) will only support IPv6 adressing by default and we need IPv4 over IPv6
|
||||
optval = 0;
|
||||
if (setsockopt(p2p_socket, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char*>(&optval), sizeof(optval)) != 0)
|
||||
fmt::throw_exception("Error setsockopt IPV6_V6ONLY on P2P socket: %s", get_last_error(true));
|
||||
|
||||
::sockaddr_in6 p2p_ipv6_addr{.sin6_family = AF_INET6, .sin6_port = be_port};
|
||||
ret_bind = ::bind(p2p_socket, reinterpret_cast<sockaddr*>(&p2p_ipv6_addr), sizeof(p2p_ipv6_addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
::sockaddr_in p2p_ipv4_addr{.sin_family = AF_INET, .sin_port = be_port};
|
||||
ret_bind = ::bind(p2p_socket, reinterpret_cast<sockaddr*>(&p2p_ipv4_addr), sizeof(p2p_ipv4_addr));
|
||||
}
|
||||
|
||||
if (ret_bind == -1)
|
||||
fmt::throw_exception("Failed to bind DGRAM socket to %d for P2P: %s!", port, get_last_error(true));
|
||||
|
@ -82,14 +87,7 @@ nt_p2p_port::nt_p2p_port(u16 port)
|
|||
|
||||
nt_p2p_port::~nt_p2p_port()
|
||||
{
|
||||
if (p2p_socket)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::closesocket(p2p_socket);
|
||||
#else
|
||||
::close(p2p_socket);
|
||||
#endif
|
||||
}
|
||||
np::close_socket(p2p_socket);
|
||||
}
|
||||
|
||||
void nt_p2p_port::dump_packet(p2ps_encapsulated_tcp* tcph)
|
||||
|
@ -153,7 +151,7 @@ bool nt_p2p_port::recv_data()
|
|||
{
|
||||
auto lerr = get_last_error(false);
|
||||
if (lerr != SYS_NET_EINPROGRESS && lerr != SYS_NET_EWOULDBLOCK)
|
||||
sys_net.error("Error recvfrom on P2P socket: %d", lerr);
|
||||
sys_net.error("Error recvfrom on %s P2P socket: %d", is_ipv6 ? "IPv6" : "IPv4", lerr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -166,6 +164,14 @@ bool nt_p2p_port::recv_data()
|
|||
|
||||
u16 dst_vport = reinterpret_cast<le_t<u16>&>(p2p_recv_data[0]);
|
||||
|
||||
if (is_ipv6)
|
||||
{
|
||||
const auto* addr_ipv6 = reinterpret_cast<sockaddr_in6*>(&native_addr);
|
||||
const auto addr_ipv4 = np::sockaddr6_to_sockaddr(*addr_ipv6);
|
||||
native_addr = {};
|
||||
std::memcpy(&native_addr, &addr_ipv4, sizeof(addr_ipv4));
|
||||
}
|
||||
|
||||
if (dst_vport == 0)
|
||||
{
|
||||
if (recv_res < VPORT_0_HEADER_SIZE)
|
||||
|
@ -339,7 +345,7 @@ bool nt_p2p_port::recv_data()
|
|||
send_hdr.flags = p2ps_tcp_flags::RST;
|
||||
auto packet = generate_u2s_packet(send_hdr, nullptr, 0);
|
||||
|
||||
if (::sendto(p2p_socket, reinterpret_cast<char*>(packet.data()), ::size32(packet), 0, reinterpret_cast<const sockaddr*>(&native_addr), sizeof(sockaddr_in)) == -1)
|
||||
if (np::sendto_possibly_ipv6(p2p_socket, reinterpret_cast<char*>(packet.data()), ::size32(packet), reinterpret_cast<const sockaddr_in*>(&native_addr), 0) == -1)
|
||||
{
|
||||
sys_net.error("[P2PS] Error sending RST to sender to unbound P2PS: %s", get_last_error(false));
|
||||
return true;
|
||||
|
|
|
@ -48,6 +48,8 @@ struct nt_p2p_port
|
|||
socket_type p2p_socket = 0;
|
||||
u16 port = 0;
|
||||
|
||||
bool is_ipv6 = false;
|
||||
|
||||
shared_mutex bound_p2p_vports_mutex;
|
||||
// For DGRAM_P2P sockets (vport, sock_ids)
|
||||
std::map<u16, std::set<s32>> bound_p2p_vports{};
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
|
||||
#include "lv2_socket.h"
|
||||
#include "sys_net_helpers.h"
|
||||
|
||||
#include "network_context.h"
|
||||
|
||||
LOG_CHANNEL(sys_net);
|
||||
|
@ -32,13 +29,13 @@ sys_net_error convert_error(bool is_blocking, int native_error, [[maybe_unused]]
|
|||
#define ERROR_CASE(error) \
|
||||
case WSA##error: \
|
||||
result = SYS_NET_##error; \
|
||||
name = #error; \
|
||||
name = #error; \
|
||||
break;
|
||||
#else
|
||||
#define ERROR_CASE(error) \
|
||||
case error: \
|
||||
result = SYS_NET_##error; \
|
||||
name = #error; \
|
||||
name = #error; \
|
||||
break;
|
||||
#endif
|
||||
switch (native_error)
|
||||
|
@ -86,11 +83,11 @@ sys_net_error convert_error(bool is_blocking, int native_error, [[maybe_unused]]
|
|||
ERROR_CASE(EHOSTDOWN);
|
||||
ERROR_CASE(EHOSTUNREACH);
|
||||
#ifdef _WIN32
|
||||
// Windows likes to be special with unique errors
|
||||
case WSAENETRESET:
|
||||
result = SYS_NET_ECONNRESET;
|
||||
name = "WSAENETRESET";
|
||||
break;
|
||||
// Windows likes to be special with unique errors
|
||||
case WSAENETRESET:
|
||||
result = SYS_NET_ECONNRESET;
|
||||
name = "WSAENETRESET";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fmt::throw_exception("sys_net get_last_error(is_blocking=%d, native_error=%d): Unknown/illegal socket error", is_blocking, native_error);
|
||||
|
@ -137,11 +134,11 @@ sys_net_sockaddr native_addr_to_sys_net_addr(const ::sockaddr_storage& native_ad
|
|||
|
||||
sys_net_sockaddr_in* paddr = reinterpret_cast<sys_net_sockaddr_in*>(&sn_addr);
|
||||
|
||||
paddr->sin_len = sizeof(sys_net_sockaddr_in);
|
||||
paddr->sin_len = sizeof(sys_net_sockaddr_in);
|
||||
paddr->sin_family = SYS_NET_AF_INET;
|
||||
paddr->sin_port = std::bit_cast<be_t<u16>, u16>(reinterpret_cast<const sockaddr_in*>(&native_addr)->sin_port);
|
||||
paddr->sin_addr = std::bit_cast<be_t<u32>, u32>(reinterpret_cast<const sockaddr_in*>(&native_addr)->sin_addr.s_addr);
|
||||
paddr->sin_zero = 0;
|
||||
paddr->sin_port = std::bit_cast<be_t<u16>, u16>(reinterpret_cast<const sockaddr_in*>(&native_addr)->sin_port);
|
||||
paddr->sin_addr = std::bit_cast<be_t<u32>, u32>(reinterpret_cast<const sockaddr_in*>(&native_addr)->sin_addr.s_addr);
|
||||
paddr->sin_zero = 0;
|
||||
|
||||
return sn_addr;
|
||||
}
|
||||
|
@ -153,8 +150,8 @@ sys_net_sockaddr native_addr_to_sys_net_addr(const ::sockaddr_storage& native_ad
|
|||
const sys_net_sockaddr_in* psa_in = reinterpret_cast<const sys_net_sockaddr_in*>(&sn_addr);
|
||||
|
||||
::sockaddr_in native_addr{};
|
||||
native_addr.sin_family = AF_INET;
|
||||
native_addr.sin_port = std::bit_cast<u16>(psa_in->sin_port);
|
||||
native_addr.sin_family = AF_INET;
|
||||
native_addr.sin_port = std::bit_cast<u16>(psa_in->sin_port);
|
||||
native_addr.sin_addr.s_addr = std::bit_cast<u32>(psa_in->sin_addr);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -189,9 +186,9 @@ u32 network_clear_queue(ppu_thread& ppu)
|
|||
u32 cleared = 0;
|
||||
|
||||
idm::select<lv2_socket>([&](u32, lv2_socket& sock)
|
||||
{
|
||||
cleared += sock.clear_queue(&ppu);
|
||||
});
|
||||
{
|
||||
cleared += sock.clear_queue(&ppu);
|
||||
});
|
||||
|
||||
return cleared;
|
||||
}
|
||||
|
@ -204,6 +201,7 @@ void clear_ppu_to_awake(ppu_thread& ppu)
|
|||
|
||||
#ifdef _WIN32
|
||||
// Workaround function for WSAPoll not reporting failed connections
|
||||
// Note that this was fixed in Windows 10 version 2004 (after more than 10 years lol)
|
||||
void windows_poll(std::vector<pollfd>& fds, unsigned long nfds, int timeout, std::vector<bool>& connecting)
|
||||
{
|
||||
ensure(fds.size() >= nfds);
|
||||
|
@ -237,12 +235,12 @@ void windows_poll(std::vector<pollfd>& fds, unsigned long nfds, int timeout, std
|
|||
{
|
||||
if (!fds[i].revents)
|
||||
{
|
||||
int error = 0;
|
||||
int error = 0;
|
||||
socklen_t intlen = sizeof(error);
|
||||
if (getsockopt(fds[i].fd, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &intlen) == -1 || error != 0)
|
||||
{
|
||||
// Connection silently failed
|
||||
connecting[i] = false;
|
||||
connecting[i] = false;
|
||||
fds[i].revents = POLLERR | POLLHUP | (fds[i].events & (POLLIN | POLLOUT));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace np
|
|||
{
|
||||
sce_group->groupId = fb_group->groupId();
|
||||
sce_group->withPassword = fb_group->withPassword();
|
||||
sce_group->withLabel = fb_group->withLabel();
|
||||
sce_group->withLabel = fb_group->label() ? 1 : 0;
|
||||
if (fb_group->label())
|
||||
{
|
||||
for (flatbuffers::uoffset_t l_index = 0; l_index < fb_group->label()->size(); l_index++)
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
table SignalingAddr {
|
||||
ip:[uint8];
|
||||
port:uint16;
|
||||
}
|
||||
|
||||
table MatchingSignalingInfo {
|
||||
npid:string;
|
||||
addr:SignalingAddr;
|
||||
}
|
||||
|
||||
table Matching2SignalingInfo {
|
||||
member_id:uint16;
|
||||
addr:SignalingAddr;
|
||||
}
|
||||
|
||||
table BinAttr {
|
||||
id:uint16;
|
||||
data:[uint8];
|
||||
|
@ -27,7 +42,6 @@ table OptParam {
|
|||
|
||||
table GroupConfig {
|
||||
slotNum:uint32;
|
||||
withLabel:bool;
|
||||
label:[uint8];
|
||||
withPassword:bool;
|
||||
}
|
||||
|
@ -52,7 +66,6 @@ table RoomMemberDataInternal {
|
|||
table RoomGroup {
|
||||
groupId:uint8;
|
||||
withPassword:bool;
|
||||
withLabel:bool;
|
||||
label:[uint8];
|
||||
slotNum:uint32;
|
||||
curGroupMemberNum:uint32;
|
||||
|
@ -108,7 +121,7 @@ table PresenceOptionData {
|
|||
}
|
||||
|
||||
table RoomGroupPasswordConfig {
|
||||
groupId:[uint8];
|
||||
groupId:uint8;
|
||||
withPassword:bool;
|
||||
}
|
||||
|
||||
|
@ -161,6 +174,11 @@ table JoinRoomRequest {
|
|||
teamId:uint8;
|
||||
}
|
||||
|
||||
table JoinRoomResponse {
|
||||
room_data: RoomDataInternal;
|
||||
signaling_data: [Matching2SignalingInfo];
|
||||
}
|
||||
|
||||
table LeaveRoomRequest {
|
||||
roomId:uint64;
|
||||
optData:PresenceOptionData;
|
||||
|
@ -221,6 +239,12 @@ table RoomMemberUpdateInfo {
|
|||
optData:PresenceOptionData;
|
||||
}
|
||||
|
||||
table NotificationUserJoinedRoom {
|
||||
room_id:uint64;
|
||||
update_info:RoomMemberUpdateInfo;
|
||||
signaling:SignalingAddr;
|
||||
}
|
||||
|
||||
table RoomUpdateInfo {
|
||||
eventCause:uint8;
|
||||
errorCode:int32;
|
||||
|
|
|
@ -13,6 +13,15 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 24 &&
|
|||
FLATBUFFERS_VERSION_REVISION == 25,
|
||||
"Non-compatible flatbuffers version included");
|
||||
|
||||
struct SignalingAddr;
|
||||
struct SignalingAddrBuilder;
|
||||
|
||||
struct MatchingSignalingInfo;
|
||||
struct MatchingSignalingInfoBuilder;
|
||||
|
||||
struct Matching2SignalingInfo;
|
||||
struct Matching2SignalingInfoBuilder;
|
||||
|
||||
struct BinAttr;
|
||||
struct BinAttrBuilder;
|
||||
|
||||
|
@ -70,6 +79,9 @@ struct CreateJoinRoomRequestBuilder;
|
|||
struct JoinRoomRequest;
|
||||
struct JoinRoomRequestBuilder;
|
||||
|
||||
struct JoinRoomResponse;
|
||||
struct JoinRoomResponseBuilder;
|
||||
|
||||
struct LeaveRoomRequest;
|
||||
struct LeaveRoomRequestBuilder;
|
||||
|
||||
|
@ -100,6 +112,9 @@ struct GetRoomDataInternalRequestBuilder;
|
|||
struct RoomMemberUpdateInfo;
|
||||
struct RoomMemberUpdateInfoBuilder;
|
||||
|
||||
struct NotificationUserJoinedRoom;
|
||||
struct NotificationUserJoinedRoomBuilder;
|
||||
|
||||
struct RoomUpdateInfo;
|
||||
struct RoomUpdateInfoBuilder;
|
||||
|
||||
|
@ -256,6 +271,185 @@ struct SearchJoinRoomGUIRequestBuilder;
|
|||
struct MatchingSearchJoinRoomInfo;
|
||||
struct MatchingSearchJoinRoomInfoBuilder;
|
||||
|
||||
struct SignalingAddr FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef SignalingAddrBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_IP = 4,
|
||||
VT_PORT = 6
|
||||
};
|
||||
const ::flatbuffers::Vector<uint8_t> *ip() const {
|
||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_IP);
|
||||
}
|
||||
uint16_t port() const {
|
||||
return GetField<uint16_t>(VT_PORT, 0);
|
||||
}
|
||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_IP) &&
|
||||
verifier.VerifyVector(ip()) &&
|
||||
VerifyField<uint16_t>(verifier, VT_PORT, 2) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct SignalingAddrBuilder {
|
||||
typedef SignalingAddr Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_ip(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> ip) {
|
||||
fbb_.AddOffset(SignalingAddr::VT_IP, ip);
|
||||
}
|
||||
void add_port(uint16_t port) {
|
||||
fbb_.AddElement<uint16_t>(SignalingAddr::VT_PORT, port, 0);
|
||||
}
|
||||
explicit SignalingAddrBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<SignalingAddr> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<SignalingAddr>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<SignalingAddr> CreateSignalingAddr(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> ip = 0,
|
||||
uint16_t port = 0) {
|
||||
SignalingAddrBuilder builder_(_fbb);
|
||||
builder_.add_ip(ip);
|
||||
builder_.add_port(port);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<SignalingAddr> CreateSignalingAddrDirect(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<uint8_t> *ip = nullptr,
|
||||
uint16_t port = 0) {
|
||||
auto ip__ = ip ? _fbb.CreateVector<uint8_t>(*ip) : 0;
|
||||
return CreateSignalingAddr(
|
||||
_fbb,
|
||||
ip__,
|
||||
port);
|
||||
}
|
||||
|
||||
struct MatchingSignalingInfo FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef MatchingSignalingInfoBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NPID = 4,
|
||||
VT_ADDR = 6
|
||||
};
|
||||
const ::flatbuffers::String *npid() const {
|
||||
return GetPointer<const ::flatbuffers::String *>(VT_NPID);
|
||||
}
|
||||
const SignalingAddr *addr() const {
|
||||
return GetPointer<const SignalingAddr *>(VT_ADDR);
|
||||
}
|
||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_NPID) &&
|
||||
verifier.VerifyString(npid()) &&
|
||||
VerifyOffset(verifier, VT_ADDR) &&
|
||||
verifier.VerifyTable(addr()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct MatchingSignalingInfoBuilder {
|
||||
typedef MatchingSignalingInfo Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_npid(::flatbuffers::Offset<::flatbuffers::String> npid) {
|
||||
fbb_.AddOffset(MatchingSignalingInfo::VT_NPID, npid);
|
||||
}
|
||||
void add_addr(::flatbuffers::Offset<SignalingAddr> addr) {
|
||||
fbb_.AddOffset(MatchingSignalingInfo::VT_ADDR, addr);
|
||||
}
|
||||
explicit MatchingSignalingInfoBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<MatchingSignalingInfo> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<MatchingSignalingInfo>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<MatchingSignalingInfo> CreateMatchingSignalingInfo(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
::flatbuffers::Offset<::flatbuffers::String> npid = 0,
|
||||
::flatbuffers::Offset<SignalingAddr> addr = 0) {
|
||||
MatchingSignalingInfoBuilder builder_(_fbb);
|
||||
builder_.add_addr(addr);
|
||||
builder_.add_npid(npid);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<MatchingSignalingInfo> CreateMatchingSignalingInfoDirect(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *npid = nullptr,
|
||||
::flatbuffers::Offset<SignalingAddr> addr = 0) {
|
||||
auto npid__ = npid ? _fbb.CreateString(npid) : 0;
|
||||
return CreateMatchingSignalingInfo(
|
||||
_fbb,
|
||||
npid__,
|
||||
addr);
|
||||
}
|
||||
|
||||
struct Matching2SignalingInfo FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef Matching2SignalingInfoBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_MEMBER_ID = 4,
|
||||
VT_ADDR = 6
|
||||
};
|
||||
uint16_t member_id() const {
|
||||
return GetField<uint16_t>(VT_MEMBER_ID, 0);
|
||||
}
|
||||
const SignalingAddr *addr() const {
|
||||
return GetPointer<const SignalingAddr *>(VT_ADDR);
|
||||
}
|
||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint16_t>(verifier, VT_MEMBER_ID, 2) &&
|
||||
VerifyOffset(verifier, VT_ADDR) &&
|
||||
verifier.VerifyTable(addr()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct Matching2SignalingInfoBuilder {
|
||||
typedef Matching2SignalingInfo Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_member_id(uint16_t member_id) {
|
||||
fbb_.AddElement<uint16_t>(Matching2SignalingInfo::VT_MEMBER_ID, member_id, 0);
|
||||
}
|
||||
void add_addr(::flatbuffers::Offset<SignalingAddr> addr) {
|
||||
fbb_.AddOffset(Matching2SignalingInfo::VT_ADDR, addr);
|
||||
}
|
||||
explicit Matching2SignalingInfoBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<Matching2SignalingInfo> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<Matching2SignalingInfo>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<Matching2SignalingInfo> CreateMatching2SignalingInfo(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint16_t member_id = 0,
|
||||
::flatbuffers::Offset<SignalingAddr> addr = 0) {
|
||||
Matching2SignalingInfoBuilder builder_(_fbb);
|
||||
builder_.add_addr(addr);
|
||||
builder_.add_member_id(member_id);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct BinAttr FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef BinAttrBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
|
@ -549,16 +743,12 @@ struct GroupConfig FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||
typedef GroupConfigBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_SLOTNUM = 4,
|
||||
VT_WITHLABEL = 6,
|
||||
VT_LABEL = 8,
|
||||
VT_WITHPASSWORD = 10
|
||||
VT_LABEL = 6,
|
||||
VT_WITHPASSWORD = 8
|
||||
};
|
||||
uint32_t slotNum() const {
|
||||
return GetField<uint32_t>(VT_SLOTNUM, 0);
|
||||
}
|
||||
bool withLabel() const {
|
||||
return GetField<uint8_t>(VT_WITHLABEL, 0) != 0;
|
||||
}
|
||||
const ::flatbuffers::Vector<uint8_t> *label() const {
|
||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_LABEL);
|
||||
}
|
||||
|
@ -568,7 +758,6 @@ struct GroupConfig FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint32_t>(verifier, VT_SLOTNUM, 4) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHLABEL, 1) &&
|
||||
VerifyOffset(verifier, VT_LABEL) &&
|
||||
verifier.VerifyVector(label()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHPASSWORD, 1) &&
|
||||
|
@ -583,9 +772,6 @@ struct GroupConfigBuilder {
|
|||
void add_slotNum(uint32_t slotNum) {
|
||||
fbb_.AddElement<uint32_t>(GroupConfig::VT_SLOTNUM, slotNum, 0);
|
||||
}
|
||||
void add_withLabel(bool withLabel) {
|
||||
fbb_.AddElement<uint8_t>(GroupConfig::VT_WITHLABEL, static_cast<uint8_t>(withLabel), 0);
|
||||
}
|
||||
void add_label(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> label) {
|
||||
fbb_.AddOffset(GroupConfig::VT_LABEL, label);
|
||||
}
|
||||
|
@ -606,28 +792,24 @@ struct GroupConfigBuilder {
|
|||
inline ::flatbuffers::Offset<GroupConfig> CreateGroupConfig(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t slotNum = 0,
|
||||
bool withLabel = false,
|
||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> label = 0,
|
||||
bool withPassword = false) {
|
||||
GroupConfigBuilder builder_(_fbb);
|
||||
builder_.add_label(label);
|
||||
builder_.add_slotNum(slotNum);
|
||||
builder_.add_withPassword(withPassword);
|
||||
builder_.add_withLabel(withLabel);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<GroupConfig> CreateGroupConfigDirect(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t slotNum = 0,
|
||||
bool withLabel = false,
|
||||
const std::vector<uint8_t> *label = nullptr,
|
||||
bool withPassword = false) {
|
||||
auto label__ = label ? _fbb.CreateVector<uint8_t>(*label) : 0;
|
||||
return CreateGroupConfig(
|
||||
_fbb,
|
||||
slotNum,
|
||||
withLabel,
|
||||
label__,
|
||||
withPassword);
|
||||
}
|
||||
|
@ -854,10 +1036,9 @@ struct RoomGroup FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_GROUPID = 4,
|
||||
VT_WITHPASSWORD = 6,
|
||||
VT_WITHLABEL = 8,
|
||||
VT_LABEL = 10,
|
||||
VT_SLOTNUM = 12,
|
||||
VT_CURGROUPMEMBERNUM = 14
|
||||
VT_LABEL = 8,
|
||||
VT_SLOTNUM = 10,
|
||||
VT_CURGROUPMEMBERNUM = 12
|
||||
};
|
||||
uint8_t groupId() const {
|
||||
return GetField<uint8_t>(VT_GROUPID, 0);
|
||||
|
@ -865,9 +1046,6 @@ struct RoomGroup FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||
bool withPassword() const {
|
||||
return GetField<uint8_t>(VT_WITHPASSWORD, 0) != 0;
|
||||
}
|
||||
bool withLabel() const {
|
||||
return GetField<uint8_t>(VT_WITHLABEL, 0) != 0;
|
||||
}
|
||||
const ::flatbuffers::Vector<uint8_t> *label() const {
|
||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_LABEL);
|
||||
}
|
||||
|
@ -881,7 +1059,6 @@ struct RoomGroup FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint8_t>(verifier, VT_GROUPID, 1) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHPASSWORD, 1) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHLABEL, 1) &&
|
||||
VerifyOffset(verifier, VT_LABEL) &&
|
||||
verifier.VerifyVector(label()) &&
|
||||
VerifyField<uint32_t>(verifier, VT_SLOTNUM, 4) &&
|
||||
|
@ -900,9 +1077,6 @@ struct RoomGroupBuilder {
|
|||
void add_withPassword(bool withPassword) {
|
||||
fbb_.AddElement<uint8_t>(RoomGroup::VT_WITHPASSWORD, static_cast<uint8_t>(withPassword), 0);
|
||||
}
|
||||
void add_withLabel(bool withLabel) {
|
||||
fbb_.AddElement<uint8_t>(RoomGroup::VT_WITHLABEL, static_cast<uint8_t>(withLabel), 0);
|
||||
}
|
||||
void add_label(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> label) {
|
||||
fbb_.AddOffset(RoomGroup::VT_LABEL, label);
|
||||
}
|
||||
|
@ -927,7 +1101,6 @@ inline ::flatbuffers::Offset<RoomGroup> CreateRoomGroup(
|
|||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint8_t groupId = 0,
|
||||
bool withPassword = false,
|
||||
bool withLabel = false,
|
||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> label = 0,
|
||||
uint32_t slotNum = 0,
|
||||
uint32_t curGroupMemberNum = 0) {
|
||||
|
@ -935,7 +1108,6 @@ inline ::flatbuffers::Offset<RoomGroup> CreateRoomGroup(
|
|||
builder_.add_curGroupMemberNum(curGroupMemberNum);
|
||||
builder_.add_slotNum(slotNum);
|
||||
builder_.add_label(label);
|
||||
builder_.add_withLabel(withLabel);
|
||||
builder_.add_withPassword(withPassword);
|
||||
builder_.add_groupId(groupId);
|
||||
return builder_.Finish();
|
||||
|
@ -945,7 +1117,6 @@ inline ::flatbuffers::Offset<RoomGroup> CreateRoomGroupDirect(
|
|||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint8_t groupId = 0,
|
||||
bool withPassword = false,
|
||||
bool withLabel = false,
|
||||
const std::vector<uint8_t> *label = nullptr,
|
||||
uint32_t slotNum = 0,
|
||||
uint32_t curGroupMemberNum = 0) {
|
||||
|
@ -954,7 +1125,6 @@ inline ::flatbuffers::Offset<RoomGroup> CreateRoomGroupDirect(
|
|||
_fbb,
|
||||
groupId,
|
||||
withPassword,
|
||||
withLabel,
|
||||
label__,
|
||||
slotNum,
|
||||
curGroupMemberNum);
|
||||
|
@ -1565,16 +1735,15 @@ struct RoomGroupPasswordConfig FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::
|
|||
VT_GROUPID = 4,
|
||||
VT_WITHPASSWORD = 6
|
||||
};
|
||||
const ::flatbuffers::Vector<uint8_t> *groupId() const {
|
||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_GROUPID);
|
||||
uint8_t groupId() const {
|
||||
return GetField<uint8_t>(VT_GROUPID, 0);
|
||||
}
|
||||
bool withPassword() const {
|
||||
return GetField<uint8_t>(VT_WITHPASSWORD, 0) != 0;
|
||||
}
|
||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_GROUPID) &&
|
||||
verifier.VerifyVector(groupId()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_GROUPID, 1) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHPASSWORD, 1) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
|
@ -1584,8 +1753,8 @@ struct RoomGroupPasswordConfigBuilder {
|
|||
typedef RoomGroupPasswordConfig Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_groupId(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> groupId) {
|
||||
fbb_.AddOffset(RoomGroupPasswordConfig::VT_GROUPID, groupId);
|
||||
void add_groupId(uint8_t groupId) {
|
||||
fbb_.AddElement<uint8_t>(RoomGroupPasswordConfig::VT_GROUPID, groupId, 0);
|
||||
}
|
||||
void add_withPassword(bool withPassword) {
|
||||
fbb_.AddElement<uint8_t>(RoomGroupPasswordConfig::VT_WITHPASSWORD, static_cast<uint8_t>(withPassword), 0);
|
||||
|
@ -1603,25 +1772,14 @@ struct RoomGroupPasswordConfigBuilder {
|
|||
|
||||
inline ::flatbuffers::Offset<RoomGroupPasswordConfig> CreateRoomGroupPasswordConfig(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> groupId = 0,
|
||||
uint8_t groupId = 0,
|
||||
bool withPassword = false) {
|
||||
RoomGroupPasswordConfigBuilder builder_(_fbb);
|
||||
builder_.add_groupId(groupId);
|
||||
builder_.add_withPassword(withPassword);
|
||||
builder_.add_groupId(groupId);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<RoomGroupPasswordConfig> CreateRoomGroupPasswordConfigDirect(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<uint8_t> *groupId = nullptr,
|
||||
bool withPassword = false) {
|
||||
auto groupId__ = groupId ? _fbb.CreateVector<uint8_t>(*groupId) : 0;
|
||||
return CreateRoomGroupPasswordConfig(
|
||||
_fbb,
|
||||
groupId__,
|
||||
withPassword);
|
||||
}
|
||||
|
||||
struct SearchRoomRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef SearchRoomRequestBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
|
@ -2250,6 +2408,71 @@ inline ::flatbuffers::Offset<JoinRoomRequest> CreateJoinRoomRequestDirect(
|
|||
teamId);
|
||||
}
|
||||
|
||||
struct JoinRoomResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef JoinRoomResponseBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_ROOM_DATA = 4,
|
||||
VT_SIGNALING_DATA = 6
|
||||
};
|
||||
const RoomDataInternal *room_data() const {
|
||||
return GetPointer<const RoomDataInternal *>(VT_ROOM_DATA);
|
||||
}
|
||||
const ::flatbuffers::Vector<::flatbuffers::Offset<Matching2SignalingInfo>> *signaling_data() const {
|
||||
return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<Matching2SignalingInfo>> *>(VT_SIGNALING_DATA);
|
||||
}
|
||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_ROOM_DATA) &&
|
||||
verifier.VerifyTable(room_data()) &&
|
||||
VerifyOffset(verifier, VT_SIGNALING_DATA) &&
|
||||
verifier.VerifyVector(signaling_data()) &&
|
||||
verifier.VerifyVectorOfTables(signaling_data()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct JoinRoomResponseBuilder {
|
||||
typedef JoinRoomResponse Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_room_data(::flatbuffers::Offset<RoomDataInternal> room_data) {
|
||||
fbb_.AddOffset(JoinRoomResponse::VT_ROOM_DATA, room_data);
|
||||
}
|
||||
void add_signaling_data(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<Matching2SignalingInfo>>> signaling_data) {
|
||||
fbb_.AddOffset(JoinRoomResponse::VT_SIGNALING_DATA, signaling_data);
|
||||
}
|
||||
explicit JoinRoomResponseBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<JoinRoomResponse> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<JoinRoomResponse>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<JoinRoomResponse> CreateJoinRoomResponse(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
::flatbuffers::Offset<RoomDataInternal> room_data = 0,
|
||||
::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<Matching2SignalingInfo>>> signaling_data = 0) {
|
||||
JoinRoomResponseBuilder builder_(_fbb);
|
||||
builder_.add_signaling_data(signaling_data);
|
||||
builder_.add_room_data(room_data);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<JoinRoomResponse> CreateJoinRoomResponseDirect(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
::flatbuffers::Offset<RoomDataInternal> room_data = 0,
|
||||
const std::vector<::flatbuffers::Offset<Matching2SignalingInfo>> *signaling_data = nullptr) {
|
||||
auto signaling_data__ = signaling_data ? _fbb.CreateVector<::flatbuffers::Offset<Matching2SignalingInfo>>(*signaling_data) : 0;
|
||||
return CreateJoinRoomResponse(
|
||||
_fbb,
|
||||
room_data,
|
||||
signaling_data__);
|
||||
}
|
||||
|
||||
struct LeaveRoomRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef LeaveRoomRequestBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
|
@ -2995,6 +3218,69 @@ inline ::flatbuffers::Offset<RoomMemberUpdateInfo> CreateRoomMemberUpdateInfo(
|
|||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct NotificationUserJoinedRoom FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef NotificationUserJoinedRoomBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_ROOM_ID = 4,
|
||||
VT_UPDATE_INFO = 6,
|
||||
VT_SIGNALING = 8
|
||||
};
|
||||
uint64_t room_id() const {
|
||||
return GetField<uint64_t>(VT_ROOM_ID, 0);
|
||||
}
|
||||
const RoomMemberUpdateInfo *update_info() const {
|
||||
return GetPointer<const RoomMemberUpdateInfo *>(VT_UPDATE_INFO);
|
||||
}
|
||||
const SignalingAddr *signaling() const {
|
||||
return GetPointer<const SignalingAddr *>(VT_SIGNALING);
|
||||
}
|
||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint64_t>(verifier, VT_ROOM_ID, 8) &&
|
||||
VerifyOffset(verifier, VT_UPDATE_INFO) &&
|
||||
verifier.VerifyTable(update_info()) &&
|
||||
VerifyOffset(verifier, VT_SIGNALING) &&
|
||||
verifier.VerifyTable(signaling()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct NotificationUserJoinedRoomBuilder {
|
||||
typedef NotificationUserJoinedRoom Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_room_id(uint64_t room_id) {
|
||||
fbb_.AddElement<uint64_t>(NotificationUserJoinedRoom::VT_ROOM_ID, room_id, 0);
|
||||
}
|
||||
void add_update_info(::flatbuffers::Offset<RoomMemberUpdateInfo> update_info) {
|
||||
fbb_.AddOffset(NotificationUserJoinedRoom::VT_UPDATE_INFO, update_info);
|
||||
}
|
||||
void add_signaling(::flatbuffers::Offset<SignalingAddr> signaling) {
|
||||
fbb_.AddOffset(NotificationUserJoinedRoom::VT_SIGNALING, signaling);
|
||||
}
|
||||
explicit NotificationUserJoinedRoomBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<NotificationUserJoinedRoom> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<NotificationUserJoinedRoom>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<NotificationUserJoinedRoom> CreateNotificationUserJoinedRoom(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint64_t room_id = 0,
|
||||
::flatbuffers::Offset<RoomMemberUpdateInfo> update_info = 0,
|
||||
::flatbuffers::Offset<SignalingAddr> signaling = 0) {
|
||||
NotificationUserJoinedRoomBuilder builder_(_fbb);
|
||||
builder_.add_room_id(room_id);
|
||||
builder_.add_signaling(signaling);
|
||||
builder_.add_update_info(update_info);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct RoomUpdateInfo FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef RoomUpdateInfoBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
|
|
249
rpcs3/Emu/NP/ip_address.cpp
Normal file
249
rpcs3/Emu/NP/ip_address.cpp
Normal file
|
@ -0,0 +1,249 @@
|
|||
#include "stdafx.h"
|
||||
#include "ip_address.h"
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "util/endian.hpp"
|
||||
#include "util/types.hpp"
|
||||
#include "Emu/NP/rpcn_config.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
LOG_CHANNEL(IPv6_log, "IPv6_layer");
|
||||
|
||||
namespace np
|
||||
{
|
||||
bool ip_address_translator::is_ipv6(u32 addr_be)
|
||||
{
|
||||
const u32 addr = std::bit_cast<u32, be_t<u32>>(addr_be);
|
||||
return (addr >= translation_range_begin && addr <= translation_range_end);
|
||||
}
|
||||
|
||||
u32 ip_address_translator::register_ipv6(const std::array<u8, 16>& ipv6_addr)
|
||||
{
|
||||
if (ipv6_addr[10] == 0xFF && ipv6_addr[11] == 0xFF &&
|
||||
std::all_of(ipv6_addr.begin(), ipv6_addr.begin() + 10, [](u8 val)
|
||||
{
|
||||
return val == 0;
|
||||
}))
|
||||
{
|
||||
// IPv4 over IPv6
|
||||
u32 ip_addr{};
|
||||
std::memcpy(&ip_addr, &ipv6_addr[12], sizeof(u32));
|
||||
return ip_addr;
|
||||
}
|
||||
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
const auto it = ipv6_to_ipv4.find(ipv6_addr);
|
||||
|
||||
if (it == ipv6_to_ipv4.end())
|
||||
{
|
||||
ensure(cur_addr != translation_range_end);
|
||||
const u32 translation_ip = cur_addr++;
|
||||
const u32 translation_ip_be = std::bit_cast<u32, be_t<u32>>(translation_ip);
|
||||
ipv6_to_ipv4.emplace(ipv6_addr, translation_ip_be);
|
||||
ipv4_to_ipv6.push_back(ipv6_addr);
|
||||
return translation_ip_be;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
sockaddr_in6 ip_address_translator::get_ipv6_sockaddr(u32 addr_be, u16 port_be)
|
||||
{
|
||||
const u32 addr_native = std::bit_cast<u32, be_t<u32>>(addr_be);
|
||||
const auto ipv6_addr = ::at32(ipv4_to_ipv6, addr_native - translation_range_begin);
|
||||
|
||||
sockaddr_in6 sockaddr_ipv6{.sin6_family = AF_INET6, .sin6_port = port_be};
|
||||
std::memcpy(&sockaddr_ipv6.sin6_addr, ipv6_addr.data(), ipv6_addr.size());
|
||||
|
||||
return sockaddr_ipv6;
|
||||
}
|
||||
|
||||
u32 register_ip(const flatbuffers::Vector<std::uint8_t>* vec)
|
||||
{
|
||||
if (vec->size() == 4)
|
||||
{
|
||||
const u32 ip = static_cast<u32>(vec->Get(0)) << 24 | static_cast<u32>(vec->Get(1)) << 16 |
|
||||
static_cast<u32>(vec->Get(2)) << 8 | static_cast<u32>(vec->Get(3));
|
||||
|
||||
u32 result_ip = std::bit_cast<u32, be_t<u32>>(ip);
|
||||
|
||||
return result_ip;
|
||||
}
|
||||
else if (vec->size() == 16)
|
||||
{
|
||||
std::array<u8, 16> ipv6_addr{};
|
||||
std::memcpy(ipv6_addr.data(), vec->Data(), 16);
|
||||
|
||||
auto& translator = g_fxo->get<np::ip_address_translator>();
|
||||
return translator.register_ipv6(ipv6_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Received ip address with size = %d", vec->size());
|
||||
}
|
||||
}
|
||||
|
||||
bool is_ipv6_supported(std::optional<IPV6_SUPPORT> force_state)
|
||||
{
|
||||
static atomic_t<IPV6_SUPPORT> ipv6_status = IPV6_SUPPORT::IPV6_UNKNOWN;
|
||||
|
||||
if (force_state)
|
||||
ipv6_status = *force_state;
|
||||
|
||||
if (ipv6_status != IPV6_SUPPORT::IPV6_UNKNOWN)
|
||||
return ipv6_status == IPV6_SUPPORT::IPV6_SUPPORTED;
|
||||
|
||||
static shared_mutex mtx;
|
||||
std::lock_guard lock(mtx);
|
||||
|
||||
if (ipv6_status != IPV6_SUPPORT::IPV6_UNKNOWN)
|
||||
return ipv6_status == IPV6_SUPPORT::IPV6_SUPPORTED;
|
||||
|
||||
// IPv6 feature is only used by RPCN
|
||||
if (!g_cfg_rpcn.get_ipv6_support())
|
||||
{
|
||||
IPv6_log.notice("is_ipv6_supported(): disabled through config");
|
||||
ipv6_status = IPV6_SUPPORT::IPV6_UNSUPPORTED;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We try to connect to ipv6.google.com:8080
|
||||
addrinfo* addr_info{};
|
||||
socket_type socket_ipv6{};
|
||||
|
||||
auto cleanup = [&]()
|
||||
{
|
||||
if (socket_ipv6)
|
||||
close_socket(socket_ipv6);
|
||||
|
||||
if (addr_info)
|
||||
freeaddrinfo(addr_info);
|
||||
};
|
||||
|
||||
auto error_and_disable = [&](const char* message) -> bool
|
||||
{
|
||||
IPv6_log.error("is_ipv6_supported(): %s", message);
|
||||
ipv6_status = IPV6_SUPPORT::IPV6_UNSUPPORTED;
|
||||
cleanup();
|
||||
return false;
|
||||
};
|
||||
|
||||
addrinfo hints{.ai_family = AF_INET6};
|
||||
|
||||
if (getaddrinfo("ipv6.google.com", nullptr, &hints, &addr_info))
|
||||
return error_and_disable("Failed to resolve ipv6.google.com!");
|
||||
|
||||
addrinfo* found = addr_info;
|
||||
|
||||
while (found != nullptr)
|
||||
{
|
||||
if (found->ai_family == AF_INET6)
|
||||
break;
|
||||
|
||||
found = found->ai_next;
|
||||
}
|
||||
|
||||
if (found == nullptr)
|
||||
return error_and_disable("Failed to find IPv6 for ipv6.google.com");
|
||||
|
||||
socket_type socket_or_err = ::socket(AF_INET6, SOCK_STREAM, 0);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (socket_or_err == INVALID_SOCKET)
|
||||
#else
|
||||
if (socket_or_err == -1)
|
||||
#endif
|
||||
return error_and_disable("Failed to create IPv6 socket!");
|
||||
|
||||
socket_ipv6 = socket_or_err;
|
||||
sockaddr_in6 ipv6_addr = *reinterpret_cast<const sockaddr_in6*>(found->ai_addr);
|
||||
ipv6_addr.sin6_port = std::bit_cast<u16, be_t<u16>>(443);
|
||||
|
||||
if (::connect(socket_ipv6, reinterpret_cast<const sockaddr*>(&ipv6_addr), sizeof(ipv6_addr)) != 0)
|
||||
return error_and_disable("Failed to connect to ipv6.google.com");
|
||||
|
||||
cleanup();
|
||||
|
||||
IPv6_log.success("Successfully tested IPv6 support!");
|
||||
ipv6_status = IPV6_SUPPORT::IPV6_SUPPORTED;
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 sendto_possibly_ipv6(socket_type native_socket, const char* data, u32 size, const sockaddr_in* addr, int native_flags)
|
||||
{
|
||||
if (is_ipv6_supported())
|
||||
{
|
||||
sockaddr_in6 addr_ipv6{};
|
||||
|
||||
if (np::ip_address_translator::is_ipv6(addr->sin_addr.s_addr))
|
||||
{
|
||||
auto& translator = g_fxo->get<np::ip_address_translator>();
|
||||
addr_ipv6 = translator.get_ipv6_sockaddr(addr->sin_addr.s_addr, addr->sin_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr_ipv6 = sockaddr_to_sockaddr6(*addr);
|
||||
}
|
||||
|
||||
return ::sendto(native_socket, data, size, native_flags, reinterpret_cast<const sockaddr*>(&addr_ipv6), sizeof(sockaddr_in6));
|
||||
}
|
||||
|
||||
return ::sendto(native_socket, data, size, native_flags, reinterpret_cast<const sockaddr*>(addr), sizeof(sockaddr_in));
|
||||
}
|
||||
|
||||
sockaddr_in6 sockaddr_to_sockaddr6(const sockaddr_in& addr)
|
||||
{
|
||||
sockaddr_in6 addr_ipv6{.sin6_family = AF_INET6, .sin6_port = addr.sin_port};
|
||||
std::array<u8, 16> ipv6{};
|
||||
|
||||
// IPv4 over IPv6
|
||||
ipv6[10] = 0xFF;
|
||||
ipv6[11] = 0xFF;
|
||||
std::memcpy(ipv6.data() + 12, &addr.sin_addr.s_addr, 4);
|
||||
std::memcpy(&addr_ipv6.sin6_addr, ipv6.data(), ipv6.size());
|
||||
return addr_ipv6;
|
||||
}
|
||||
|
||||
sockaddr_in sockaddr6_to_sockaddr(const sockaddr_in6& addr)
|
||||
{
|
||||
sockaddr_in addr_ipv4{.sin_family = AF_INET, .sin_port = addr.sin6_port};
|
||||
|
||||
std::array<u8, 16> ipv6{};
|
||||
std::memcpy(ipv6.data(), &addr.sin6_addr, 16);
|
||||
auto& translator = g_fxo->get<np::ip_address_translator>();
|
||||
addr_ipv4.sin_addr.s_addr = translator.register_ipv6(ipv6);
|
||||
|
||||
return addr_ipv4;
|
||||
}
|
||||
|
||||
void close_socket(socket_type socket)
|
||||
{
|
||||
if (socket)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::closesocket(socket);
|
||||
#else
|
||||
::close(socket);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void set_socket_non_blocking(socket_type socket)
|
||||
{
|
||||
if (socket)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
u_long _true = 1;
|
||||
::ioctlsocket(socket, FIONBIO, &_true);
|
||||
#else
|
||||
::fcntl(socket, F_SETFL, ::fcntl(socket, F_GETFL, 0) | O_NONBLOCK);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace np
|
86
rpcs3/Emu/NP/ip_address.h
Normal file
86
rpcs3/Emu/NP/ip_address.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <flatbuffers/vector.h>
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "Utilities/mutex.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#ifdef __clang__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#ifdef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
using socket_type = uptr;
|
||||
#else
|
||||
using socket_type = int;
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct std::hash<std::array<u8, 16>>
|
||||
{
|
||||
std::size_t operator()(const std::array<u8, 16>& array) const noexcept
|
||||
{
|
||||
std::size_t hash = 0;
|
||||
std::hash<std::uint8_t> hasher;
|
||||
|
||||
for (auto byte : array)
|
||||
{
|
||||
hash ^= hasher(byte) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
namespace np
|
||||
{
|
||||
class ip_address_translator
|
||||
{
|
||||
public:
|
||||
static bool is_ipv6(u32 addr_be);
|
||||
|
||||
u32 register_ipv6(const std::array<u8, 16>& ipv6_addr);
|
||||
sockaddr_in6 get_ipv6_sockaddr(u32 addr_be, u16 port_be);
|
||||
|
||||
private:
|
||||
static constexpr u32 translation_range_begin = 0x00'00'00'01;
|
||||
static constexpr u32 translation_range_end = 0x00'00'FF'FF;
|
||||
|
||||
shared_mutex mutex;
|
||||
u32 cur_addr = translation_range_begin;
|
||||
std::unordered_map<std::array<u8, 16>, u32> ipv6_to_ipv4;
|
||||
std::vector<std::array<u8, 16>> ipv4_to_ipv6;
|
||||
};
|
||||
|
||||
u32 register_ip(const flatbuffers::Vector<std::uint8_t>* vec);
|
||||
|
||||
enum class IPV6_SUPPORT : u8
|
||||
{
|
||||
IPV6_UNKNOWN,
|
||||
IPV6_UNSUPPORTED,
|
||||
IPV6_SUPPORTED,
|
||||
};
|
||||
|
||||
bool is_ipv6_supported(std::optional<IPV6_SUPPORT> force_state = std::nullopt);
|
||||
s32 sendto_possibly_ipv6(socket_type native_socket, const char* data, u32 size, const sockaddr_in* addr, int native_flags);
|
||||
sockaddr_in6 sockaddr_to_sockaddr6(const sockaddr_in& addr);
|
||||
sockaddr_in sockaddr6_to_sockaddr(const sockaddr_in6& addr);
|
||||
|
||||
void close_socket(socket_type socket);
|
||||
void set_socket_non_blocking(socket_type socket);
|
||||
} // namespace np
|
|
@ -45,11 +45,10 @@ error_code generic_async_transaction_context::wait_for_completion()
|
|||
return *result;
|
||||
}
|
||||
|
||||
bool generic_async_transaction_context::set_result_and_wake(error_code err)
|
||||
void generic_async_transaction_context::set_result_and_wake(error_code err)
|
||||
{
|
||||
result = err;
|
||||
wake_cond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
tus_ctx::tus_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
||||
|
|
|
@ -23,7 +23,7 @@ struct generic_async_transaction_context
|
|||
std::optional<s32> get_transaction_status();
|
||||
void abort_transaction();
|
||||
error_code wait_for_completion();
|
||||
bool set_result_and_wake(error_code err);
|
||||
void set_result_and_wake(error_code err);
|
||||
|
||||
shared_mutex mutex;
|
||||
std::condition_variable_any wake_cond, completion_cond;
|
||||
|
|
|
@ -788,7 +788,14 @@ namespace np
|
|||
break;
|
||||
|
||||
std::lock_guard lock(mutex_rpcn);
|
||||
rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
bool was_already_started = true;
|
||||
|
||||
if (!rpcn)
|
||||
{
|
||||
rpcn = rpcn::rpcn_client::get_instance();
|
||||
was_already_started = false;
|
||||
}
|
||||
|
||||
// Make sure we're connected
|
||||
|
||||
|
@ -808,7 +815,8 @@ namespace np
|
|||
return;
|
||||
}
|
||||
|
||||
rsx::overlays::queue_message(localized_string_id::RPCN_SUCCESS_LOGGED_ON);
|
||||
if (!was_already_started)
|
||||
rsx::overlays::queue_message(localized_string_id::RPCN_SUCCESS_LOGGED_ON);
|
||||
|
||||
string_to_online_name(rpcn->get_online_name(), online_name);
|
||||
string_to_avatar_url(rpcn->get_avatar_url(), avatar_url);
|
||||
|
@ -836,11 +844,20 @@ namespace np
|
|||
{
|
||||
np_memory.release();
|
||||
|
||||
manager_cb = {};
|
||||
manager_cb_arg = {};
|
||||
basic_handler_registered = false;
|
||||
room_event_cb = {};
|
||||
room_event_cb_ctx = 0;
|
||||
room_event_cb_arg = {};
|
||||
room_msg_cb = {};
|
||||
room_msg_cb_ctx = 0;
|
||||
room_msg_cb_arg = {};
|
||||
|
||||
if (g_cfg.net.psn_status == np_psn_status::psn_rpcn)
|
||||
{
|
||||
rpcn_log.notice("Disconnecting from RPCN!");
|
||||
std::lock_guard lock(mutex_rpcn);
|
||||
rpcn.reset();
|
||||
rpcn_log.notice("Setting RPCN state to disconnected!");
|
||||
rpcn->reset_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -854,10 +871,13 @@ namespace np
|
|||
auto& data = ::at32(match2_req_results, event_key);
|
||||
data.apply_relocations(dest_addr);
|
||||
|
||||
vm::ptr<void> dest = vm::cast(dest_addr);
|
||||
const u32 size_copied = std::min(size, data.size());
|
||||
|
||||
u32 size_copied = std::min(size, data.size());
|
||||
memcpy(dest.get_ptr(), data.data(), size_copied);
|
||||
if (dest_addr && size_copied)
|
||||
{
|
||||
vm::ptr<void> dest = vm::cast(dest_addr);
|
||||
memcpy(dest.get_ptr(), data.data(), size_copied);
|
||||
}
|
||||
|
||||
np_memory.free(data.addr());
|
||||
match2_req_results.erase(event_key);
|
||||
|
@ -1073,61 +1093,63 @@ namespace np
|
|||
auto replies = rpcn->get_replies();
|
||||
for (auto& reply : replies)
|
||||
{
|
||||
const u16 command = reply.second.first;
|
||||
const rpcn::CommandType command = static_cast<rpcn::CommandType>(reply.second.first);
|
||||
const u32 req_id = reply.first;
|
||||
std::vector<u8>& data = reply.second.second;
|
||||
|
||||
// Every reply should at least contain a return value/error code
|
||||
ensure(data.size() >= 1);
|
||||
const auto error = static_cast<rpcn::ErrorType>(data[0]);
|
||||
vec_stream reply_data(data, 1);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case rpcn::CommandType::GetWorldList: reply_get_world_list(req_id, data); break;
|
||||
case rpcn::CommandType::CreateRoom: reply_create_join_room(req_id, data); break;
|
||||
case rpcn::CommandType::JoinRoom: reply_join_room(req_id, data); break;
|
||||
case rpcn::CommandType::LeaveRoom: reply_leave_room(req_id, data); break;
|
||||
case rpcn::CommandType::SearchRoom: reply_search_room(req_id, data); break;
|
||||
case rpcn::CommandType::GetRoomDataExternalList: reply_get_roomdata_external_list(req_id, data); break;
|
||||
case rpcn::CommandType::SetRoomDataExternal: reply_set_roomdata_external(req_id, data); break;
|
||||
case rpcn::CommandType::GetRoomDataInternal: reply_get_roomdata_internal(req_id, data); break;
|
||||
case rpcn::CommandType::SetRoomDataInternal: reply_set_roomdata_internal(req_id, data); break;
|
||||
case rpcn::CommandType::GetRoomMemberDataInternal: reply_get_roommemberdata_internal(req_id, data); break;
|
||||
case rpcn::CommandType::SetRoomMemberDataInternal: reply_set_roommemberdata_internal(req_id, data); break;
|
||||
case rpcn::CommandType::SetUserInfo: reply_set_userinfo(req_id, data); break;
|
||||
case rpcn::CommandType::PingRoomOwner: reply_get_ping_info(req_id, data); break;
|
||||
case rpcn::CommandType::SendRoomMessage: reply_send_room_message(req_id, data); break;
|
||||
case rpcn::CommandType::RequestSignalingInfos: reply_req_sign_infos(req_id, data); break;
|
||||
case rpcn::CommandType::RequestTicket: reply_req_ticket(req_id, data); break;
|
||||
case rpcn::CommandType::GetBoardInfos: reply_get_board_infos(req_id, data); break;
|
||||
case rpcn::CommandType::RecordScore: reply_record_score(req_id, data); break;
|
||||
case rpcn::CommandType::RecordScoreData: reply_record_score_data(req_id, data); break;
|
||||
case rpcn::CommandType::GetScoreData: reply_get_score_data(req_id, data); break;
|
||||
case rpcn::CommandType::GetScoreRange: reply_get_score_range(req_id, data); break;
|
||||
case rpcn::CommandType::GetScoreFriends: reply_get_score_friends(req_id, data); break;
|
||||
case rpcn::CommandType::GetScoreNpid: reply_get_score_npid(req_id, data); break;
|
||||
case rpcn::CommandType::TusSetMultiSlotVariable: reply_tus_set_multislot_variable(req_id, data); break;
|
||||
case rpcn::CommandType::TusGetMultiSlotVariable: reply_tus_get_multislot_variable(req_id, data); break;
|
||||
case rpcn::CommandType::TusGetMultiUserVariable: reply_tus_get_multiuser_variable(req_id, data); break;
|
||||
case rpcn::CommandType::TusGetFriendsVariable: reply_tus_get_friends_variable(req_id, data); break;
|
||||
case rpcn::CommandType::TusAddAndGetVariable: reply_tus_add_and_get_variable(req_id, data); break;
|
||||
case rpcn::CommandType::TusTryAndSetVariable: reply_tus_try_and_set_variable(req_id, data); break;
|
||||
case rpcn::CommandType::TusDeleteMultiSlotVariable: reply_tus_delete_multislot_variable(req_id, data); break;
|
||||
case rpcn::CommandType::TusSetData: reply_tus_set_data(req_id, data); break;
|
||||
case rpcn::CommandType::TusGetData: reply_tus_get_data(req_id, data); break;
|
||||
case rpcn::CommandType::TusGetMultiSlotDataStatus: reply_tus_get_multislot_data_status(req_id, data); break;
|
||||
case rpcn::CommandType::TusGetMultiUserDataStatus: reply_tus_get_multiuser_data_status(req_id, data); break;
|
||||
case rpcn::CommandType::TusGetFriendsDataStatus: reply_tus_get_friends_data_status(req_id, data); break;
|
||||
case rpcn::CommandType::TusDeleteMultiSlotData: reply_tus_delete_multislot_data(req_id, data); break;
|
||||
case rpcn::CommandType::CreateRoomGUI: reply_create_room_gui(req_id, data); break;
|
||||
case rpcn::CommandType::JoinRoomGUI: reply_join_room_gui(req_id, data); break;
|
||||
case rpcn::CommandType::LeaveRoomGUI: reply_leave_room_gui(req_id, data); break;
|
||||
case rpcn::CommandType::GetRoomListGUI: reply_get_room_list_gui(req_id, data); break;
|
||||
case rpcn::CommandType::SetRoomSearchFlagGUI: reply_set_room_search_flag_gui(req_id, data); break;
|
||||
case rpcn::CommandType::GetRoomSearchFlagGUI: reply_get_room_search_flag_gui(req_id, data); break;
|
||||
case rpcn::CommandType::SetRoomInfoGUI: reply_set_room_info_gui(req_id, data); break;
|
||||
case rpcn::CommandType::GetRoomInfoGUI: reply_get_room_info_gui(req_id, data); break;
|
||||
case rpcn::CommandType::QuickMatchGUI: reply_quickmatch_gui(req_id, data); break;
|
||||
case rpcn::CommandType::SearchJoinRoomGUI: reply_searchjoin_gui(req_id, data); break;
|
||||
case rpcn::CommandType::GetWorldList: reply_get_world_list(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::CreateRoom: reply_create_join_room(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::JoinRoom: reply_join_room(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::LeaveRoom: reply_leave_room(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::SearchRoom: reply_search_room(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::GetRoomDataExternalList: reply_get_roomdata_external_list(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::SetRoomDataExternal: reply_set_roomdata_external(req_id, error); break;
|
||||
case rpcn::CommandType::GetRoomDataInternal: reply_get_roomdata_internal(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::SetRoomDataInternal: reply_set_roomdata_internal(req_id, error); break;
|
||||
case rpcn::CommandType::GetRoomMemberDataInternal: reply_get_roommemberdata_internal(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::SetRoomMemberDataInternal: reply_set_roommemberdata_internal(req_id, error); break;
|
||||
case rpcn::CommandType::SetUserInfo: reply_set_userinfo(req_id, error); break;
|
||||
case rpcn::CommandType::PingRoomOwner: reply_get_ping_info(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::SendRoomMessage: reply_send_room_message(req_id, error); break;
|
||||
case rpcn::CommandType::RequestSignalingInfos: reply_req_sign_infos(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::RequestTicket: reply_req_ticket(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::GetBoardInfos: reply_get_board_infos(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::RecordScore: reply_record_score(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::RecordScoreData: reply_record_score_data(req_id, error); break;
|
||||
case rpcn::CommandType::GetScoreData: reply_get_score_data(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::GetScoreRange: reply_get_score_range(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::GetScoreFriends: reply_get_score_friends(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::GetScoreNpid: reply_get_score_npid(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusSetMultiSlotVariable: reply_tus_set_multislot_variable(req_id, error); break;
|
||||
case rpcn::CommandType::TusGetMultiSlotVariable: reply_tus_get_multislot_variable(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusGetMultiUserVariable: reply_tus_get_multiuser_variable(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusGetFriendsVariable: reply_tus_get_friends_variable(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusAddAndGetVariable: reply_tus_add_and_get_variable(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusTryAndSetVariable: reply_tus_try_and_set_variable(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusDeleteMultiSlotVariable: reply_tus_delete_multislot_variable(req_id, error); break;
|
||||
case rpcn::CommandType::TusSetData: reply_tus_set_data(req_id, error); break;
|
||||
case rpcn::CommandType::TusGetData: reply_tus_get_data(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusGetMultiSlotDataStatus: reply_tus_get_multislot_data_status(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusGetMultiUserDataStatus: reply_tus_get_multiuser_data_status(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusGetFriendsDataStatus: reply_tus_get_friends_data_status(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::TusDeleteMultiSlotData: reply_tus_delete_multislot_data(req_id, error); break;
|
||||
case rpcn::CommandType::CreateRoomGUI: reply_create_room_gui(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::JoinRoomGUI: reply_join_room_gui(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::LeaveRoomGUI: reply_leave_room_gui(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::GetRoomListGUI: reply_get_room_list_gui(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::SetRoomSearchFlagGUI: reply_set_room_search_flag_gui(req_id, error); break;
|
||||
case rpcn::CommandType::GetRoomSearchFlagGUI: reply_get_room_search_flag_gui(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::SetRoomInfoGUI: reply_set_room_info_gui(req_id, error); break;
|
||||
case rpcn::CommandType::GetRoomInfoGUI: reply_get_room_info_gui(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::QuickMatchGUI: reply_quickmatch_gui(req_id, error, reply_data); break;
|
||||
case rpcn::CommandType::SearchJoinRoomGUI: reply_searchjoin_gui(req_id, error, reply_data); break;
|
||||
default: fmt::throw_exception("Unknown reply(%d) received!", command); break;
|
||||
}
|
||||
}
|
||||
|
@ -1142,9 +1164,8 @@ namespace np
|
|||
case rpcn::NotificationType::RoomDestroyed: notif_room_destroyed(notif.second); break;
|
||||
case rpcn::NotificationType::UpdatedRoomDataInternal: notif_updated_room_data_internal(notif.second); break;
|
||||
case rpcn::NotificationType::UpdatedRoomMemberDataInternal: notif_updated_room_member_data_internal(notif.second); break;
|
||||
case rpcn::NotificationType::SignalP2PConnect: notif_p2p_connect(notif.second); break;
|
||||
case rpcn::NotificationType::RoomMessageReceived: notif_room_message_received(notif.second); break;
|
||||
case rpcn::NotificationType::SignalingInfo: notif_signaling_info(notif.second); break;
|
||||
case rpcn::NotificationType::SignalingHelper: notif_signaling_helper(notif.second); break;
|
||||
case rpcn::NotificationType::MemberJoinedRoomGUI: notif_member_joined_room_gui(notif.second); break;
|
||||
case rpcn::NotificationType::MemberLeftRoomGUI: notif_member_left_room_gui(notif.second); break;
|
||||
case rpcn::NotificationType::RoomDisappearedGUI: notif_room_disappeared_gui(notif.second); break;
|
||||
|
|
|
@ -298,8 +298,7 @@ namespace np
|
|||
void notif_room_destroyed(std::vector<u8>& data);
|
||||
void notif_updated_room_data_internal(std::vector<u8>& data);
|
||||
void notif_updated_room_member_data_internal(std::vector<u8>& data);
|
||||
void notif_p2p_connect(std::vector<u8>& data);
|
||||
void notif_signaling_info(std::vector<u8>& data);
|
||||
void notif_signaling_helper(std::vector<u8>& data);
|
||||
void notif_room_message_received(std::vector<u8>& data);
|
||||
|
||||
void generic_gui_notification_handler(std::vector<u8>& data, std::string_view name, s32 notification_type);
|
||||
|
@ -312,60 +311,60 @@ namespace np
|
|||
void notif_quickmatch_complete_gui(std::vector<u8>& data);
|
||||
|
||||
// Reply handlers
|
||||
bool reply_get_world_list(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_create_join_room(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_join_room(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_leave_room(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_search_room(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_roomdata_external_list(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_set_roomdata_external(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_set_roomdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_set_roommemberdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_roommemberdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_set_userinfo(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_ping_info(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_send_room_message(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_req_sign_infos(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_req_ticket(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_board_infos(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_record_score(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_record_score_data(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_score_data(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_score_range(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_score_friends(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_score_npid(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_set_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_get_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_get_multiuser_variable(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_get_friends_variable(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_add_and_get_variable(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_try_and_set_variable(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_delete_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_set_data(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_get_data(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_get_multislot_data_status(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_get_multiuser_data_status(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_get_friends_data_status(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_tus_delete_multislot_data(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_create_room_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_join_room_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_leave_room_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_room_list_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_set_room_search_flag_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_room_search_flag_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_set_room_info_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_room_info_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_quickmatch_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_searchjoin_gui(u32 req_id, std::vector<u8>& reply_data);
|
||||
void reply_get_world_list(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_create_join_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_join_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_leave_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_search_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_get_roomdata_external_list(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_set_roomdata_external(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_get_roomdata_internal(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_set_roomdata_internal(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_set_roommemberdata_internal(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_get_roommemberdata_internal(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_set_userinfo(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_get_ping_info(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_send_room_message(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_req_sign_infos(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_req_ticket(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_get_board_infos(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_record_score(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_record_score_data(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_get_score_data(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_get_score_range(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_get_score_friends(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_get_score_npid(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_set_multislot_variable(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_tus_get_multislot_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_get_multiuser_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_get_friends_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_add_and_get_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_try_and_set_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_delete_multislot_variable(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_tus_set_data(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_tus_get_data(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_get_multislot_data_status(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_get_multiuser_data_status(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_get_friends_data_status(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_tus_delete_multislot_data(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_create_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_join_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_leave_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_get_room_list_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_set_room_search_flag_gui(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_get_room_search_flag_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_set_room_info_gui(u32 req_id, rpcn::ErrorType error);
|
||||
void reply_get_room_info_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_quickmatch_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void reply_searchjoin_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
|
||||
// Helper functions
|
||||
std::pair<bool, bool> get_match2_context_options(u32 ctx_id);
|
||||
bool handle_GetScoreResponse(u32 req_id, std::vector<u8>& reply_data, bool simple_result = false);
|
||||
bool handle_tus_no_data(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool handle_TusVarResponse(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool handle_TusVariable(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool handle_TusDataStatusResponse(u32 req_id, std::vector<u8>& reply_data);
|
||||
void handle_GetScoreResponse(u32 req_id, rpcn::ErrorType error, vec_stream& reply, bool simple_result = false);
|
||||
void handle_tus_no_data(u32 req_id, rpcn::ErrorType error);
|
||||
void handle_TusVarResponse(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void handle_TusVariable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
void handle_TusDataStatusResponse(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
|
||||
struct callback_info
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Emu/NP/np_structs_extra.h"
|
||||
#include "Emu/NP/fb_helpers.h"
|
||||
#include "Emu/NP/signaling_handler.h"
|
||||
#include "Emu/NP/ip_address.h"
|
||||
|
||||
LOG_CHANNEL(rpcn_log, "rpcn");
|
||||
|
||||
|
@ -15,8 +16,7 @@ namespace np
|
|||
void np_handler::notif_user_joined_room(std::vector<u8>& data)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
u64 room_id = noti.get<u64>();
|
||||
const auto* update_info = noti.get_flatbuffer<RoomMemberUpdateInfo>();
|
||||
const auto* notification = noti.get_flatbuffer<NotificationUserJoinedRoom>();
|
||||
|
||||
if (noti.is_error())
|
||||
{
|
||||
|
@ -24,20 +24,44 @@ namespace np
|
|||
return;
|
||||
}
|
||||
|
||||
ensure(notification->update_info());
|
||||
|
||||
const u32 event_key = get_event_key();
|
||||
auto [include_onlinename, include_avatarurl] = get_match2_context_options(room_event_cb_ctx);
|
||||
const auto [include_onlinename, include_avatarurl] = get_match2_context_options(room_event_cb_ctx);
|
||||
const auto room_id = notification->room_id();
|
||||
|
||||
auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_RoomMemberUpdateInfo, sizeof(SceNpMatching2RoomMemberUpdateInfo));
|
||||
auto* notif_data = reinterpret_cast<SceNpMatching2RoomMemberUpdateInfo*>(edata.data());
|
||||
RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(edata, update_info, notif_data, include_onlinename, include_avatarurl);
|
||||
RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(edata, notification->update_info(), notif_data, include_onlinename, include_avatarurl);
|
||||
np_memory.shrink_allocation(edata.addr(), edata.size());
|
||||
|
||||
// Ensures we do not call the callback if the room is not in the cache(ie we left the room already)
|
||||
if (!np_cache.add_member(room_id, notif_data->roomMemberDataInternal.get_ptr()))
|
||||
{
|
||||
get_match2_event(event_key, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
rpcn_log.notice("Received notification that user %s(%d) joined the room(%d)", notif_data->roomMemberDataInternal->userInfo.npId.handle.data, notif_data->roomMemberDataInternal->memberId, room_id);
|
||||
extra_nps::print_SceNpMatching2RoomMemberDataInternal(notif_data->roomMemberDataInternal.get_ptr());
|
||||
|
||||
// We initiate signaling if necessary
|
||||
if (const auto* signaling_info = notification->signaling())
|
||||
{
|
||||
const u32 addr_p2p = register_ip(signaling_info->ip());
|
||||
const u16 port_p2p = signaling_info->port();
|
||||
|
||||
const u16 member_id = notif_data->roomMemberDataInternal->memberId;
|
||||
const SceNpId& npid = notif_data->roomMemberDataInternal->userInfo.npId;
|
||||
|
||||
rpcn_log.notice("Join notification told to connect to member(%d=%s) of room(%d): %s:%d", member_id, reinterpret_cast<const char*>(npid.handle.data), room_id, ip_to_string(addr_p2p), port_p2p);
|
||||
|
||||
// Attempt Signaling
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
const u32 conn_id = sigh.init_sig2(npid, room_id, member_id);
|
||||
sigh.start_sig(conn_id, addr_p2p, port_p2p);
|
||||
}
|
||||
|
||||
if (room_event_cb)
|
||||
{
|
||||
sysutil_register_cb([room_event_cb = this->room_event_cb, room_id, event_key, room_event_cb_ctx = this->room_event_cb_ctx, room_event_cb_arg = this->room_event_cb_arg, size = edata.size()](ppu_thread& cb_ppu) -> s32
|
||||
|
@ -68,8 +92,12 @@ namespace np
|
|||
RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(edata, update_info, notif_data, include_onlinename, include_avatarurl);
|
||||
np_memory.shrink_allocation(edata.addr(), edata.size());
|
||||
|
||||
// Ensures we do not call the callback if the room is not in the cache(ie we left the room already)
|
||||
if (!np_cache.del_member(room_id, notif_data->roomMemberDataInternal->memberId))
|
||||
{
|
||||
get_match2_event(event_key, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
rpcn_log.notice("Received notification that user %s(%d) left the room(%d)", notif_data->roomMemberDataInternal->userInfo.npId.handle.data, notif_data->roomMemberDataInternal->memberId, room_id);
|
||||
extra_nps::print_SceNpMatching2RoomMemberDataInternal(notif_data->roomMemberDataInternal.get_ptr());
|
||||
|
@ -175,7 +203,10 @@ namespace np
|
|||
np_memory.shrink_allocation(edata.addr(), edata.size());
|
||||
|
||||
if (!np_cache.add_member(room_id, notif_data->newRoomMemberDataInternal.get_ptr()))
|
||||
{
|
||||
get_match2_event(event_key, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
rpcn_log.notice("Received notification that user's %s(%d) room (%d) data was updated", notif_data->newRoomMemberDataInternal->userInfo.npId.handle.data, notif_data->newRoomMemberDataInternal->memberId, room_id);
|
||||
extra_nps::print_SceNpMatching2RoomMemberDataInternal(notif_data->newRoomMemberDataInternal.get_ptr());
|
||||
|
@ -223,33 +254,7 @@ namespace np
|
|||
}
|
||||
}
|
||||
|
||||
void np_handler::notif_p2p_connect(std::vector<u8>& data)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
const u64 room_id = noti.get<u64>();
|
||||
const u16 member_id = noti.get<u16>();
|
||||
const u16 port_p2p = noti.get<u16>();
|
||||
const u32 addr_p2p = noti.get<u32>();
|
||||
|
||||
if (noti.is_error())
|
||||
{
|
||||
rpcn_log.error("Received faulty SignalP2PConnect notification");
|
||||
return;
|
||||
}
|
||||
|
||||
auto [res, npid] = np_cache.get_npid(room_id, member_id);
|
||||
if (!npid)
|
||||
return;
|
||||
|
||||
rpcn_log.notice("Received notification to connect to member(%d=%s) of room(%d): %s:%d", member_id, reinterpret_cast<const char*>((*npid).handle.data), room_id, ip_to_string(addr_p2p), port_p2p);
|
||||
|
||||
// Attempt Signaling
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
const u32 conn_id = sigh.init_sig2(*npid, room_id, member_id);
|
||||
sigh.start_sig(conn_id, addr_p2p, port_p2p);
|
||||
}
|
||||
|
||||
void np_handler::notif_signaling_info(std::vector<u8>& data)
|
||||
void np_handler::notif_signaling_helper(std::vector<u8>& data)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
const u32 addr_p2p = noti.get<u32>();
|
||||
|
@ -258,7 +263,7 @@ namespace np
|
|||
|
||||
if (noti.is_error())
|
||||
{
|
||||
rpcn_log.error("Received faulty SignalingInfo notification");
|
||||
rpcn_log.error("Received faulty SignalingHelper notification");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,4 @@
|
|||
#include "Emu/NP/rpcn_types.h"
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUCallback.h"
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
|
@ -156,20 +157,16 @@ namespace np
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
bool np_handler::reply_create_room_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_create_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
ensure(!rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])), "Unexpected error in CreateRoomGUI reply");
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
ensure(error == rpcn::ErrorType::NoError, "Unexpected error in CreateRoomGUI reply");
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoomStatus>();
|
||||
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to CreateRoomGUI command");
|
||||
ensure(!reply.is_error(), "Malformed reply to CreateRoomGUI command");
|
||||
|
||||
event_data edata(np_memory.allocate(MAX_SceNpMatchingJoinedRoomInfo_SIZE), sizeof(SceNpMatchingJoinedRoomInfo), MAX_SceNpMatchingJoinedRoomInfo_SIZE);
|
||||
auto* room_info = reinterpret_cast<SceNpMatchingJoinedRoomInfo*>(edata.data());
|
||||
|
@ -182,8 +179,6 @@ namespace np
|
|||
set_gui_result(SCE_NP_MATCHING_GUI_EVENT_CREATE_ROOM, std::move(edata));
|
||||
ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_CREATE_ROOM, 0);
|
||||
gui_epilog(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
error_code np_handler::join_room_gui(u32 ctx_id, vm::ptr<SceNpRoomId> roomid, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg)
|
||||
|
@ -201,44 +196,42 @@ namespace np
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
bool np_handler::reply_join_room_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_join_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
s32 error_code = CELL_OK;
|
||||
|
||||
switch (error)
|
||||
{
|
||||
s32 error = -1;
|
||||
|
||||
switch (static_cast<rpcn::ErrorType>(reply_data[0]))
|
||||
{
|
||||
case rpcn::ErrorType::RoomMissing:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM;
|
||||
break;
|
||||
case rpcn::ErrorType::RoomFull:
|
||||
// Might also be SCE_NP_MATCHING_SERVER_ERROR_ACCESS_FORBIDDEN or SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED ?
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_ROOM_CLOSED;
|
||||
break;
|
||||
case rpcn::ErrorType::RoomAlreadyJoined:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_ACCESS_FORBIDDEN;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected error in JoinRoomGUI reply: %d", reply_data[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_JOIN_ROOM, error);
|
||||
gui_epilog(ctx);
|
||||
return true;
|
||||
case rpcn::ErrorType::NoError: break;
|
||||
case rpcn::ErrorType::RoomMissing:
|
||||
error_code = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM;
|
||||
break;
|
||||
case rpcn::ErrorType::RoomFull:
|
||||
// Might also be SCE_NP_MATCHING_SERVER_ERROR_ACCESS_FORBIDDEN or SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED ?
|
||||
error_code = SCE_NP_MATCHING_SERVER_ERROR_ROOM_CLOSED;
|
||||
break;
|
||||
case rpcn::ErrorType::RoomAlreadyJoined:
|
||||
error_code = SCE_NP_MATCHING_SERVER_ERROR_ACCESS_FORBIDDEN;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected error in JoinRoomGUI reply: %d", static_cast<u8>(error));
|
||||
break;
|
||||
}
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoomStatus>();
|
||||
if (error_code != 0)
|
||||
{
|
||||
ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_JOIN_ROOM, error_code);
|
||||
gui_epilog(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to JoinRoomGUI command");
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoomStatus>();
|
||||
ensure(!reply.is_error(), "Malformed reply to JoinRoomGUI command");
|
||||
|
||||
event_data edata(np_memory.allocate(MAX_SceNpMatchingJoinedRoomInfo_SIZE), sizeof(SceNpMatchingJoinedRoomInfo), MAX_SceNpMatchingJoinedRoomInfo_SIZE);
|
||||
auto* room_info = reinterpret_cast<SceNpMatchingJoinedRoomInfo*>(edata.data());
|
||||
|
@ -257,8 +250,6 @@ namespace np
|
|||
set_gui_result(SCE_NP_MATCHING_GUI_EVENT_JOIN_ROOM, std::move(edata));
|
||||
ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_JOIN_ROOM, 0);
|
||||
gui_epilog(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
error_code np_handler::leave_room_gui(u32 ctx_id, vm::cptr<SceNpRoomId> roomid)
|
||||
|
@ -278,36 +269,29 @@ namespace np
|
|||
return not_an_error(req_id);
|
||||
}
|
||||
|
||||
bool np_handler::reply_leave_room_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_leave_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
s32 error_code = CELL_OK;
|
||||
|
||||
switch (error)
|
||||
{
|
||||
s32 error = -1;
|
||||
|
||||
switch (static_cast<rpcn::ErrorType>(reply_data[0]))
|
||||
{
|
||||
case rpcn::ErrorType::NotFound:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected error in LeaveRoomGUI reply: %d", reply_data[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, error);
|
||||
return true;
|
||||
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; break;
|
||||
default: fmt::throw_exception("Unexpected error in LeaveRoomGUI reply: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoomStatus>();
|
||||
if (error_code != CELL_OK)
|
||||
{
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, error_code);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to LeaveRoomGUI command");
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoomStatus>();
|
||||
ensure(!reply.is_error(), "Malformed reply to LeaveRoomGUI command");
|
||||
|
||||
event_data edata(np_memory.allocate(MAX_SceNpMatchingRoomStatus_SIZE), sizeof(SceNpMatchingRoomStatus), MAX_SceNpMatchingRoomStatus_SIZE);
|
||||
auto* room_status = reinterpret_cast<SceNpMatchingRoomStatus*>(edata.data());
|
||||
|
@ -320,7 +304,6 @@ namespace np
|
|||
|
||||
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, .edata = std::move(edata)});
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
error_code np_handler::get_room_list_gui(u32 ctx_id, vm::cptr<SceNpCommunicationId> communicationId, vm::ptr<SceNpMatchingReqRange> range, vm::ptr<SceNpMatchingSearchCondition> cond, vm::ptr<SceNpMatchingAttr> attr, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg, bool limit)
|
||||
|
@ -351,20 +334,16 @@ namespace np
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
bool np_handler::reply_get_room_list_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_get_room_list_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
ensure(!rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])), "Unexpected error in GetRoomListGUI reply");
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
ensure(error == rpcn::ErrorType::NoError, "Unexpected error in GetRoomListGUI reply");
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoomList>();
|
||||
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to GetRoomListGUI command");
|
||||
ensure(!reply.is_error(), "Malformed reply to GetRoomListGUI command");
|
||||
|
||||
event_data edata(np_memory.allocate(MAX_SceNpMatchingRoomList_SIZE), sizeof(SceNpMatchingRoomList), MAX_SceNpMatchingRoomList_SIZE);
|
||||
auto* room_list = reinterpret_cast<SceNpMatchingRoomList*>(edata.data());
|
||||
|
@ -385,7 +364,6 @@ namespace np
|
|||
}
|
||||
|
||||
gui_epilog(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
error_code np_handler::set_room_search_flag_gui(u32 ctx_id, vm::ptr<SceNpLobbyId> /* lobby_id */, vm::ptr<SceNpRoomId> room_id, s32 flag)
|
||||
|
@ -405,33 +383,24 @@ namespace np
|
|||
return not_an_error(req_id);
|
||||
}
|
||||
|
||||
bool np_handler::reply_set_room_search_flag_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_set_room_search_flag_gui(u32 req_id, rpcn::ErrorType error)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
s32 error = 0;
|
||||
s32 error_code = CELL_OK;
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
switch (error)
|
||||
{
|
||||
switch (static_cast<rpcn::ErrorType>(reply_data[0]))
|
||||
{
|
||||
case rpcn::ErrorType::NotFound:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM;
|
||||
break;
|
||||
case rpcn::ErrorType::Unauthorized:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected error in SetRoomSearchFlagGUI reply: %d", reply_data[0]);
|
||||
break;
|
||||
}
|
||||
case rpcn::ErrorType::NoError: break;
|
||||
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; break;
|
||||
case rpcn::ErrorType::Unauthorized: error_code = SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED; break;
|
||||
default: fmt::throw_exception("Unexpected error in SetRoomSearchFlagGUI reply: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_SET_ROOM_SEARCH_FLAG_DONE, error);
|
||||
return true;
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_SET_ROOM_SEARCH_FLAG_DONE, error_code);
|
||||
}
|
||||
|
||||
error_code np_handler::get_room_search_flag_gui(u32 ctx_id, vm::ptr<SceNpLobbyId> /* lobby_id */, vm::ptr<SceNpRoomId> room_id)
|
||||
|
@ -451,36 +420,30 @@ namespace np
|
|||
return not_an_error(req_id);
|
||||
}
|
||||
|
||||
bool np_handler::reply_get_room_search_flag_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_get_room_search_flag_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
s32 error_code = CELL_OK;
|
||||
|
||||
switch (error)
|
||||
{
|
||||
s32 error = -1;
|
||||
|
||||
switch (static_cast<rpcn::ErrorType>(reply_data[0]))
|
||||
{
|
||||
case rpcn::ErrorType::NotFound:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected error in GetRoomSearchFlagGUI reply: %d", reply_data[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, error);
|
||||
return true;
|
||||
case rpcn::ErrorType::NoError: break;
|
||||
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; break;
|
||||
default: fmt::throw_exception("Unexpected error in GetRoomSearchFlagGUI reply: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoom>();
|
||||
if (error_code != CELL_OK)
|
||||
{
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, error_code);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to GetRoomSearchFlagGUI command");
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoom>();
|
||||
ensure(!reply.is_error(), "Malformed reply to GetRoomSearchFlagGUI command");
|
||||
|
||||
event_data edata(np_memory.allocate(MAX_SceNpMatchingRoom_SIZE), sizeof(SceNpMatchingRoom), MAX_SceNpMatchingRoom_SIZE);
|
||||
auto* room_info = reinterpret_cast<SceNpMatchingRoom*>(edata.data());
|
||||
|
@ -491,7 +454,6 @@ namespace np
|
|||
|
||||
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, .edata = std::move(edata)});
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
error_code np_handler::set_room_info_gui(u32 ctx_id, vm::ptr<SceNpLobbyId> /* lobby_id */, vm::ptr<SceNpRoomId> room_id, vm::ptr<SceNpMatchingAttr> attr)
|
||||
|
@ -516,33 +478,23 @@ namespace np
|
|||
return not_an_error(req_id);
|
||||
}
|
||||
|
||||
bool np_handler::reply_set_room_info_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_set_room_info_gui(u32 req_id, rpcn::ErrorType error)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
s32 error = 0;
|
||||
s32 error_code = CELL_OK;
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
switch (error)
|
||||
{
|
||||
switch (static_cast<rpcn::ErrorType>(reply_data[0]))
|
||||
{
|
||||
case rpcn::ErrorType::NotFound:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM;
|
||||
break;
|
||||
case rpcn::ErrorType::Unauthorized:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected error in SetRoomInfoGUI reply: %d", reply_data[0]);
|
||||
break;
|
||||
}
|
||||
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; break;
|
||||
case rpcn::ErrorType::Unauthorized: error_code = SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED; break;
|
||||
default: fmt::throw_exception("Unexpected error in SetRoomInfoGUI reply: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_SET_ROOM_INFO_DONE, error);
|
||||
return true;
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_SET_ROOM_INFO_DONE, error_code);
|
||||
}
|
||||
|
||||
error_code np_handler::get_room_info_gui(u32 ctx_id, vm::ptr<SceNpLobbyId> /* lobby_id */, vm::ptr<SceNpRoomId> room_id, vm::ptr<SceNpMatchingAttr> attr)
|
||||
|
@ -562,36 +514,30 @@ namespace np
|
|||
return not_an_error(req_id);
|
||||
}
|
||||
|
||||
bool np_handler::reply_get_room_info_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_get_room_info_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
s32 error_code = CELL_OK;
|
||||
|
||||
switch (error)
|
||||
{
|
||||
s32 error = -1;
|
||||
|
||||
switch (static_cast<rpcn::ErrorType>(reply_data[0]))
|
||||
{
|
||||
case rpcn::ErrorType::NotFound:
|
||||
error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected error in GetRoomInfoGUI reply: %d", reply_data[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, error);
|
||||
return true;
|
||||
case rpcn::ErrorType::NoError: break;
|
||||
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; break;
|
||||
default: fmt::throw_exception("Unexpected error in GetRoomInfoGUI reply: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoom>();
|
||||
if (error_code != CELL_OK)
|
||||
{
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, error_code);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to GetRoomInfoGUI command");
|
||||
const auto* resp = reply.get_flatbuffer<MatchingRoom>();
|
||||
ensure(!reply.is_error(), "Malformed reply to GetRoomInfoGUI command");
|
||||
|
||||
event_data edata(np_memory.allocate(MAX_SceNpMatchingRoom_SIZE), sizeof(SceNpMatchingRoom), MAX_SceNpMatchingRoom_SIZE);
|
||||
auto* room_info = reinterpret_cast<SceNpMatchingRoom*>(edata.data());
|
||||
|
@ -602,7 +548,6 @@ namespace np
|
|||
|
||||
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, .edata = std::move(edata)});
|
||||
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
error_code np_handler::quickmatch_gui(u32 ctx_id, vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpMatchingSearchCondition> cond, s32 available_num, s32 timeout, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg)
|
||||
|
@ -621,20 +566,16 @@ namespace np
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
bool np_handler::reply_quickmatch_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_quickmatch_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
ensure(!rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])), "Unexpected error in QuickMatchGUI reply");
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
ensure(error == rpcn::ErrorType::NoError, "Unexpected error in QuickMatchGUI reply");
|
||||
const auto* resp = reply.get_flatbuffer<MatchingGuiRoomId>();
|
||||
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to QuickMatchGUI command");
|
||||
ensure(!reply.is_error(), "Malformed reply to QuickMatchGUI command");
|
||||
|
||||
SceNpRoomId room_id{};
|
||||
ensure(resp->id() && resp->id()->size() == sizeof(SceNpRoomId::opt));
|
||||
|
@ -675,7 +616,6 @@ namespace np
|
|||
ctx->wakey = 0;
|
||||
auto& thread = *ctx->thread;
|
||||
thread(room_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
error_code np_handler::searchjoin_gui(u32 ctx_id, vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpMatchingSearchCondition> cond, vm::cptr<SceNpMatchingAttr> attr, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg)
|
||||
|
@ -692,37 +632,30 @@ namespace np
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
bool np_handler::reply_searchjoin_gui(u32 req_id, std::vector<u8>& reply_data)
|
||||
void np_handler::reply_searchjoin_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply)
|
||||
{
|
||||
auto ctx = take_pending_gui_request(req_id);
|
||||
|
||||
if (!ctx)
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
s32 error_code = CELL_OK;
|
||||
|
||||
switch (error)
|
||||
{
|
||||
s32 error = -1;
|
||||
|
||||
switch (static_cast<rpcn::ErrorType>(reply_data[0]))
|
||||
{
|
||||
case rpcn::ErrorType::NotFound:
|
||||
error = SCE_NP_MATCHING_ERROR_SEARCH_JOIN_ROOM_NOT_FOUND;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected error in SearchJoinRoomGUI reply: %d", reply_data[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_SEARCH_JOIN, error);
|
||||
gui_epilog(ctx);
|
||||
return true;
|
||||
case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING_ERROR_SEARCH_JOIN_ROOM_NOT_FOUND; break;
|
||||
default: fmt::throw_exception("Unexpected error in SearchJoinRoomGUI reply: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
const auto* resp = reply.get_flatbuffer<MatchingSearchJoinRoomInfo>();
|
||||
if (error_code != CELL_OK)
|
||||
{
|
||||
ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_SEARCH_JOIN, error_code);
|
||||
gui_epilog(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to SearchJoinRoomGUI command");
|
||||
const auto* resp = reply.get_flatbuffer<MatchingSearchJoinRoomInfo>();
|
||||
ensure(!reply.is_error(), "Malformed reply to SearchJoinRoomGUI command");
|
||||
|
||||
event_data edata(np_memory.allocate(MAX_SceNpMatchingSearchJoinRoomInfo_SIZE), sizeof(SceNpMatchingSearchJoinRoomInfo), MAX_SceNpMatchingSearchJoinRoomInfo_SIZE);
|
||||
auto* room_info = reinterpret_cast<SceNpMatchingSearchJoinRoomInfo*>(edata.data());
|
||||
|
@ -741,8 +674,6 @@ namespace np
|
|||
set_gui_result(SCE_NP_MATCHING_GUI_EVENT_SEARCH_JOIN, std::move(edata));
|
||||
ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_SEARCH_JOIN, 0);
|
||||
gui_epilog(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Local cache requests
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "Utilities/StrUtil.h"
|
||||
#include "stdafx.h"
|
||||
#include <span>
|
||||
#include "np_structs_extra.h"
|
||||
|
@ -117,9 +118,13 @@ namespace extra_nps
|
|||
print_SceNpMatching2BinAttr(&req->roomBinAttrExternal[i]);
|
||||
|
||||
sceNp2.warning("roomPassword: *0x%x", req->roomPassword);
|
||||
|
||||
if (req->roomPassword)
|
||||
sceNp2.warning("data: %s", fmt::buf_to_hexstring(req->roomPassword->data, sizeof(req->roomPassword->data)));
|
||||
|
||||
sceNp2.warning("groupConfig: *0x%x", req->groupConfig);
|
||||
sceNp2.warning("groupConfigNum: %d", req->groupConfigNum);
|
||||
sceNp2.warning("passwordSlotMask: *0x%x", req->passwordSlotMask);
|
||||
sceNp2.warning("passwordSlotMask: *0x%x, value: 0x%x", req->passwordSlotMask, req->passwordSlotMask ? static_cast<u64>(*req->passwordSlotMask) : 0ull);
|
||||
sceNp2.warning("allowedUser: *0x%x", req->allowedUser);
|
||||
sceNp2.warning("allowedUserNum: %d", req->allowedUserNum);
|
||||
sceNp2.warning("blockedUser: *0x%x", req->blockedUser);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "Emu/Cell/lv2/sys_net/sys_net_helpers.h"
|
||||
#include "Emu/NP/ip_address.h"
|
||||
#include "stdafx.h"
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
@ -5,6 +7,7 @@
|
|||
#include <chrono>
|
||||
#include "rpcn_client.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include "Utilities/Thread.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/NP/rpcn_config.h"
|
||||
|
@ -42,6 +45,160 @@ LOG_CHANNEL(rpcn_log, "rpcn");
|
|||
|
||||
int get_native_error();
|
||||
|
||||
template <>
|
||||
void fmt_class_string<rpcn::ErrorType>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](auto value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case rpcn::ErrorType::NoError: return "NoError";
|
||||
case rpcn::ErrorType::Malformed: return "Malformed";
|
||||
case rpcn::ErrorType::Invalid: return "Invalid";
|
||||
case rpcn::ErrorType::InvalidInput: return "InvalidInput";
|
||||
case rpcn::ErrorType::TooSoon: return "TooSoon";
|
||||
case rpcn::ErrorType::LoginError: return "LoginError";
|
||||
case rpcn::ErrorType::LoginAlreadyLoggedIn: return "LoginAlreadyLoggedIn";
|
||||
case rpcn::ErrorType::LoginInvalidUsername: return "LoginInvalidUsername";
|
||||
case rpcn::ErrorType::LoginInvalidPassword: return "LoginInvalidPassword";
|
||||
case rpcn::ErrorType::LoginInvalidToken: return "LoginInvalidToken";
|
||||
case rpcn::ErrorType::CreationError: return "CreationError";
|
||||
case rpcn::ErrorType::CreationExistingUsername: return "CreationExistingUsername";
|
||||
case rpcn::ErrorType::CreationBannedEmailProvider: return "CreationBannedEmailProvider";
|
||||
case rpcn::ErrorType::CreationExistingEmail: return "CreationExistingEmail";
|
||||
case rpcn::ErrorType::RoomMissing: return "RoomMissing";
|
||||
case rpcn::ErrorType::RoomAlreadyJoined: return "RoomAlreadyJoined";
|
||||
case rpcn::ErrorType::RoomFull: return "RoomFull";
|
||||
case rpcn::ErrorType::RoomPasswordMismatch: return "RoomPasswordMismatch";
|
||||
case rpcn::ErrorType::RoomPasswordMissing: return "RoomPasswordMissing";
|
||||
case rpcn::ErrorType::RoomGroupNoJoinLabel: return "RoomGroupNoJoinLabel";
|
||||
case rpcn::ErrorType::RoomGroupFull: return "RoomGroupFull";
|
||||
case rpcn::ErrorType::RoomGroupJoinLabelNotFound: return "RoomGroupJoinLabelNotFound";
|
||||
case rpcn::ErrorType::RoomGroupMaxSlotMismatch: return "RoomGroupMaxSlotMismatch";
|
||||
case rpcn::ErrorType::Unauthorized: return "Unauthorized";
|
||||
case rpcn::ErrorType::DbFail: return "DbFail";
|
||||
case rpcn::ErrorType::EmailFail: return "EmailFail";
|
||||
case rpcn::ErrorType::NotFound: return "NotFound";
|
||||
case rpcn::ErrorType::Blocked: return "Blocked";
|
||||
case rpcn::ErrorType::AlreadyFriend: return "AlreadyFriend";
|
||||
case rpcn::ErrorType::ScoreNotBest: return "ScoreNotBest";
|
||||
case rpcn::ErrorType::ScoreInvalid: return "ScoreInvalid";
|
||||
case rpcn::ErrorType::ScoreHasData: return "ScoreHasData";
|
||||
case rpcn::ErrorType::CondFail: return "CondFail";
|
||||
case rpcn::ErrorType::Unsupported: return "Unsupported";
|
||||
default: break;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<rpcn::CommandType>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](auto value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case rpcn::CommandType::Login: return "Login";
|
||||
case rpcn::CommandType::Terminate: return "Terminate";
|
||||
case rpcn::CommandType::Create: return "Create";
|
||||
case rpcn::CommandType::SendToken: return "SendToken";
|
||||
case rpcn::CommandType::SendResetToken: return "SendResetToken";
|
||||
case rpcn::CommandType::ResetPassword: return "ResetPassword";
|
||||
case rpcn::CommandType::ResetState: return "ResetState";
|
||||
case rpcn::CommandType::AddFriend: return "AddFriend";
|
||||
case rpcn::CommandType::RemoveFriend: return "RemoveFriend";
|
||||
case rpcn::CommandType::AddBlock: return "AddBlock";
|
||||
case rpcn::CommandType::RemoveBlock: return "RemoveBlock";
|
||||
case rpcn::CommandType::GetServerList: return "GetServerList";
|
||||
case rpcn::CommandType::GetWorldList: return "GetWorldList";
|
||||
case rpcn::CommandType::CreateRoom: return "CreateRoom";
|
||||
case rpcn::CommandType::JoinRoom: return "JoinRoom";
|
||||
case rpcn::CommandType::LeaveRoom: return "LeaveRoom";
|
||||
case rpcn::CommandType::SearchRoom: return "SearchRoom";
|
||||
case rpcn::CommandType::GetRoomDataExternalList: return "GetRoomDataExternalList";
|
||||
case rpcn::CommandType::SetRoomDataExternal: return "SetRoomDataExternal";
|
||||
case rpcn::CommandType::GetRoomDataInternal: return "GetRoomDataInternal";
|
||||
case rpcn::CommandType::SetRoomDataInternal: return "SetRoomDataInternal";
|
||||
case rpcn::CommandType::GetRoomMemberDataInternal: return "GetRoomMemberDataInternal";
|
||||
case rpcn::CommandType::SetRoomMemberDataInternal: return "SetRoomMemberDataInternal";
|
||||
case rpcn::CommandType::SetUserInfo: return "SetUserInfo";
|
||||
case rpcn::CommandType::PingRoomOwner: return "PingRoomOwner";
|
||||
case rpcn::CommandType::SendRoomMessage: return "SendRoomMessage";
|
||||
case rpcn::CommandType::RequestSignalingInfos: return "RequestSignalingInfos";
|
||||
case rpcn::CommandType::RequestTicket: return "RequestTicket";
|
||||
case rpcn::CommandType::SendMessage: return "SendMessage";
|
||||
case rpcn::CommandType::GetBoardInfos: return "GetBoardInfos";
|
||||
case rpcn::CommandType::RecordScore: return "RecordScore";
|
||||
case rpcn::CommandType::RecordScoreData: return "RecordScoreData";
|
||||
case rpcn::CommandType::GetScoreData: return "GetScoreData";
|
||||
case rpcn::CommandType::GetScoreRange: return "GetScoreRange";
|
||||
case rpcn::CommandType::GetScoreFriends: return "GetScoreFriends";
|
||||
case rpcn::CommandType::GetScoreNpid: return "GetScoreNpid";
|
||||
case rpcn::CommandType::GetNetworkTime: return "GetNetworkTime";
|
||||
case rpcn::CommandType::TusSetMultiSlotVariable: return "TusSetMultiSlotVariable";
|
||||
case rpcn::CommandType::TusGetMultiSlotVariable: return "TusGetMultiSlotVariable";
|
||||
case rpcn::CommandType::TusGetMultiUserVariable: return "TusGetMultiUserVariable";
|
||||
case rpcn::CommandType::TusGetFriendsVariable: return "TusGetFriendsVariable";
|
||||
case rpcn::CommandType::TusAddAndGetVariable: return "TusAddAndGetVariable";
|
||||
case rpcn::CommandType::TusTryAndSetVariable: return "TusTryAndSetVariable";
|
||||
case rpcn::CommandType::TusDeleteMultiSlotVariable: return "TusDeleteMultiSlotVariable";
|
||||
case rpcn::CommandType::TusSetData: return "TusSetData";
|
||||
case rpcn::CommandType::TusGetData: return "TusGetData";
|
||||
case rpcn::CommandType::TusGetMultiSlotDataStatus: return "TusGetMultiSlotDataStatus";
|
||||
case rpcn::CommandType::TusGetMultiUserDataStatus: return "TusGetMultiUserDataStatus";
|
||||
case rpcn::CommandType::TusGetFriendsDataStatus: return "TusGetFriendsDataStatus";
|
||||
case rpcn::CommandType::TusDeleteMultiSlotData: return "TusDeleteMultiSlotData";
|
||||
case rpcn::CommandType::SetPresence: return "SetPresence";
|
||||
case rpcn::CommandType::CreateRoomGUI: return "CreateRoomGUI";
|
||||
case rpcn::CommandType::JoinRoomGUI: return "JoinRoomGUI";
|
||||
case rpcn::CommandType::LeaveRoomGUI: return "LeaveRoomGUI";
|
||||
case rpcn::CommandType::GetRoomListGUI: return "GetRoomListGUI";
|
||||
case rpcn::CommandType::SetRoomSearchFlagGUI: return "SetRoomSearchFlagGUI";
|
||||
case rpcn::CommandType::GetRoomSearchFlagGUI: return "GetRoomSearchFlagGUI";
|
||||
case rpcn::CommandType::SetRoomInfoGUI: return "SetRoomInfoGUI";
|
||||
case rpcn::CommandType::GetRoomInfoGUI: return "GetRoomInfoGUI";
|
||||
case rpcn::CommandType::QuickMatchGUI: return "QuickMatchGUI";
|
||||
case rpcn::CommandType::SearchJoinRoomGUI: return "SearchJoinRoomGUI";
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<rpcn::NotificationType>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](auto value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case rpcn::NotificationType::UserJoinedRoom: return "UserJoinedRoom";
|
||||
case rpcn::NotificationType::UserLeftRoom: return "UserLeftRoom";
|
||||
case rpcn::NotificationType::RoomDestroyed: return "RoomDestroyed";
|
||||
case rpcn::NotificationType::UpdatedRoomDataInternal: return "UpdatedRoomDataInternal";
|
||||
case rpcn::NotificationType::UpdatedRoomMemberDataInternal: return "UpdatedRoomMemberDataInternal";
|
||||
case rpcn::NotificationType::FriendQuery: return "FriendQuery";
|
||||
case rpcn::NotificationType::FriendNew: return "FriendNew";
|
||||
case rpcn::NotificationType::FriendLost: return "FriendLost";
|
||||
case rpcn::NotificationType::FriendStatus: return "FriendStatus";
|
||||
case rpcn::NotificationType::RoomMessageReceived: return "RoomMessageReceived";
|
||||
case rpcn::NotificationType::MessageReceived: return "MessageReceived";
|
||||
case rpcn::NotificationType::FriendPresenceChanged: return "FriendPresenceChanged";
|
||||
case rpcn::NotificationType::SignalingHelper: return "SignalingHelper";
|
||||
case rpcn::NotificationType::MemberJoinedRoomGUI: return "MemberJoinedRoomGUI";
|
||||
case rpcn::NotificationType::MemberLeftRoomGUI: return "MemberLeftRoomGUI";
|
||||
case rpcn::NotificationType::RoomDisappearedGUI: return "RoomDisappearedGUI";
|
||||
case rpcn::NotificationType::RoomOwnerChangedGUI: return "RoomOwnerChangedGUI";
|
||||
case rpcn::NotificationType::UserKickedGUI: return "UserKickedGUI";
|
||||
case rpcn::NotificationType::QuickMatchCompleteGUI: return "QuickMatchCompleteGUI";
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
void vec_stream::dump() const
|
||||
{
|
||||
rpcn_log.error("vec_stream dump:\n%s", fmt::buf_to_hexstring(vec.data(), vec.size()));
|
||||
|
@ -99,51 +256,64 @@ namespace rpcn
|
|||
rpcn_log.notice("online: %s, pr_com_id: %s, pr_title: %s, pr_status: %s, pr_comment: %s, pr_data: %s", online ? "true" : "false", pr_com_id.data, pr_title, pr_status, pr_comment, fmt::buf_to_hexstring(pr_data.data(), pr_data.size()));
|
||||
}
|
||||
|
||||
constexpr u32 RPCN_PROTOCOL_VERSION = 25;
|
||||
constexpr usz RPCN_HEADER_SIZE = 15;
|
||||
constexpr u32 RPCN_PROTOCOL_VERSION = 26;
|
||||
constexpr usz RPCN_HEADER_SIZE = 15;
|
||||
|
||||
bool is_error(ErrorType err)
|
||||
const char* error_to_explanation(rpcn::ErrorType error)
|
||||
{
|
||||
if (err >= ErrorType::__error_last)
|
||||
switch (error)
|
||||
{
|
||||
rpcn_log.error("Invalid error returned!");
|
||||
return true;
|
||||
case rpcn::ErrorType::NoError: return "No error";
|
||||
case rpcn::ErrorType::Malformed: return "Sent packet was malformed!";
|
||||
case rpcn::ErrorType::Invalid: return "Sent command was invalid!";
|
||||
case rpcn::ErrorType::InvalidInput: return "Sent data was invalid!";
|
||||
case rpcn::ErrorType::TooSoon: return "Request happened too soon!";
|
||||
case rpcn::ErrorType::LoginError: return "Unknown login error!";
|
||||
case rpcn::ErrorType::LoginAlreadyLoggedIn: return "User is already logged in!";
|
||||
case rpcn::ErrorType::LoginInvalidUsername: return "Login error: invalid username!";
|
||||
case rpcn::ErrorType::LoginInvalidPassword: return "Login error: invalid password!";
|
||||
case rpcn::ErrorType::LoginInvalidToken: return "Login error: invalid token!";
|
||||
case rpcn::ErrorType::CreationError: return "Error creating an account!";
|
||||
case rpcn::ErrorType::CreationExistingUsername: return "Error creating an account: existing username!";
|
||||
case rpcn::ErrorType::CreationBannedEmailProvider: return "Error creating an account: banned email provider!";
|
||||
case rpcn::ErrorType::CreationExistingEmail: return "Error creating an account: an account with that email already exist!";
|
||||
case rpcn::ErrorType::RoomMissing: return "User tried to join a non-existent room!";
|
||||
case rpcn::ErrorType::RoomAlreadyJoined: return "User has already joined!";
|
||||
case rpcn::ErrorType::RoomFull: return "User tried to join a full room!";
|
||||
case rpcn::ErrorType::RoomPasswordMismatch: return "Room password used was invalid";
|
||||
case rpcn::ErrorType::RoomPasswordMissing: return "Room password was missing during room creation";
|
||||
case rpcn::ErrorType::RoomGroupNoJoinLabel: return "Tried to join a group room without a label";
|
||||
case rpcn::ErrorType::RoomGroupFull: return "Room group is full";
|
||||
case rpcn::ErrorType::RoomGroupJoinLabelNotFound: return "Join label was invalid";
|
||||
case rpcn::ErrorType::RoomGroupMaxSlotMismatch: return "Mismatch between max_slot and the listed slots in groups";
|
||||
case rpcn::ErrorType::Unauthorized: return "User attempted an unauthorized operation!";
|
||||
case rpcn::ErrorType::DbFail: return "A db query failed on the server!";
|
||||
case rpcn::ErrorType::EmailFail: return "An email action failed on the server!";
|
||||
case rpcn::ErrorType::NotFound: return "A request replied not found!";
|
||||
case rpcn::ErrorType::Blocked: return "You're blocked!";
|
||||
case rpcn::ErrorType::AlreadyFriend: return "You're already friends!";
|
||||
case rpcn::ErrorType::ScoreNotBest: return "Attempted to register a score that is not better!";
|
||||
case rpcn::ErrorType::ScoreInvalid: return "Score for player was found but wasn't what was expected!";
|
||||
case rpcn::ErrorType::ScoreHasData: return "Score already has game data associated with it!";
|
||||
case rpcn::ErrorType::CondFail: return "Condition related to the query failed!";
|
||||
case rpcn::ErrorType::Unsupported: return "An unsupported operation was attempted!";
|
||||
}
|
||||
|
||||
switch (err)
|
||||
{
|
||||
case NoError: return false;
|
||||
case Malformed: rpcn_log.error("Sent packet was malformed!"); break;
|
||||
case Invalid: rpcn_log.error("Sent command was invalid!"); break;
|
||||
case InvalidInput: rpcn_log.error("Sent data was invalid!"); break;
|
||||
case TooSoon: rpcn_log.error("Request happened too soon!"); break;
|
||||
case LoginError: rpcn_log.error("Unknown login error!"); break;
|
||||
case LoginAlreadyLoggedIn: rpcn_log.error("User is already logged in!"); break;
|
||||
case LoginInvalidUsername: rpcn_log.error("Login error: invalid username!"); break;
|
||||
case LoginInvalidPassword: rpcn_log.error("Login error: invalid password!"); break;
|
||||
case LoginInvalidToken: rpcn_log.error("Login error: invalid token!"); break;
|
||||
case CreationError: rpcn_log.error("Error creating an account!"); break;
|
||||
case CreationExistingUsername: rpcn_log.error("Error creating an account: existing username!"); break;
|
||||
case CreationBannedEmailProvider: rpcn_log.error("Error creating an account: banned email provider!"); break;
|
||||
case CreationExistingEmail: rpcn_log.error("Error creating an account: an account with that email already exist!"); break;
|
||||
case RoomMissing: rpcn_log.error("User tried to join a non-existent room!"); break;
|
||||
case RoomAlreadyJoined: rpcn_log.error("User has already joined!"); break;
|
||||
case RoomFull: rpcn_log.error("User tried to join a full room!"); break;
|
||||
case Unauthorized: rpcn_log.error("User attempted an unauthorized operation!"); break;
|
||||
case DbFail: rpcn_log.error("A db query failed on the server!"); break;
|
||||
case EmailFail: rpcn_log.error("An email action failed on the server!"); break;
|
||||
case NotFound: rpcn_log.error("A request replied not found!"); break;
|
||||
case Blocked: rpcn_log.error("You're blocked!"); break;
|
||||
case AlreadyFriend: rpcn_log.error("You're already friends!"); break;
|
||||
case ScoreNotBest: rpcn_log.error("Attempted to register a score that is not better!"); break;
|
||||
case ScoreInvalid: rpcn_log.error("Score for player was found but wasn't what was expected!"); break;
|
||||
case ScoreHasData: rpcn_log.error("Score already has game data associated with it!"); break;
|
||||
case CondFail: rpcn_log.error("Condition related to the query failed!"); break;
|
||||
case Unsupported: rpcn_log.error("An unsupported operation was attempted!"); break;
|
||||
default: rpcn_log.fatal("Unhandled ErrorType reached the switch?"); break;
|
||||
}
|
||||
fmt::throw_exception("Unknown error returned: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
return true;
|
||||
void print_error(rpcn::CommandType command, rpcn::ErrorType error)
|
||||
{
|
||||
const std::string error_message = fmt::format("command: %s result: %s, explanation: %s", command, error, error_to_explanation(error));
|
||||
|
||||
if (error == rpcn::ErrorType::NoError)
|
||||
{
|
||||
rpcn_log.trace("%s", error_message);
|
||||
}
|
||||
else
|
||||
{
|
||||
rpcn_log.warning("%s", error_message);
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor, destructor & singleton manager
|
||||
|
@ -267,6 +437,10 @@ namespace rpcn
|
|||
{
|
||||
thread_base::set_name("RPCN Client");
|
||||
|
||||
// UDP Signaling related
|
||||
steady_clock::time_point last_ping_time_ipv4{}, last_pong_time_ipv4{};
|
||||
steady_clock::time_point last_ping_time_ipv6{}, last_pong_time_ipv6{};
|
||||
|
||||
while (true)
|
||||
{
|
||||
sem_rpcn.acquire();
|
||||
|
@ -321,16 +495,15 @@ namespace rpcn
|
|||
if (authentified && !Emu.IsStopped())
|
||||
{
|
||||
// Ping the UDP Signaling Server if we're authentified & ingame
|
||||
auto now = steady_clock::now();
|
||||
|
||||
auto rpcn_msgs = get_rpcn_msgs();
|
||||
const auto now = steady_clock::now();
|
||||
const auto rpcn_msgs = get_rpcn_msgs();
|
||||
|
||||
for (const auto& msg : rpcn_msgs)
|
||||
{
|
||||
if (msg.size() == 6)
|
||||
{
|
||||
const u32 new_addr_sig = read_from_ptr<le_t<u32>>(&msg[0]);
|
||||
const u32 new_port_sig = read_from_ptr<be_t<u16>>(&msg[4]);
|
||||
const u16 new_port_sig = read_from_ptr<be_t<u16>>(&msg[4]);
|
||||
const u32 old_addr_sig = addr_sig;
|
||||
const u32 old_port_sig = port_sig;
|
||||
|
||||
|
@ -352,7 +525,16 @@ namespace rpcn
|
|||
}
|
||||
}
|
||||
|
||||
last_pong_time = now;
|
||||
last_pong_time_ipv4 = now;
|
||||
}
|
||||
else if (msg.size() == 18)
|
||||
{
|
||||
// We don't really need ipv6 info stored so we just update the pong data
|
||||
// std::array<u8, 16> new_ipv6_addr;
|
||||
// std::memcpy(new_ipv6_addr.data(), &msg[3], 16);
|
||||
// const u32 new_ipv6_port = read_from_ptr<be_t<u16>>(&msg[16]);
|
||||
|
||||
last_pong_time_ipv6 = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -360,36 +542,64 @@ namespace rpcn
|
|||
}
|
||||
}
|
||||
|
||||
// Send a packet every 5 seconds and then every 500 ms until reply is received
|
||||
if (now - last_pong_time >= 5s && now - last_ping_time > 500ms)
|
||||
const std::chrono::nanoseconds time_since_last_ipv4_ping = now - last_ping_time_ipv4;
|
||||
const std::chrono::nanoseconds time_since_last_ipv4_pong = now - last_pong_time_ipv4;
|
||||
const std::chrono::nanoseconds time_since_last_ipv6_ping = now - last_ping_time_ipv6;
|
||||
const std::chrono::nanoseconds time_since_last_ipv6_pong = now - last_pong_time_ipv6;
|
||||
|
||||
auto forge_ping_packet = [&]() -> std::vector<u8>
|
||||
{
|
||||
std::vector<u8> ping(13);
|
||||
ping[0] = 1;
|
||||
ping[0] = 1;
|
||||
write_to_ptr<le_t<s64>>(ping, 1, user_id);
|
||||
write_to_ptr<be_t<u32>>(ping, 9, +local_addr_sig);
|
||||
if (send_packet_from_p2p_port(ping, addr_rpcn_udp) == -1)
|
||||
{
|
||||
rpcn_log.error("Failed to send ping to RPCN!");
|
||||
}
|
||||
last_ping_time = now;
|
||||
}
|
||||
else
|
||||
return ping;
|
||||
};
|
||||
|
||||
// Send a packet every 5 seconds and then every 500 ms until reply is received
|
||||
if (time_since_last_ipv4_pong >= 5s && time_since_last_ipv4_ping > 500ms)
|
||||
{
|
||||
const auto ping = forge_ping_packet();
|
||||
|
||||
if (!send_packet_from_p2p_port_ipv4(ping, addr_rpcn_udp_ipv4))
|
||||
rpcn_log.error("Failed to send IPv4 ping to RPCN!");
|
||||
|
||||
last_ping_time_ipv4 = now;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (np::is_ipv6_supported() && time_since_last_ipv6_pong >= 5s && time_since_last_ipv6_ping > 500ms)
|
||||
{
|
||||
const auto ping = forge_ping_packet();
|
||||
|
||||
if (!send_packet_from_p2p_port_ipv6(ping, addr_rpcn_udp_ipv6))
|
||||
rpcn_log.error("Failed to send IPv6 ping to RPCN!");
|
||||
|
||||
last_ping_time_ipv6 = now;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto min_duration_for = [&](const auto last_ping_time, const auto last_pong_time) -> std::chrono::nanoseconds
|
||||
{
|
||||
std::chrono::nanoseconds duration;
|
||||
if ((now - last_pong_time) < 5s)
|
||||
{
|
||||
duration = 5s - (now - last_pong_time);
|
||||
return (5s - (now - last_pong_time));
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = 500ms - (now - last_ping_time);
|
||||
return (500ms - (now - last_ping_time));
|
||||
}
|
||||
};
|
||||
|
||||
if (!sem_rpcn.try_acquire_for(duration))
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
auto duration = min_duration_for(last_ping_time_ipv4, last_pong_time_ipv4);
|
||||
|
||||
if (np::is_ipv6_supported())
|
||||
{
|
||||
const auto duration_ipv6 = min_duration_for(last_ping_time_ipv6, last_pong_time_ipv6);
|
||||
duration = std::min(duration, duration_ipv6);
|
||||
}
|
||||
|
||||
sem_rpcn.try_acquire_for(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -410,10 +620,10 @@ namespace rpcn
|
|||
case recvn_result::recvn_terminate: return error_and_disconnect_notice("Recvn was forcefully aborted");
|
||||
}
|
||||
|
||||
const u8 packet_type = header[0];
|
||||
const u16 command = read_from_ptr<le_t<u16>>(&header[1]);
|
||||
const u8 packet_type = header[0];
|
||||
const auto command = static_cast<rpcn::CommandType>(static_cast<u16>(read_from_ptr<le_t<u16>>(&header[1])));
|
||||
const u32 packet_size = read_from_ptr<le_t<u32>>(&header[3]);
|
||||
const u64 packet_id = read_from_ptr<le_t<u64>>(&header[7]);
|
||||
const u64 packet_id = read_from_ptr<le_t<u64>>(&header[7]);
|
||||
|
||||
if (packet_size < RPCN_HEADER_SIZE)
|
||||
return error_and_disconnect("Invalid packet size");
|
||||
|
@ -435,6 +645,13 @@ namespace rpcn
|
|||
if (data.empty())
|
||||
return error_and_disconnect("Reply packet without result");
|
||||
|
||||
// Internal commands without feedback
|
||||
if (command == CommandType::ResetState)
|
||||
{
|
||||
ensure(data[0] == static_cast<u8>(ErrorType::NoError));
|
||||
break;
|
||||
}
|
||||
|
||||
// Those commands are handled synchronously and won't be forwarded to NP Handler
|
||||
if (command == CommandType::Login || command == CommandType::GetServerList || command == CommandType::Create ||
|
||||
command == CommandType::AddFriend || command == CommandType::RemoveFriend ||
|
||||
|
@ -463,7 +680,9 @@ namespace rpcn
|
|||
}
|
||||
case PacketType::Notification:
|
||||
{
|
||||
switch (command)
|
||||
auto notif_type = static_cast<rpcn::NotificationType>(command);
|
||||
|
||||
switch (notif_type)
|
||||
{
|
||||
case NotificationType::FriendNew:
|
||||
case NotificationType::FriendLost:
|
||||
|
@ -471,7 +690,7 @@ namespace rpcn
|
|||
case NotificationType::FriendStatus:
|
||||
case NotificationType::FriendPresenceChanged:
|
||||
{
|
||||
handle_friend_notification(command, std::move(data));
|
||||
handle_friend_notification(notif_type, std::move(data));
|
||||
break;
|
||||
}
|
||||
case NotificationType::MessageReceived:
|
||||
|
@ -482,7 +701,7 @@ namespace rpcn
|
|||
default:
|
||||
{
|
||||
std::lock_guard lock(mutex_notifs);
|
||||
notifications.emplace_back(std::make_pair(command, std::move(data)));
|
||||
notifications.emplace_back(std::make_pair(notif_type, std::move(data)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -493,7 +712,7 @@ namespace rpcn
|
|||
if (data.size() != 4)
|
||||
return error_and_disconnect("Invalid size of ServerInfo packet");
|
||||
|
||||
received_version = reinterpret_cast<le_t<u32>&>(data[0]);
|
||||
received_version = reinterpret_cast<le_t<u32>&>(data[0]);
|
||||
server_info_received = true;
|
||||
break;
|
||||
}
|
||||
|
@ -623,7 +842,7 @@ namespace rpcn
|
|||
bool rpcn_client::send_packet(const std::vector<u8>& packet)
|
||||
{
|
||||
u32 num_timeouts = 0;
|
||||
usz n_sent = 0;
|
||||
usz n_sent = 0;
|
||||
while (n_sent != packet.size())
|
||||
{
|
||||
if (terminate)
|
||||
|
@ -682,7 +901,7 @@ namespace rpcn
|
|||
|
||||
// Helper functions
|
||||
|
||||
bool rpcn_client::forge_send(u16 command, u64 packet_id, const std::vector<u8>& data)
|
||||
bool rpcn_client::forge_send(rpcn::CommandType command, u64 packet_id, const std::vector<u8>& data)
|
||||
{
|
||||
// TODO: add a check for status?
|
||||
|
||||
|
@ -691,7 +910,7 @@ namespace rpcn
|
|||
return true;
|
||||
}
|
||||
|
||||
bool rpcn_client::forge_send_reply(u16 command, u64 packet_id, const std::vector<u8>& data, std::vector<u8>& reply_data)
|
||||
bool rpcn_client::forge_send_reply(rpcn::CommandType command, u64 packet_id, const std::vector<u8>& data, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (!forge_send(command, packet_id, data))
|
||||
return false;
|
||||
|
@ -738,8 +957,8 @@ namespace rpcn
|
|||
sockfd = 0;
|
||||
}
|
||||
|
||||
connected = false;
|
||||
authentified = false;
|
||||
connected = false;
|
||||
authentified = false;
|
||||
server_info_received = false;
|
||||
}
|
||||
|
||||
|
@ -811,28 +1030,63 @@ namespace rpcn
|
|||
|
||||
memset(&addr_rpcn, 0, sizeof(addr_rpcn));
|
||||
|
||||
addr_rpcn.sin_port = std::bit_cast<u16, be_t<u16>>(port); // htons
|
||||
addr_rpcn.sin_port = std::bit_cast<u16, be_t<u16>>(port); // htons
|
||||
addr_rpcn.sin_family = AF_INET;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
hostent* host_addr = gethostbyname(splithost[0].c_str());
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
if (!host_addr)
|
||||
addrinfo* addr_info{};
|
||||
|
||||
if (getaddrinfo(splithost[0].c_str(), nullptr, nullptr, &addr_info))
|
||||
{
|
||||
rpcn_log.error("connect: Failed to resolve %s", host);
|
||||
rpcn_log.error("connect: Failed to getaddrinfo %s", host);
|
||||
state = rpcn_state::failure_resolve;
|
||||
return false;
|
||||
}
|
||||
|
||||
addr_rpcn.sin_addr.s_addr = *reinterpret_cast<u32*>(host_addr->h_addr_list[0]);
|
||||
bool found_ipv4 = false, found_ipv6 = false;
|
||||
addrinfo* found = addr_info;
|
||||
|
||||
memcpy(&addr_rpcn_udp, &addr_rpcn, sizeof(addr_rpcn_udp));
|
||||
addr_rpcn_udp.sin_port = std::bit_cast<u16, be_t<u16>>(3657); // htons
|
||||
while (found != nullptr)
|
||||
{
|
||||
switch (found->ai_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
addr_rpcn.sin_addr = reinterpret_cast<sockaddr_in*>(found->ai_addr)->sin_addr;
|
||||
found_ipv4 = true;
|
||||
break;
|
||||
}
|
||||
case AF_INET6:
|
||||
{
|
||||
if (np::is_ipv6_supported())
|
||||
{
|
||||
addr_rpcn_udp_ipv6.sin6_family = AF_INET6;
|
||||
addr_rpcn_udp_ipv6.sin6_port = std::bit_cast<u16, be_t<u16>>(3657);
|
||||
addr_rpcn_udp_ipv6.sin6_addr = reinterpret_cast<sockaddr_in6*>(found->ai_addr)->sin6_addr;
|
||||
found_ipv6 = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
found = found->ai_next;
|
||||
}
|
||||
|
||||
if (!found_ipv4)
|
||||
{
|
||||
rpcn_log.error("connect: Failed to find IPv4 for %s", host);
|
||||
state = rpcn_state::failure_resolve;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (np::is_ipv6_supported() && !found_ipv6)
|
||||
{
|
||||
rpcn_log.warning("IPv6 seems supported but no IPv6 could be found for the RPCN server, IPv6 is disabled!");
|
||||
is_ipv6_supported(np::IPV6_SUPPORT::IPV6_UNSUPPORTED);
|
||||
}
|
||||
|
||||
memcpy(&addr_rpcn_udp_ipv4, &addr_rpcn, sizeof(addr_rpcn_udp_ipv4));
|
||||
addr_rpcn_udp_ipv4.sin_port = std::bit_cast<u16, be_t<u16>>(3657); // htons
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#ifdef _WIN32
|
||||
|
@ -926,10 +1180,6 @@ namespace rpcn
|
|||
}
|
||||
|
||||
rpcn_log.notice("connect: Protocol version matches");
|
||||
|
||||
last_ping_time = steady_clock::now() - 5s;
|
||||
last_pong_time = last_ping_time;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -968,10 +1218,10 @@ namespace rpcn
|
|||
}
|
||||
|
||||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
online_name = reply.get_string(false);
|
||||
avatar_url = reply.get_string(false);
|
||||
user_id = reply.get<s64>();
|
||||
avatar_url = reply.get_string(false);
|
||||
user_id = reply.get<s64>();
|
||||
|
||||
auto get_usernames_and_status = [](vec_stream& stream, std::map<std::string, friend_online_data>& friends)
|
||||
{
|
||||
|
@ -1016,15 +1266,15 @@ namespace rpcn
|
|||
get_usernames(reply, friend_infos.blocked);
|
||||
}
|
||||
|
||||
if (is_error(error))
|
||||
if (error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case LoginError: state = rpcn_state::failure_id; break;
|
||||
case LoginAlreadyLoggedIn: state = rpcn_state::failure_id_already_logged_in; break;
|
||||
case LoginInvalidUsername: state = rpcn_state::failure_id_username; break;
|
||||
case LoginInvalidPassword: state = rpcn_state::failure_id_password; break;
|
||||
case LoginInvalidToken: state = rpcn_state::failure_id_token; break;
|
||||
case rpcn::ErrorType::LoginError: state = rpcn_state::failure_id; break;
|
||||
case rpcn::ErrorType::LoginAlreadyLoggedIn: state = rpcn_state::failure_id_already_logged_in; break;
|
||||
case rpcn::ErrorType::LoginInvalidUsername: state = rpcn_state::failure_id_username; break;
|
||||
case rpcn::ErrorType::LoginInvalidPassword: state = rpcn_state::failure_id_password; break;
|
||||
case rpcn::ErrorType::LoginInvalidToken: state = rpcn_state::failure_id_token; break;
|
||||
default: state = rpcn_state::failure_id; break;
|
||||
}
|
||||
|
||||
|
@ -1056,6 +1306,15 @@ namespace rpcn
|
|||
return true;
|
||||
}
|
||||
|
||||
void rpcn_client::reset_state()
|
||||
{
|
||||
if (!connected || !authentified)
|
||||
return;
|
||||
|
||||
std::vector<u8> data;
|
||||
forge_send(CommandType::ResetState, rpcn_request_counter.fetch_add(1), data);
|
||||
}
|
||||
|
||||
ErrorType rpcn_client::create_user(std::string_view npid, std::string_view password, std::string_view online_name, std::string_view avatar_url, std::string_view email)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
|
@ -1082,14 +1341,12 @@ namespace rpcn
|
|||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
if (error == rpcn::ErrorType::NoError)
|
||||
{
|
||||
return error;
|
||||
rpcn_log.success("You have successfully created a RPCN account(%s | %s)!", npid, online_name);
|
||||
}
|
||||
|
||||
rpcn_log.success("You have successfully created a RPCN account(%s | %s)!", npid, online_name);
|
||||
|
||||
return ErrorType::NoError;
|
||||
return error;
|
||||
}
|
||||
|
||||
ErrorType rpcn_client::resend_token(const std::string& npid, const std::string& password)
|
||||
|
@ -1117,14 +1374,12 @@ namespace rpcn
|
|||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
if (error == rpcn::ErrorType::NoError)
|
||||
{
|
||||
return error;
|
||||
rpcn_log.success("Token has successfully been resent!");
|
||||
}
|
||||
|
||||
rpcn_log.success("Token has successfully been resent!");
|
||||
|
||||
return ErrorType::NoError;
|
||||
return error;
|
||||
}
|
||||
|
||||
ErrorType rpcn_client::send_reset_token(std::string_view npid, std::string_view email)
|
||||
|
@ -1152,14 +1407,12 @@ namespace rpcn
|
|||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
if (error == rpcn::ErrorType::NoError)
|
||||
{
|
||||
return error;
|
||||
rpcn_log.success("Password reset token has successfully been sent!");
|
||||
}
|
||||
|
||||
rpcn_log.success("Password reset token has successfully been sent!");
|
||||
|
||||
return ErrorType::NoError;
|
||||
return error;
|
||||
}
|
||||
|
||||
ErrorType rpcn_client::reset_password(std::string_view npid, std::string_view token, std::string_view password)
|
||||
|
@ -1189,14 +1442,12 @@ namespace rpcn
|
|||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
if (error == rpcn::ErrorType::NoError)
|
||||
{
|
||||
return error;
|
||||
rpcn_log.success("Password has successfully been reset!");
|
||||
}
|
||||
|
||||
rpcn_log.success("Password has successfully been reset!");
|
||||
|
||||
return ErrorType::NoError;
|
||||
return error;
|
||||
}
|
||||
|
||||
bool rpcn_client::add_friend(const std::string& friend_username)
|
||||
|
@ -1216,7 +1467,7 @@ namespace rpcn
|
|||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
if (error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1242,7 +1493,7 @@ namespace rpcn
|
|||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
if (error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1251,18 +1502,18 @@ namespace rpcn
|
|||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::pair<u16, std::vector<u8>>> rpcn_client::get_notifications()
|
||||
std::vector<std::pair<rpcn::NotificationType, std::vector<u8>>> rpcn_client::get_notifications()
|
||||
{
|
||||
std::lock_guard lock(mutex_notifs);
|
||||
std::vector<std::pair<u16, std::vector<u8>>> notifs = std::move(notifications);
|
||||
auto notifs = std::move(notifications);
|
||||
notifications.clear();
|
||||
return notifs;
|
||||
}
|
||||
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> rpcn_client::get_replies()
|
||||
std::unordered_map<u32, std::pair<rpcn::CommandType, std::vector<u8>>> rpcn_client::get_replies()
|
||||
{
|
||||
std::lock_guard lock(mutex_replies);
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> ret_replies = std::move(replies);
|
||||
auto ret_replies = std::move(replies);
|
||||
replies.clear();
|
||||
return ret_replies;
|
||||
}
|
||||
|
@ -1331,7 +1582,7 @@ namespace rpcn
|
|||
vec_stream reply(reply_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
if (error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1364,7 +1615,7 @@ namespace rpcn
|
|||
vec_stream reply(reply_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
if (error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1380,7 +1631,6 @@ namespace rpcn
|
|||
return network_time;
|
||||
}
|
||||
|
||||
|
||||
bool rpcn_client::get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id)
|
||||
{
|
||||
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u16));
|
||||
|
@ -1447,7 +1697,7 @@ namespace rpcn
|
|||
std::vector<flatbuffers::Offset<GroupConfig>> davec;
|
||||
for (u32 i = 0; i < req->groupConfigNum; i++)
|
||||
{
|
||||
auto bin = CreateGroupConfig(builder, req->groupConfig[i].slotNum, req->groupConfig[i].withLabel, builder.CreateVector(req->groupConfig[i].label.data, 8), req->groupConfig[i].withPassword);
|
||||
auto bin = CreateGroupConfig(builder, req->groupConfig[i].slotNum, req->groupConfig[i].withLabel ? builder.CreateVector(req->groupConfig[i].label.data, 8) : 0, req->groupConfig[i].withPassword);
|
||||
davec.push_back(bin);
|
||||
}
|
||||
final_groupconfigs_vec = builder.CreateVector(davec);
|
||||
|
@ -1549,7 +1799,7 @@ namespace rpcn
|
|||
{
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
flatbuffers::Offset<PresenceOptionData> final_optdata = CreatePresenceOptionData(builder, builder.CreateVector(req->optData.data, 16), req->optData.length);
|
||||
auto req_finished = CreateLeaveRoomRequest(builder, req->roomId, final_optdata);
|
||||
auto req_finished = CreateLeaveRoomRequest(builder, req->roomId, final_optdata);
|
||||
builder.Finish(req_finished);
|
||||
|
||||
return forge_request_with_com_id(builder, communication_id, CommandType::LeaveRoom, req_id);
|
||||
|
@ -1565,7 +1815,7 @@ namespace rpcn
|
|||
for (u32 i = 0; i < req->intFilterNum; i++)
|
||||
{
|
||||
auto int_attr = CreateIntAttr(builder, req->intFilter[i].attr.id, req->intFilter[i].attr.num);
|
||||
auto bin = CreateIntSearchFilter(builder, req->intFilter[i].searchOperator, int_attr);
|
||||
auto bin = CreateIntSearchFilter(builder, req->intFilter[i].searchOperator, int_attr);
|
||||
davec.push_back(bin);
|
||||
}
|
||||
final_intfilter_vec = builder.CreateVector(davec);
|
||||
|
@ -1577,7 +1827,7 @@ namespace rpcn
|
|||
for (u32 i = 0; i < req->binFilterNum; i++)
|
||||
{
|
||||
auto bin_attr = CreateBinAttr(builder, req->binFilter[i].attr.id, builder.CreateVector(req->binFilter[i].attr.ptr.get_ptr(), req->binFilter[i].attr.size));
|
||||
auto bin = CreateBinSearchFilter(builder, req->binFilter[i].searchOperator, bin_attr);
|
||||
auto bin = CreateBinSearchFilter(builder, req->binFilter[i].searchOperator, bin_attr);
|
||||
davec.push_back(bin);
|
||||
}
|
||||
final_binfilter_vec = builder.CreateVector(davec);
|
||||
|
@ -1892,7 +2142,7 @@ namespace rpcn
|
|||
auto fb_sendmessage = CreateSendMessageRequest(builder, nested_flatbuffer_vector, npids_vector);
|
||||
|
||||
builder.Finish(fb_sendmessage);
|
||||
const u8* buf = builder.GetBufferPointer();
|
||||
const u8* buf = builder.GetBufferPointer();
|
||||
const usz bufsize = builder.GetSize();
|
||||
std::vector<u8> data(bufsize + sizeof(u32));
|
||||
|
||||
|
@ -1963,7 +2213,7 @@ namespace rpcn
|
|||
auto req_finished = CreateRecordScoreGameDataRequest(builder, board_id, pc_id, score);
|
||||
builder.Finish(req_finished);
|
||||
|
||||
const u8* buf = builder.GetBufferPointer();
|
||||
const u8* buf = builder.GetBufferPointer();
|
||||
const usz bufsize = builder.GetSize();
|
||||
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize + sizeof(u32) + score_data.size());
|
||||
|
||||
|
@ -2385,11 +2635,7 @@ namespace rpcn
|
|||
num = cur_attr->value.num;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fmt::throw_exception("Invalid attr type reached set_room_info_gui");
|
||||
break;
|
||||
}
|
||||
default: fmt::throw_exception("Invalid attr type reached set_room_info_gui");
|
||||
}
|
||||
|
||||
auto fb_attr = CreateMatchingAttr(builder, cur_attr->type, cur_attr->id, num, fb_vec_data);
|
||||
|
@ -2468,7 +2714,7 @@ namespace rpcn
|
|||
|
||||
bool rpcn_client::forge_request_with_com_id(const flatbuffers::FlatBufferBuilder& builder, const SceNpCommunicationId& com_id, CommandType command, u64 packet_id)
|
||||
{
|
||||
const u8* buf = builder.GetBufferPointer();
|
||||
const u8* buf = builder.GetBufferPointer();
|
||||
const usz bufsize = builder.GetSize();
|
||||
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
|
||||
|
||||
|
@ -2492,13 +2738,13 @@ namespace rpcn
|
|||
return forge_send(command, packet_id, data);
|
||||
}
|
||||
|
||||
std::vector<u8> rpcn_client::forge_request(u16 command, u64 packet_id, const std::vector<u8>& data) const
|
||||
std::vector<u8> rpcn_client::forge_request(rpcn::CommandType command, u64 packet_id, const std::vector<u8>& data) const
|
||||
{
|
||||
const usz packet_size = data.size() + RPCN_HEADER_SIZE;
|
||||
|
||||
std::vector<u8> packet(packet_size);
|
||||
packet[0] = PacketType::Request;
|
||||
reinterpret_cast<le_t<u16>&>(packet[1]) = command;
|
||||
packet[0] = static_cast<u8>(PacketType::Request);
|
||||
reinterpret_cast<le_t<u16>&>(packet[1]) = static_cast<u16>(command);
|
||||
reinterpret_cast<le_t<u32>&>(packet[3]) = ::narrow<u32>(packet_size);
|
||||
reinterpret_cast<le_t<u64>&>(packet[7]) = packet_id;
|
||||
|
||||
|
@ -2601,11 +2847,10 @@ namespace rpcn
|
|||
}
|
||||
}
|
||||
|
||||
void rpcn_client::handle_friend_notification(u16 command, std::vector<u8> data)
|
||||
void rpcn_client::handle_friend_notification(rpcn::NotificationType ntype, std::vector<u8> data)
|
||||
{
|
||||
std::lock_guard lock(mutex_friends);
|
||||
|
||||
NotificationType ntype = static_cast<NotificationType>(command);
|
||||
vec_stream vdata(data);
|
||||
|
||||
const auto call_callbacks = [&](NotificationType ntype, const std::string& username, bool status)
|
||||
|
@ -2666,7 +2911,7 @@ namespace rpcn
|
|||
case NotificationType::FriendStatus: // Set status of friend to Offline or Online
|
||||
{
|
||||
const bool online = !!vdata.get<u8>();
|
||||
const u64 timestamp = vdata.get<u64>();
|
||||
const u64 timestamp = vdata.get<u64>();
|
||||
const std::string username = vdata.get_string(false);
|
||||
if (vdata.is_error())
|
||||
{
|
||||
|
@ -2740,7 +2985,7 @@ namespace rpcn
|
|||
// Unserialize the message
|
||||
vec_stream sdata(data);
|
||||
std::string sender = sdata.get_string(false);
|
||||
auto* fb_mdata = sdata.get_flatbuffer<MessageDetails>();
|
||||
auto* fb_mdata = sdata.get_flatbuffer<MessageDetails>();
|
||||
|
||||
if (sdata.is_error())
|
||||
{
|
||||
|
@ -2755,12 +3000,12 @@ namespace rpcn
|
|||
}
|
||||
|
||||
message_data mdata = {
|
||||
.msgId = message_counter,
|
||||
.mainType = fb_mdata->mainType(),
|
||||
.subType = fb_mdata->subType(),
|
||||
.msgId = message_counter,
|
||||
.mainType = fb_mdata->mainType(),
|
||||
.subType = fb_mdata->subType(),
|
||||
.msgFeatures = fb_mdata->msgFeatures(),
|
||||
.subject = fb_mdata->subject()->str(),
|
||||
.body = fb_mdata->body()->str()};
|
||||
.subject = fb_mdata->subject()->str(),
|
||||
.body = fb_mdata->body()->str()};
|
||||
|
||||
strcpy_trunc(mdata.commId.data, fb_mdata->communicationId()->str());
|
||||
mdata.data.assign(fb_mdata->data()->Data(), fb_mdata->data()->Data() + fb_mdata->data()->size());
|
||||
|
@ -2769,7 +3014,7 @@ namespace rpcn
|
|||
{
|
||||
std::lock_guard lock(mutex_messages);
|
||||
const u64 msg_id = message_counter++;
|
||||
auto id_and_msg = stx::make_shared<std::pair<std::string, message_data>>(std::make_pair(std::move(sender), std::move(mdata)));
|
||||
auto id_and_msg = stx::make_shared<std::pair<std::string, message_data>>(std::make_pair(std::move(sender), std::move(mdata)));
|
||||
messages.emplace(msg_id, id_and_msg);
|
||||
new_messages.push_back(msg_id);
|
||||
active_messages.insert(msg_id);
|
||||
|
@ -2805,7 +3050,7 @@ namespace rpcn
|
|||
for (auto id : active_messages)
|
||||
{
|
||||
const auto& entry = ::at32(messages, id);
|
||||
const auto& msg = entry->second;
|
||||
const auto& msg = entry->second;
|
||||
if (msg.mainType == type_filter && (include_bootable || !(msg.msgFeatures & SCE_NP_BASIC_MESSAGE_FEATURES_BOOTABLE)))
|
||||
{
|
||||
vec_messages.push_back(std::make_pair(id, entry));
|
||||
|
@ -2813,9 +3058,9 @@ namespace rpcn
|
|||
}
|
||||
|
||||
message_cbs.insert(message_cb_t{
|
||||
.cb_func = cb_func,
|
||||
.cb_param = cb_param,
|
||||
.type_filter = type_filter,
|
||||
.cb_func = cb_func,
|
||||
.cb_param = cb_param,
|
||||
.type_filter = type_filter,
|
||||
.inc_bootable = include_bootable,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,12 +30,15 @@
|
|||
#ifdef __clang__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wextern-c-compat"
|
||||
#endif
|
||||
#include <wolfssl/ssl.h>
|
||||
#ifdef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include "rpcn_types.h"
|
||||
|
||||
// COMID is sent as 9 chars - + '_' + 2 digits
|
||||
constexpr usz COMMUNICATION_ID_COMID_COMPONENT_SIZE = 9;
|
||||
constexpr usz COMMUNICATION_ID_SUBID_COMPONENT_SIZE = 2;
|
||||
|
@ -180,153 +183,6 @@ protected:
|
|||
|
||||
namespace rpcn
|
||||
{
|
||||
enum CommandType : u16
|
||||
{
|
||||
Login,
|
||||
Terminate,
|
||||
Create,
|
||||
SendToken,
|
||||
SendResetToken,
|
||||
ResetPassword,
|
||||
AddFriend,
|
||||
RemoveFriend,
|
||||
AddBlock,
|
||||
RemoveBlock,
|
||||
GetServerList,
|
||||
GetWorldList,
|
||||
CreateRoom,
|
||||
JoinRoom,
|
||||
LeaveRoom,
|
||||
SearchRoom,
|
||||
GetRoomDataExternalList,
|
||||
SetRoomDataExternal,
|
||||
GetRoomDataInternal,
|
||||
SetRoomDataInternal,
|
||||
GetRoomMemberDataInternal,
|
||||
SetRoomMemberDataInternal,
|
||||
SetUserInfo,
|
||||
PingRoomOwner,
|
||||
SendRoomMessage,
|
||||
RequestSignalingInfos,
|
||||
RequestTicket,
|
||||
SendMessage,
|
||||
GetBoardInfos,
|
||||
RecordScore,
|
||||
RecordScoreData,
|
||||
GetScoreData,
|
||||
GetScoreRange,
|
||||
GetScoreFriends,
|
||||
GetScoreNpid,
|
||||
GetNetworkTime,
|
||||
TusSetMultiSlotVariable,
|
||||
TusGetMultiSlotVariable,
|
||||
TusGetMultiUserVariable,
|
||||
TusGetFriendsVariable,
|
||||
TusAddAndGetVariable,
|
||||
TusTryAndSetVariable,
|
||||
TusDeleteMultiSlotVariable,
|
||||
TusSetData,
|
||||
TusGetData,
|
||||
TusGetMultiSlotDataStatus,
|
||||
TusGetMultiUserDataStatus,
|
||||
TusGetFriendsDataStatus,
|
||||
TusDeleteMultiSlotData,
|
||||
ClearPresence,
|
||||
SetPresence,
|
||||
CreateRoomGUI,
|
||||
JoinRoomGUI,
|
||||
LeaveRoomGUI,
|
||||
GetRoomListGUI,
|
||||
SetRoomSearchFlagGUI,
|
||||
GetRoomSearchFlagGUI,
|
||||
SetRoomInfoGUI,
|
||||
GetRoomInfoGUI,
|
||||
QuickMatchGUI,
|
||||
SearchJoinRoomGUI,
|
||||
};
|
||||
|
||||
enum NotificationType : u16
|
||||
{
|
||||
UserJoinedRoom,
|
||||
UserLeftRoom,
|
||||
RoomDestroyed,
|
||||
UpdatedRoomDataInternal,
|
||||
UpdatedRoomMemberDataInternal,
|
||||
SignalP2PConnect,
|
||||
_SignalP2PDisconnect,
|
||||
FriendQuery, // Other user sent a friend request
|
||||
FriendNew, // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||
FriendLost, // Remove friend from the friendlist(user removed friend or friend removed friend)
|
||||
FriendStatus, // Set status of friend to Offline or Online
|
||||
RoomMessageReceived,
|
||||
MessageReceived,
|
||||
FriendPresenceChanged,
|
||||
SignalingInfo,
|
||||
MemberJoinedRoomGUI,
|
||||
MemberLeftRoomGUI,
|
||||
RoomDisappearedGUI,
|
||||
RoomOwnerChangedGUI,
|
||||
UserKickedGUI,
|
||||
QuickMatchCompleteGUI,
|
||||
};
|
||||
|
||||
enum class rpcn_state
|
||||
{
|
||||
failure_no_failure,
|
||||
failure_input,
|
||||
failure_wolfssl,
|
||||
failure_resolve,
|
||||
failure_connect,
|
||||
failure_id,
|
||||
failure_id_already_logged_in,
|
||||
failure_id_username,
|
||||
failure_id_password,
|
||||
failure_id_token,
|
||||
failure_protocol,
|
||||
failure_other,
|
||||
};
|
||||
|
||||
enum PacketType : u8
|
||||
{
|
||||
Request,
|
||||
Reply,
|
||||
Notification,
|
||||
ServerInfo,
|
||||
};
|
||||
|
||||
enum ErrorType : u8
|
||||
{
|
||||
NoError, // No error
|
||||
Malformed, // Query was malformed, critical error that should close the connection
|
||||
Invalid, // The request type is invalid(wrong stage?)
|
||||
InvalidInput, // The Input doesn't fit the constraints of the request
|
||||
TooSoon, // Time limited operation attempted too soon
|
||||
LoginError, // An error happened related to login
|
||||
LoginAlreadyLoggedIn, // Can't log in because you're already logged in
|
||||
LoginInvalidUsername, // Invalid username
|
||||
LoginInvalidPassword, // Invalid password
|
||||
LoginInvalidToken, // Invalid token
|
||||
CreationError, // An error happened related to account creation
|
||||
CreationExistingUsername, // Specific to Account Creation: username exists already
|
||||
CreationBannedEmailProvider, // Specific to Account Creation: the email provider is banned
|
||||
CreationExistingEmail, // Specific to Account Creation: that email is already registered to an account
|
||||
RoomMissing, // User tried to join a non existing room
|
||||
RoomAlreadyJoined, // User tried to join a room he's already part of
|
||||
RoomFull, // User tried to join a full room
|
||||
Unauthorized, // User attempted an unauthorized operation
|
||||
DbFail, // Generic failure on db side
|
||||
EmailFail, // Generic failure related to email
|
||||
NotFound, // Object of the query was not found(room, user, etc)
|
||||
Blocked, // The operation can't complete because you've been blocked
|
||||
AlreadyFriend, // Can't add friend because already friend
|
||||
ScoreNotBest, // A better score is already registered for that user/character_id
|
||||
ScoreInvalid, // Score for player was found but wasn't what was expected
|
||||
ScoreHasData, // Score already has data
|
||||
CondFail, // Condition related to query failed
|
||||
Unsupported,
|
||||
__error_last
|
||||
};
|
||||
|
||||
using friend_cb_func = void (*)(void* param, NotificationType ntype, const std::string& username, bool status);
|
||||
using message_cb_func = void (*)(void* param, const shared_ptr<std::pair<std::string, message_data>> new_msg, u64 msg_id);
|
||||
|
||||
|
@ -359,7 +215,7 @@ namespace rpcn
|
|||
|
||||
localized_string_id rpcn_state_to_localized_string_id(rpcn::rpcn_state state);
|
||||
std::string rpcn_state_to_string(rpcn::rpcn_state state);
|
||||
bool is_error(ErrorType err);
|
||||
void print_error(rpcn::CommandType command, rpcn::ErrorType error);
|
||||
|
||||
class rpcn_client
|
||||
{
|
||||
|
@ -392,7 +248,7 @@ namespace rpcn
|
|||
std::set<std::pair<friend_cb_func, void*>> friend_cbs;
|
||||
friend_data friend_infos;
|
||||
|
||||
void handle_friend_notification(u16 command, std::vector<u8> data);
|
||||
void handle_friend_notification(rpcn::NotificationType ntype, std::vector<u8> data);
|
||||
|
||||
void handle_message(std::vector<u8> data);
|
||||
|
||||
|
@ -435,6 +291,7 @@ namespace rpcn
|
|||
rpcn_state wait_for_connection();
|
||||
rpcn_state wait_for_authentified();
|
||||
bool terminate_connection();
|
||||
void reset_state();
|
||||
|
||||
void get_friends(friend_data& friend_infos);
|
||||
void get_friends_and_register_cb(friend_data& friend_infos, friend_cb_func cb_func, void* cb_param);
|
||||
|
@ -454,8 +311,8 @@ namespace rpcn
|
|||
std::optional<std::pair<std::string, friend_online_data>> get_friend_presence_by_index(u32 index);
|
||||
std::optional<std::pair<std::string, friend_online_data>> get_friend_presence_by_npid(const std::string& npid);
|
||||
|
||||
std::vector<std::pair<u16, std::vector<u8>>> get_notifications();
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> get_replies();
|
||||
std::vector<std::pair<rpcn::NotificationType, std::vector<u8>>> get_notifications();
|
||||
std::unordered_map<u32, std::pair<rpcn::CommandType, std::vector<u8>>> get_replies();
|
||||
std::unordered_map<std::string, friend_online_data> get_presence_updates();
|
||||
std::map<std::string, friend_online_data> get_presence_states();
|
||||
|
||||
|
@ -537,11 +394,11 @@ namespace rpcn
|
|||
|
||||
static void write_communication_id(const SceNpCommunicationId& com_id, std::vector<u8>& data);
|
||||
|
||||
std::vector<u8> forge_request(u16 command, u64 packet_id, const std::vector<u8>& data) const;
|
||||
bool forge_send(u16 command, u64 packet_id, const std::vector<u8>& data);
|
||||
std::vector<u8> forge_request(rpcn::CommandType command, u64 packet_id, const std::vector<u8>& data) const;
|
||||
bool forge_send(rpcn::CommandType command, u64 packet_id, const std::vector<u8>& data);
|
||||
bool forge_request_with_com_id(const flatbuffers::FlatBufferBuilder& builder, const SceNpCommunicationId& com_id, CommandType command, u64 packet_id);
|
||||
bool forge_request_with_data(const flatbuffers::FlatBufferBuilder& builder, CommandType command, u64 packet_id);
|
||||
bool forge_send_reply(u16 command, u64 packet_id, const std::vector<u8>& data, std::vector<u8>& reply_data);
|
||||
bool forge_send_reply(rpcn::CommandType command, u64 packet_id, const std::vector<u8>& data, std::vector<u8>& reply_data);
|
||||
|
||||
bool error_and_disconnect(const std::string& error_mgs);
|
||||
bool error_and_disconnect_notice(const std::string& error_msg);
|
||||
|
@ -556,11 +413,9 @@ namespace rpcn
|
|||
atomic_t<bool> 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{};
|
||||
sockaddr_in addr_rpcn_udp_ipv4{};
|
||||
sockaddr_in6 addr_rpcn_udp_ipv6{};
|
||||
#ifdef _WIN32
|
||||
SOCKET sockfd = 0;
|
||||
#else
|
||||
|
@ -570,10 +425,10 @@ namespace rpcn
|
|||
atomic_t<u64> rpcn_request_counter = 0x100000001; // Counter used for commands whose result is not forwarded to NP handler(login, create, sendmessage, etc)
|
||||
|
||||
shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync, mutex_presence_updates;
|
||||
std::vector<std::pair<u16, std::vector<u8>>> notifications; // notif type / data
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> replies; // req id / (command / data)
|
||||
std::unordered_map<u64, std::pair<u16, std::vector<u8>>> replies_sync; // same but for sync replies(see handle_input())
|
||||
std::unordered_map<std::string, friend_online_data> presence_updates; // npid / presence data
|
||||
std::vector<std::pair<rpcn::NotificationType, std::vector<u8>>> notifications; // notif type / data
|
||||
std::unordered_map<u32, std::pair<rpcn::CommandType, std::vector<u8>>> replies; // req id / (command / data)
|
||||
std::unordered_map<u64, std::pair<rpcn::CommandType, std::vector<u8>>> replies_sync; // same but for sync replies(see handle_input())
|
||||
std::unordered_map<std::string, friend_online_data> presence_updates; // npid / presence data
|
||||
|
||||
// Messages
|
||||
struct message_cb_t
|
||||
|
|
|
@ -124,6 +124,11 @@ std::string cfg_rpcn::get_token() const
|
|||
return token.to_string();
|
||||
}
|
||||
|
||||
bool cfg_rpcn::get_ipv6_support() const
|
||||
{
|
||||
return ipv6_support.get();
|
||||
}
|
||||
|
||||
void cfg_rpcn::set_host(std::string_view host)
|
||||
{
|
||||
this->host.from_string(host);
|
||||
|
@ -144,6 +149,11 @@ void cfg_rpcn::set_token(std::string_view token)
|
|||
this->token.from_string(token);
|
||||
}
|
||||
|
||||
void cfg_rpcn::set_ipv6_support(bool ipv6_support)
|
||||
{
|
||||
this->ipv6_support.set(ipv6_support);
|
||||
}
|
||||
|
||||
void cfg_rpcn::set_hosts(const std::vector<std::pair<std::string, std::string>>& vec_hosts)
|
||||
{
|
||||
std::string final_string;
|
||||
|
|
|
@ -10,6 +10,7 @@ struct cfg_rpcn : cfg::node
|
|||
cfg::string password{this, "Password", ""};
|
||||
cfg::string token{this, "Token", ""};
|
||||
cfg::string hosts{this, "Hosts", "Official RPCN Server|np.rpcs3.net|||RPCN Test Server|test-np.rpcs3.net"};
|
||||
cfg::_bool ipv6_support{this, "IPv6 support", true};
|
||||
|
||||
void load();
|
||||
void save() const;
|
||||
|
@ -18,12 +19,14 @@ struct cfg_rpcn : cfg::node
|
|||
std::string get_npid(); // not const because it can save if npid is requested and it has never been set
|
||||
std::string get_password() const;
|
||||
std::string get_token() const;
|
||||
bool get_ipv6_support() const;
|
||||
std::vector<std::pair<std::string, std::string>> get_hosts(); // saves default if no valid server in the list
|
||||
|
||||
void set_host(std::string_view host);
|
||||
void set_npid(std::string_view npid);
|
||||
void set_password(std::string_view password);
|
||||
void set_token(std::string_view token);
|
||||
void set_ipv6_support(bool ipv6_support);
|
||||
bool add_host(std::string_view description, std::string_view host);
|
||||
bool del_host(std::string_view description, std::string_view host);
|
||||
|
||||
|
|
156
rpcs3/Emu/NP/rpcn_types.h
Normal file
156
rpcs3/Emu/NP/rpcn_types.h
Normal file
|
@ -0,0 +1,156 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/types.hpp"
|
||||
|
||||
namespace rpcn
|
||||
{
|
||||
enum class CommandType : u16
|
||||
{
|
||||
Login,
|
||||
Terminate,
|
||||
Create,
|
||||
SendToken,
|
||||
SendResetToken,
|
||||
ResetPassword,
|
||||
ResetState,
|
||||
AddFriend,
|
||||
RemoveFriend,
|
||||
AddBlock,
|
||||
RemoveBlock,
|
||||
GetServerList,
|
||||
GetWorldList,
|
||||
CreateRoom,
|
||||
JoinRoom,
|
||||
LeaveRoom,
|
||||
SearchRoom,
|
||||
GetRoomDataExternalList,
|
||||
SetRoomDataExternal,
|
||||
GetRoomDataInternal,
|
||||
SetRoomDataInternal,
|
||||
GetRoomMemberDataInternal,
|
||||
SetRoomMemberDataInternal,
|
||||
SetUserInfo,
|
||||
PingRoomOwner,
|
||||
SendRoomMessage,
|
||||
RequestSignalingInfos,
|
||||
RequestTicket,
|
||||
SendMessage,
|
||||
GetBoardInfos,
|
||||
RecordScore,
|
||||
RecordScoreData,
|
||||
GetScoreData,
|
||||
GetScoreRange,
|
||||
GetScoreFriends,
|
||||
GetScoreNpid,
|
||||
GetNetworkTime,
|
||||
TusSetMultiSlotVariable,
|
||||
TusGetMultiSlotVariable,
|
||||
TusGetMultiUserVariable,
|
||||
TusGetFriendsVariable,
|
||||
TusAddAndGetVariable,
|
||||
TusTryAndSetVariable,
|
||||
TusDeleteMultiSlotVariable,
|
||||
TusSetData,
|
||||
TusGetData,
|
||||
TusGetMultiSlotDataStatus,
|
||||
TusGetMultiUserDataStatus,
|
||||
TusGetFriendsDataStatus,
|
||||
TusDeleteMultiSlotData,
|
||||
SetPresence,
|
||||
CreateRoomGUI,
|
||||
JoinRoomGUI,
|
||||
LeaveRoomGUI,
|
||||
GetRoomListGUI,
|
||||
SetRoomSearchFlagGUI,
|
||||
GetRoomSearchFlagGUI,
|
||||
SetRoomInfoGUI,
|
||||
GetRoomInfoGUI,
|
||||
QuickMatchGUI,
|
||||
SearchJoinRoomGUI,
|
||||
};
|
||||
|
||||
enum class NotificationType : u16
|
||||
{
|
||||
UserJoinedRoom,
|
||||
UserLeftRoom,
|
||||
RoomDestroyed,
|
||||
UpdatedRoomDataInternal,
|
||||
UpdatedRoomMemberDataInternal,
|
||||
FriendQuery, // Other user sent a friend request
|
||||
FriendNew, // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||
FriendLost, // Remove friend from the friendlist(user removed friend or friend removed friend)
|
||||
FriendStatus, // Set status of friend to Offline or Online
|
||||
RoomMessageReceived,
|
||||
MessageReceived,
|
||||
FriendPresenceChanged,
|
||||
SignalingHelper,
|
||||
MemberJoinedRoomGUI,
|
||||
MemberLeftRoomGUI,
|
||||
RoomDisappearedGUI,
|
||||
RoomOwnerChangedGUI,
|
||||
UserKickedGUI,
|
||||
QuickMatchCompleteGUI,
|
||||
};
|
||||
|
||||
enum class rpcn_state
|
||||
{
|
||||
failure_no_failure,
|
||||
failure_input,
|
||||
failure_wolfssl,
|
||||
failure_resolve,
|
||||
failure_connect,
|
||||
failure_id,
|
||||
failure_id_already_logged_in,
|
||||
failure_id_username,
|
||||
failure_id_password,
|
||||
failure_id_token,
|
||||
failure_protocol,
|
||||
failure_other,
|
||||
};
|
||||
|
||||
enum class PacketType : u8
|
||||
{
|
||||
Request,
|
||||
Reply,
|
||||
Notification,
|
||||
ServerInfo,
|
||||
};
|
||||
|
||||
enum class ErrorType : u8
|
||||
{
|
||||
NoError, // No error
|
||||
Malformed, // Query was malformed, critical error that should close the connection
|
||||
Invalid, // The request type is invalid(wrong stage?)
|
||||
InvalidInput, // The Input doesn't fit the constraints of the request
|
||||
TooSoon, // Time limited operation attempted too soon
|
||||
LoginError, // An error happened related to login
|
||||
LoginAlreadyLoggedIn, // Can't log in because you're already logged in
|
||||
LoginInvalidUsername, // Invalid username
|
||||
LoginInvalidPassword, // Invalid password
|
||||
LoginInvalidToken, // Invalid token
|
||||
CreationError, // An error happened related to account creation
|
||||
CreationExistingUsername, // Specific to Account Creation: username exists already
|
||||
CreationBannedEmailProvider, // Specific to Account Creation: the email provider is banned
|
||||
CreationExistingEmail, // Specific to Account Creation: that email is already registered to an account
|
||||
RoomMissing, // User tried to interact with a non existing room
|
||||
RoomAlreadyJoined, // User tried to join a room he's already part of
|
||||
RoomFull, // User tried to join a full room
|
||||
RoomPasswordMismatch, // Room password didn't match
|
||||
RoomPasswordMissing, // A password was missing during room creation
|
||||
RoomGroupNoJoinLabel, // Tried to join a group room without a label
|
||||
RoomGroupFull, // Room group is full
|
||||
RoomGroupJoinLabelNotFound, // Join label was invalid in some way
|
||||
RoomGroupMaxSlotMismatch, // Mismatch between max_slot and the listed slots in groups
|
||||
Unauthorized, // User attempted an unauthorized operation
|
||||
DbFail, // Generic failure on db side
|
||||
EmailFail, // Generic failure related to email
|
||||
NotFound, // Object of the query was not found(user, etc), use RoomMissing for rooms instead
|
||||
Blocked, // The operation can't complete because you've been blocked
|
||||
AlreadyFriend, // Can't add friend because already friend
|
||||
ScoreNotBest, // A better score is already registered for that user/character_id
|
||||
ScoreInvalid, // Score for player was found but wasn't what was expected
|
||||
ScoreHasData, // Score already has data
|
||||
CondFail, // Condition related to query failed
|
||||
Unsupported,
|
||||
};
|
||||
} // namespace rpcn
|
|
@ -1,3 +1,4 @@
|
|||
#include "Emu/NP/ip_address.h"
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUCallback.h"
|
||||
#include "signaling_handler.h"
|
||||
|
@ -547,6 +548,13 @@ void signaling_handler::update_si_mapped_addr(std::shared_ptr<signaling_info>& s
|
|||
{
|
||||
ensure(si);
|
||||
|
||||
// If the address given to us by op is a translation IP, just replace it with our public ip(v4)
|
||||
if (np::is_ipv6_supported() && np::ip_address_translator::is_ipv6(new_addr))
|
||||
{
|
||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||
new_addr = nph.get_public_ip_addr();
|
||||
}
|
||||
|
||||
if (si->mapped_addr != new_addr || si->mapped_port != new_port)
|
||||
{
|
||||
if (sign_log.trace)
|
||||
|
@ -640,7 +648,15 @@ void signaling_handler::send_signaling_packet(signaling_packet& sp, u32 addr, u1
|
|||
|
||||
sign_log.trace("Sending %s packet to %s:%d", sp.command, ip_str, port);
|
||||
|
||||
if (send_packet_from_p2p_port(packet, dest) == -1)
|
||||
if (np::is_ipv6_supported() && np::ip_address_translator::is_ipv6(dest.sin_addr.s_addr))
|
||||
{
|
||||
auto& translator = g_fxo->get<np::ip_address_translator>();
|
||||
const auto addr6 = translator.get_ipv6_sockaddr(dest.sin_addr.s_addr, dest.sin_port);
|
||||
|
||||
if (!send_packet_from_p2p_port_ipv6(packet, addr6))
|
||||
sign_log.error("Failed to send signaling packet to %s:%d", ip_str, port);
|
||||
}
|
||||
else if (!send_packet_from_p2p_port_ipv4(packet, dest))
|
||||
{
|
||||
sign_log.error("Failed to send signaling packet to %s:%d", ip_str, port);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
#include "Emu/Cell/lv2/sys_net/nt_p2p_port.h"
|
||||
|
||||
s32 send_packet_from_p2p_port(const std::vector<u8>& data, const sockaddr_in& addr);
|
||||
bool send_packet_from_p2p_port_ipv4(const std::vector<u8>& data, const sockaddr_in& addr);
|
||||
bool send_packet_from_p2p_port_ipv6(const std::vector<u8>& data, const sockaddr_in6& addr);
|
||||
std::vector<signaling_message> get_sign_msgs();
|
||||
std::vector<std::vector<u8>> get_rpcn_msgs();
|
||||
|
||||
|
|
|
@ -383,7 +383,7 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
void sendmessage_dialog::callback_handler(u16 ntype, const std::string& username, bool status)
|
||||
void sendmessage_dialog::callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace rsx
|
|||
compiled_resource get_compiled() override;
|
||||
|
||||
error_code Exec(message_data& msg_data, std::set<std::string>& npids) override;
|
||||
void callback_handler(u16 ntype, const std::string& username, bool status) override;
|
||||
void callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ enum class np_internet_status
|
|||
enabled,
|
||||
};
|
||||
|
||||
enum np_psn_status
|
||||
enum class np_psn_status
|
||||
{
|
||||
disabled,
|
||||
psn_fake,
|
||||
|
|
|
@ -175,6 +175,7 @@
|
|||
<ClCompile Include="Emu\NP\signaling_handler.cpp" />
|
||||
<ClCompile Include="Emu\NP\np_structs_extra.cpp" />
|
||||
<ClCompile Include="Emu\NP\rpcn_client.cpp" />
|
||||
<ClCompile Include="Emu\NP\ip_address.cpp" />
|
||||
<ClCompile Include="Emu\vfs_config.cpp" />
|
||||
<ClCompile Include="Loader\disc.cpp" />
|
||||
<ClCompile Include="util\serialization_ext.cpp">
|
||||
|
@ -618,6 +619,7 @@
|
|||
<ClInclude Include="Emu\NP\np_structs_extra.h" />
|
||||
<ClInclude Include="Emu\NP\rpcn_client.h" />
|
||||
<ClInclude Include="Emu\NP\rpcn_config.h" />
|
||||
<ClInclude Include="Emu\NP\ip_address.h" />
|
||||
<ClInclude Include="Emu\perf_monitor.hpp" />
|
||||
<ClInclude Include="Emu\RSX\color_utils.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\bitfield.hpp" />
|
||||
|
|
|
@ -1029,6 +1029,9 @@
|
|||
<ClCompile Include="Emu\NP\rpcn_client.cpp">
|
||||
<Filter>Emu\NP</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\NP\ip_address.cpp">
|
||||
<Filter>Emu\NP</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\NP\rpcn_config.cpp">
|
||||
<Filter>Emu\NP</Filter>
|
||||
</ClCompile>
|
||||
|
@ -2683,6 +2686,9 @@
|
|||
<ClInclude Include="Emu\NP\np_gui_cache.h">
|
||||
<Filter>Emu\NP</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\NP\ip_address.h">
|
||||
<Filter>Emu\NP</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Core\RSXDrawCommands.h">
|
||||
<Filter>Emu\GPU\RSX\Core</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
#include <QGroupBox>
|
||||
#include <QMenu>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
#include "qt_utils.h"
|
||||
|
||||
#include "rpcn_settings_dialog.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/NP/rpcn_config.h"
|
||||
#include "Emu/NP/ip_address.h"
|
||||
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/openssl/evp.h>
|
||||
|
@ -160,6 +162,9 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
|||
QPushButton* btn_test = new QPushButton(tr("Test Account"));
|
||||
QLabel* label_npid = new QLabel();
|
||||
|
||||
QCheckBox* checkbox_disable_ipv6 = new QCheckBox("Disable IPv6");
|
||||
checkbox_disable_ipv6->setCheckState(g_cfg_rpcn.get_ipv6_support() ? Qt::Unchecked : Qt::Checked);
|
||||
|
||||
const auto update_npid_label = [label_npid]()
|
||||
{
|
||||
const std::string npid = g_cfg_rpcn.get_npid();
|
||||
|
@ -178,6 +183,7 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
|||
grp_buttons->setLayout(vbox_buttons);
|
||||
|
||||
vbox_global->addWidget(grp_buttons);
|
||||
vbox_global->addWidget(checkbox_disable_ipv6);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
|
@ -193,6 +199,10 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
|||
|
||||
g_cfg_rpcn.set_host(host.toString().toStdString());
|
||||
g_cfg_rpcn.save();
|
||||
|
||||
// Resets the state in case the support was limited by the RPCN server
|
||||
if (!np::is_ipv6_supported())
|
||||
np::is_ipv6_supported(np::IPV6_SUPPORT::IPV6_UNKNOWN);
|
||||
});
|
||||
|
||||
connect(btn_add_server, &QAbstractButton::clicked, this, [this]()
|
||||
|
@ -333,6 +343,12 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
|||
|
||||
QMessageBox::information(this, tr("RPCN Account Valid!"), tr("Your account is valid!"), QMessageBox::Ok);
|
||||
});
|
||||
|
||||
connect(checkbox_disable_ipv6, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state)
|
||||
{
|
||||
g_cfg_rpcn.set_ipv6_support(state == Qt::Unchecked);
|
||||
g_cfg_rpcn.save();
|
||||
});
|
||||
}
|
||||
|
||||
void rpcn_account_dialog::refresh_combobox()
|
||||
|
|
|
@ -156,7 +156,7 @@ void sendmessage_dialog_frame::slot_remove_friend(QString name)
|
|||
remove_friend(m_lst_friends, name);
|
||||
}
|
||||
|
||||
void sendmessage_dialog_frame::callback_handler(u16 ntype, const std::string& username, bool status)
|
||||
void sendmessage_dialog_frame::callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||
{
|
||||
QString qtr_username = QString::fromStdString(username);
|
||||
switch (ntype)
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
sendmessage_dialog_frame() = default;
|
||||
~sendmessage_dialog_frame();
|
||||
error_code Exec(message_data& msg_data, std::set<std::string>& npids) override;
|
||||
void callback_handler(u16 ntype, const std::string& username, bool status) override;
|
||||
void callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status) override;
|
||||
|
||||
private:
|
||||
void add_friend(QListWidget* list, const QString& name);
|
||||
|
|
Loading…
Add table
Reference in a new issue