Compare commits

..

2 Commits

Author SHA1 Message Date
Smile Yik
b44f03ba58 Delete .room_post_office.h.kate-swp 2022-11-11 16:34:39 +08:00
Smile Yik
02e24d0211 network: play together in different room
change with suggested change
2022-11-09 09:41:20 +08:00
15 changed files with 436 additions and 48 deletions

View File

@@ -151,7 +151,6 @@ void UpdateRescalingInfo() {
ASSERT(false);
info.up_scale = 1;
info.down_shift = 0;
break;
}
info.up_factor = static_cast<f32>(info.up_scale) / (1U << info.down_shift);
info.down_factor = static_cast<f32>(1U << info.down_shift) / info.up_scale;

View File

@@ -27,12 +27,16 @@ namespace Kernel {
SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
ServiceThreadType thread_type)
: kernel{kernel_}, service_thread{thread_type == ServiceThreadType::CreateNew
? kernel.CreateServiceThread(service_name_)
: kernel.GetDefaultServiceThread()} {}
: kernel{kernel_} {
if (thread_type == ServiceThreadType::CreateNew) {
service_thread = kernel.CreateServiceThread(service_name_);
} else {
service_thread = kernel.GetDefaultServiceThread();
}
}
SessionRequestHandler::~SessionRequestHandler() {
kernel.ReleaseServiceThread(service_thread);
kernel.ReleaseServiceThread(service_thread.lock());
}
void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
@@ -45,7 +49,7 @@ void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
void SessionRequestHandler::RegisterSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager) {
manager->SetSessionHandler(shared_from_this());
service_thread.RegisterServerSession(server_session, manager);
service_thread.lock()->RegisterServerSession(server_session, manager);
server_session->Close();
}

View File

@@ -82,13 +82,13 @@ public:
void RegisterSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager);
ServiceThread& GetServiceThread() const {
std::weak_ptr<ServiceThread> GetServiceThread() const {
return service_thread;
}
protected:
KernelCore& kernel;
ServiceThread& service_thread;
std::weak_ptr<ServiceThread> service_thread;
};
using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>;
@@ -154,7 +154,7 @@ public:
session_handler = std::move(handler);
}
ServiceThread& GetServiceThread() const {
std::weak_ptr<ServiceThread> GetServiceThread() const {
return session_handler->GetServiceThread();
}

View File

@@ -384,8 +384,7 @@ void KScheduler::SwitchThread(KThread* next_thread) {
void KScheduler::ScheduleImpl() {
// First, clear the needs scheduling bool.
m_state.needs_scheduling.store(false, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
m_state.needs_scheduling.store(false, std::memory_order_seq_cst);
// Load the appropriate thread pointers for scheduling.
KThread* const cur_thread{GetCurrentThreadPointer(kernel)};
@@ -401,8 +400,7 @@ void KScheduler::ScheduleImpl() {
// If there aren't, we want to check if the highest priority thread is the same as the current
// thread.
if (highest_priority_thread == cur_thread) {
// If they're the same, then we can just issue a memory barrier and return.
std::atomic_thread_fence(std::memory_order_seq_cst);
// If they're the same, then we can just return.
return;
}
@@ -478,8 +476,7 @@ void KScheduler::ScheduleImplFiber() {
// We failed to successfully do the context switch, and need to retry.
// Clear needs_scheduling.
m_state.needs_scheduling.store(false, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
m_state.needs_scheduling.store(false, std::memory_order_seq_cst);
// Refresh the highest priority thread.
highest_priority_thread = m_state.highest_priority_thread;

View File

@@ -60,9 +60,6 @@ public:
// Release an instance of the lock.
if ((--lock_count) == 0) {
// Perform a memory barrier here.
std::atomic_thread_fence(std::memory_order_seq_cst);
// We're no longer going to hold the lock. Take note of what cores need scheduling.
const u64 cores_needing_scheduling =
SchedulerType::UpdateHighestPriorityThreads(kernel);

View File

@@ -93,7 +93,7 @@ struct KernelCore::Impl {
RegisterHostThread();
default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread");
}
void InitializeCores() {
@@ -779,31 +779,33 @@ struct KernelCore::Impl {
search->second(system.ServiceManager(), server_port);
}
Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) {
auto* ptr = new ServiceThread(kernel, name);
std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel,
const std::string& name) {
auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, name);
service_threads_manager.QueueWork(
[this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); });
[this, service_thread]() { service_threads.emplace(service_thread); });
return *ptr;
return service_thread;
}
void ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
auto* ptr = &service_thread;
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
if (auto strong_ptr = service_thread.lock()) {
if (strong_ptr == default_service_thread.lock()) {
// Nothing to do here, the service is using default_service_thread, which will be
// released on shutdown.
return;
}
if (ptr == default_service_thread) {
// Nothing to do here, the service is using default_service_thread, which will be
// released on shutdown.
return;
service_threads_manager.QueueWork(
[this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); });
}
service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
}
void ClearServiceThreads() {
service_threads_manager.QueueWork([this] {
service_threads.clear();
default_service_thread = nullptr;
default_service_thread.reset();
service_thread_barrier.Sync();
});
service_thread_barrier.Sync();
@@ -879,8 +881,8 @@ struct KernelCore::Impl {
std::unique_ptr<KMemoryLayout> memory_layout;
// Threads used for services
std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads;
ServiceThread* default_service_thread{};
std::unordered_set<std::shared_ptr<ServiceThread>> service_threads;
std::weak_ptr<ServiceThread> default_service_thread;
Common::ThreadWorker service_threads_manager;
Common::Barrier service_thread_barrier;
@@ -1237,15 +1239,15 @@ void KernelCore::ExitSVCProfile() {
MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
}
Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) {
std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
return impl->CreateServiceThread(*this, name);
}
Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const {
return *impl->default_service_thread;
std::weak_ptr<Kernel::ServiceThread> KernelCore::GetDefaultServiceThread() const {
return impl->default_service_thread;
}
void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
impl->ReleaseServiceThread(service_thread);
}

View File

@@ -309,24 +309,24 @@ public:
* See GetDefaultServiceThread.
* @param name String name for the ServerSession creating this thread, used for debug
* purposes.
* @returns A reference to the newly created service thread.
* @returns The a weak pointer newly created service thread.
*/
Kernel::ServiceThread& CreateServiceThread(const std::string& name);
std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name);
/**
* Gets the default host service thread, which executes HLE service requests. Unless service
* requests need to block on the host, the default service thread should be used in favor of
* creating a new service thread.
* @returns A reference to the default service thread.
* @returns The a weak pointer for the default service thread.
*/
Kernel::ServiceThread& GetDefaultServiceThread() const;
std::weak_ptr<Kernel::ServiceThread> GetDefaultServiceThread() const;
/**
* Releases a HLE service thread, instructing KernelCore to free it. This should be called when
* the ServerSession associated with the thread is destroyed.
* @param service_thread Service thread to release.
*/
void ReleaseServiceThread(Kernel::ServiceThread& service_thread);
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread);
/// Workaround for single-core mode when preempting threads while idle.
bool IsPhantomModeForSingleCore() const;

View File

@@ -61,7 +61,10 @@ static void PrintHelp(const char* argv0) {
"--log-file The file for storing the room log\n"
"--enable-yuzu-mods Allow yuzu Community Moderators to moderate on your room\n"
"-h, --help Display this help and exit\n"
"-v, --version Output version information and exit\n",
"-v, --version Output version information and exit\n"
"--room-post-office Open server as a room post office\n"
"--room-post-host Room post office host\n"
"--room-post-port Room post office port\n",
argv0);
}
@@ -180,6 +183,34 @@ static void InitializeLogging(const std::string& log_file) {
Common::Log::Start();
}
static int RunRoomPostOffice(Common::DetachedTasks& detached_tasks, u32 port) {
if (port > UINT16_MAX) {
LOG_ERROR(Network, "Port needs to be in the range 0 - 65535!");
return -1;
}
Network::RoomNetwork network{};
network.Init();
if (auto post_office = network.GetRoomPostOffice().lock()) {
if (!post_office->Create("", port)) {
LOG_INFO(Network, "Failed to create room post office: ");
return -1;
}
LOG_INFO(Network, "Room post office is open. Close with Q+Enter...");
while (true) {
std::string in;
std::cin >> in;
if (in.size() > 0) {
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
network.Shutdown();
detached_tasks.WaitForAllTasks();
return 0;
}
/// Application entry point
int main(int argc, char** argv) {
Common::DetachedTasks detached_tasks;
@@ -195,10 +226,13 @@ int main(int argc, char** argv) {
std::string web_api_url;
std::string ban_list_file;
std::string log_file = "yuzu-room.log";
std::string room_post_host = "127.0.0.1";
u64 preferred_game_id = 0;
u32 port = Network::DefaultRoomPort;
u32 room_post_port = Network::DefaultRoomPort;
u32 max_members = 16;
bool enable_yuzu_mods = false;
bool room_post_office = false;
static struct option long_options[] = {
{"room-name", required_argument, 0, 'n'},
@@ -216,6 +250,9 @@ int main(int argc, char** argv) {
{"enable-yuzu-mods", no_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{"room-post-office", no_argument, 0, 'c'},
{"room-post-host", required_argument, 0, 'f'},
{"room-post-port", required_argument, 0, 'j'},
{0, 0, 0, 0},
};
@@ -270,10 +307,23 @@ int main(int argc, char** argv) {
case 'v':
PrintVersion();
return 0;
case 'c':
room_post_office = true;
break;
case 'f':
room_post_host.assign(optarg);
break;
case 'j':
room_post_port = strtoul(optarg, &endarg, 0);
break;
}
}
}
if (room_post_office) {
return RunRoomPostOffice(detached_tasks, room_post_port);
}
if (room_name.empty()) {
LOG_ERROR(Network, "Room name is empty!");
PrintHelp(argv[0]);
@@ -353,6 +403,10 @@ int main(int argc, char** argv) {
verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
}
if (!room_post_host.empty()) {
room_post_office = true;
}
Network::RoomNetwork network{};
network.Init();
if (auto room = network.GetRoom().lock()) {
@@ -369,6 +423,9 @@ int main(int argc, char** argv) {
if (announce) {
announce_session->Start();
}
if (room_post_office && !room->HasMailBox()) {
room->SetupMailBox(room_post_host, room_post_port);
}
while (room->GetState() == Network::Room::State::Open) {
std::string in;
std::cin >> in;

View File

@@ -14,6 +14,8 @@ add_library(network STATIC
room_member.h
verify_user.cpp
verify_user.h
room_post_office.cpp
room_post_office.h
)
create_target_directory_groups(network)

View File

@@ -11,6 +11,7 @@ namespace Network {
RoomNetwork::RoomNetwork() {
m_room = std::make_shared<Room>();
m_room_member = std::make_shared<RoomMember>();
m_room_post_office = std::make_shared<RoomPostOffice>();
}
bool RoomNetwork::Init() {
@@ -20,10 +21,15 @@ bool RoomNetwork::Init() {
}
m_room = std::make_shared<Room>();
m_room_member = std::make_shared<RoomMember>();
m_room_post_office = std::make_shared<RoomPostOffice>();
LOG_DEBUG(Network, "initialized OK");
return true;
}
std::weak_ptr<RoomPostOffice> RoomNetwork::GetRoomPostOffice() {
return m_room_post_office;
}
std::weak_ptr<Room> RoomNetwork::GetRoom() {
return m_room;
}
@@ -43,6 +49,12 @@ void RoomNetwork::Shutdown() {
m_room->Destroy();
m_room.reset();
}
if (m_room_post_office) {
if (m_room_post_office->GetState() == RoomPostOffice::State::Open) {
m_room_post_office->Destroy();
}
m_room_post_office.reset();
}
enet_deinitialize();
LOG_DEBUG(Network, "shutdown OK");
}

View File

@@ -6,6 +6,7 @@
#include <memory>
#include "network/room.h"
#include "network/room_member.h"
#include "network/room_post_office.h"
namespace Network {
@@ -16,6 +17,9 @@ public:
/// Initializes and registers the network device, the room, and the room member.
bool Init();
/// Returns a pointer to the room post office handle
std::weak_ptr<RoomPostOffice> GetRoomPostOffice();
/// Returns a pointer to the room handle
std::weak_ptr<Room> GetRoom();
@@ -26,8 +30,9 @@ public:
void Shutdown();
private:
std::shared_ptr<RoomMember> m_room_member; ///< RoomMember (Client) for network games
std::shared_ptr<Room> m_room; ///< Room (Server) for network games
std::shared_ptr<RoomMember> m_room_member; ///< RoomMember (Client) for network games
std::shared_ptr<Room> m_room; ///< Room (Server) for network games
std::shared_ptr<RoomPostOffice> m_room_post_office; ///< Room (Relay Server) for rooms
};
} // namespace Network

View File

@@ -48,6 +48,15 @@ public:
IPBanList ip_ban_list; ///< List of banned IP addresses
mutable std::mutex ban_list_mutex; ///< Mutex for the ban lists
struct PostOffice {
static constexpr u8 WaitPacket = 10; ///< Wait post office's reply max times.
ENetPeer* peer = nullptr; ///< post office's peer
std::string address; ///< post office's address. Will skip if this is empty.
u16 port; ///< post office's port
u8 wait = 0; ///< Wait post office's reply times.
};
PostOffice post_office;
RoomImpl() : random_gen(std::random_device()()) {}
/// Thread that receives and dispatches network packets
@@ -234,6 +243,26 @@ public:
* to all other clients.
*/
void HandleClientDisconnection(ENetPeer* client);
/**
* Post recived packet to room post office.
*/
void HandlePostMail(const ENetEvent* event);
/**
* Check connection between this and room post office.
*/
void HandlePostOfficeConnection(const ENetEvent* event);
/**
* Connect to room post office.
*/
bool ConnectPostOffice();
/**
* Disconnect room post office
*/
void DisconnectPostOffice();
};
// RoomImpl
@@ -251,9 +280,11 @@ void Room::RoomImpl::ServerLoop() {
HandleGameInfoPacket(&event);
break;
case IdProxyPacket:
HandlePostMail(&event);
HandleProxyPacket(&event);
break;
case IdLdnPacket:
HandlePostMail(&event);
HandleLdnPacket(&event);
break;
case IdChatMessage:
@@ -283,9 +314,11 @@ void Room::RoomImpl::ServerLoop() {
break;
}
}
HandlePostOfficeConnection(&event);
}
// Close the connection to all members:
SendCloseMessage();
DisconnectPostOffice();
}
void Room::RoomImpl::StartLoop() {
@@ -859,7 +892,7 @@ void Room::RoomImpl::HandleProxyPacket(const ENetEvent* event) {
if (member != members.end()) {
enet_peer_send(member->peer, 0, enet_packet);
} else {
LOG_ERROR(Network,
LOG_DEBUG(Network,
"Attempting to send to unknown IP address: "
"{}.{}.{}.{}",
destination_address[0], destination_address[1], destination_address[2],
@@ -913,7 +946,7 @@ void Room::RoomImpl::HandleLdnPacket(const ENetEvent* event) {
if (member != members.end()) {
enet_peer_send(member->peer, 0, enet_packet);
} else {
LOG_ERROR(Network,
LOG_DEBUG(Network,
"Attempting to send to unknown IP address: "
"{}.{}.{}.{}",
destination_address[0], destination_address[1], destination_address[2],
@@ -1037,6 +1070,68 @@ void Room::RoomImpl::HandleClientDisconnection(ENetPeer* client) {
BroadcastRoomInformation();
}
void Room::RoomImpl::HandlePostMail(const ENetEvent* event) {
if (!post_office.peer) {
ConnectPostOffice();
}
Packet out_packet;
out_packet.Append(event->packet->data, event->packet->dataLength);
ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(),
ENET_PACKET_FLAG_RELIABLE);
if (post_office.peer && event->peer != post_office.peer) {
enet_peer_send(post_office.peer, 0, enet_packet);
}
}
bool Room::RoomImpl::ConnectPostOffice() {
if (post_office.address.empty()) {
return false;
}
LOG_INFO(Network, "Try to Connecting room post office {}:{} ...", post_office.address,
post_office.port);
ENetAddress address{};
enet_address_set_host(&address, post_office.address.c_str());
address.port = post_office.port;
post_office.peer = enet_host_connect(server, &address, NumChannels, 0);
if (!post_office.peer) {
LOG_ERROR(Network, "Connect to room post office {}:{} failed!", post_office.address,
post_office.port);
return false;
}
post_office.wait = post_office.WaitPacket - 1;
return true;
}
void Room::RoomImpl::DisconnectPostOffice() {
post_office.address.clear();
if (post_office.peer) {
enet_peer_disconnect(post_office.peer, 0);
post_office.peer = nullptr;
}
}
void Room::RoomImpl::HandlePostOfficeConnection(const ENetEvent* event) {
if (post_office.address.empty() || post_office.wait == post_office.WaitPacket) {
return;
} else if (event->peer == post_office.peer) {
post_office.wait = post_office.WaitPacket;
LOG_INFO(Network, "Connect to room post office {}:{} success!", post_office.address,
post_office.port);
return;
}
--post_office.wait;
if (post_office.wait == 0) {
post_office.wait = 0xFF;
LOG_ERROR(Network, "Room post office {}:{} have not response!", post_office.address,
post_office.port);
} else if (post_office.wait == post_office.WaitPacket + 1) {
ConnectPostOffice();
}
}
// Room
Room::Room() : room_impl{std::make_unique<RoomImpl>()} {}
@@ -1140,4 +1235,15 @@ void Room::Destroy() {
room_impl->room_information.name.clear();
}
bool Room::SetupMailBox(std::string server_address, u16 server_port) {
room_impl->post_office.address = std::move(server_address);
room_impl->post_office.port = server_port;
return room_impl->ConnectPostOffice();
}
bool Room::HasMailBox() const {
return room_impl->post_office.peer;
}
} // namespace Network

View File

@@ -140,6 +140,16 @@ public:
*/
void Destroy();
/**
* Config post office room's address and port, and connect it.
*/
bool SetupMailBox(std::string server_address, u16 server_port);
/**
* Checks this room should send packets to post office room or not.
*/
bool HasMailBox() const;
private:
class RoomImpl;
std::unique_ptr<RoomImpl> room_impl;

View File

@@ -0,0 +1,157 @@
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <thread>
#include <vector>
#include <enet/enet.h>
#include "common/logging/log.h"
#include "network/room.h"
#include "network/room_post_office.h"
namespace Network {
class RoomPostOffice::RoomPostOfficeImpl {
public:
ENetHost* server = nullptr;
/// Thread that receives and dispatches network packets
std::unique_ptr<std::thread> room_center_thread;
std::atomic<State> state{State::Closed};
class Mailbox {
public:
ENetPeer* peer; ///< the remote room's peer
};
using MailboxList = std::vector<Mailbox>;
/// remote rooms
MailboxList mailboxes;
RoomPostOfficeImpl() = default;
/// Thread function that will receive and dispatch messages until the room is destroyed.
void ServerLoop();
void StartLoop();
/**
* Handle client disconnection.
*/
void HandleClientDisconnection(const ENetPeer* peer);
/**
* Handle mail.
*/
void HandleMail(const ENetEvent* event);
/**
* Handle the room joined room post office.
*/
void HandleJoinMailbox(const ENetEvent* event);
};
RoomPostOffice::RoomPostOffice() : room_post_office_impl{std::make_unique<RoomPostOfficeImpl>()} {}
RoomPostOffice::~RoomPostOffice() = default;
void RoomPostOffice::RoomPostOfficeImpl::ServerLoop() {
while (state != State::Closed) {
ENetEvent event;
if (enet_host_service(server, &event, 5) > 0) {
switch (event.type) {
case ENET_EVENT_TYPE_RECEIVE:
HandleMail(&event);
break;
case ENET_EVENT_TYPE_DISCONNECT:
HandleClientDisconnection(event.peer);
break;
case ENET_EVENT_TYPE_NONE:
break;
case ENET_EVENT_TYPE_CONNECT:
HandleJoinMailbox(&event);
break;
}
}
}
for (const Mailbox& mailbox : mailboxes) {
if (mailbox.peer) {
enet_peer_disconnect(mailbox.peer, 0);
}
}
}
bool RoomPostOffice::Create(const std::string& server_address, u16 server_port) {
ENetAddress address;
address.host = ENET_HOST_ANY;
if (!server_address.empty()) {
enet_address_set_host(&address, server_address.c_str());
}
address.port = server_port;
room_post_office_impl->server = enet_host_create(&address, 16, NumChannels, 0, 0);
if (!room_post_office_impl->server) {
return false;
}
room_post_office_impl->state = State::Open;
room_post_office_impl->StartLoop();
return true;
}
bool RoomPostOffice::Destroy() {
room_post_office_impl->state = State::Closed;
room_post_office_impl->room_center_thread->join();
room_post_office_impl->room_center_thread.reset();
if (room_post_office_impl->server) {
enet_host_destroy(room_post_office_impl->server);
}
room_post_office_impl->server = nullptr;
room_post_office_impl->mailboxes.clear();
return true;
}
void RoomPostOffice::RoomPostOfficeImpl::StartLoop() {
room_center_thread =
std::make_unique<std::thread>(&RoomPostOffice::RoomPostOfficeImpl::ServerLoop, this);
}
void RoomPostOffice::RoomPostOfficeImpl::HandleClientDisconnection(const ENetPeer* peer) {
if (!peer) {
return;
}
const auto& mailbox =
std::find_if(mailboxes.begin(), mailboxes.end(),
[peer](const Mailbox& mailbox_entry) { return mailbox_entry.peer == peer; });
if (mailbox != mailboxes.end()) {
mailboxes.erase(mailbox);
LOG_INFO(Network, "some room leave to this room center");
}
}
void RoomPostOffice::RoomPostOfficeImpl::HandleMail(const ENetEvent* event) {
for (const auto& mailbox : mailboxes) {
if (mailbox.peer && mailbox.peer != event->peer) {
enet_peer_send(mailbox.peer, 0, event->packet);
}
}
enet_host_flush(server);
}
void RoomPostOffice::RoomPostOfficeImpl::HandleJoinMailbox(const ENetEvent* event) {
if (!event || !event->peer) {
return;
}
Mailbox mailbox{};
mailbox.peer = event->peer;
const auto& result =
std::find_if(mailboxes.begin(), mailboxes.end(), [mailbox](const Mailbox& mailbox_entry) {
return mailbox_entry.peer == mailbox.peer;
});
if (result == mailboxes.end()) {
mailboxes.push_back(mailbox);
ENetAddress address = event->peer->address;
LOG_INFO(Network, "{}.{}.{}.{}:{} Join to this room post office", (address.host) & 0xFF,
(address.host >> 8) & 0xFF, (address.host >> 16) & 0xFF,
(address.host >> 24) & 0xFF, address.port);
}
}
RoomPostOffice::State RoomPostOffice::GetState() const {
return room_post_office_impl->state;
}
} // namespace Network

View File

@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <string>
#include <vector>
namespace Network {
class RoomPostOffice final {
public:
enum class State : u8 {
Open, ///< The room post office is open and ready to accept connections.
Closed, ///< The room post office is not opened and can not accept connections.
};
RoomPostOffice();
~RoomPostOffice();
/**
* Gets the current state of the room post office.
*/
State GetState() const;
/**
* Creates the socket for this room post office.
* Will bind to default address if server is empty string.
*/
bool Create(const std::string& server_addr, u16 server_port);
/**
* Destorys the socket.
*/
bool Destroy();
private:
class RoomPostOfficeImpl;
std::unique_ptr<RoomPostOfficeImpl> room_post_office_impl;
};
} // namespace Network