From d11df2b700896c5244bd547797a4038f910b4bed Mon Sep 17 00:00:00 2001 From: Sage King Date: Thu, 4 Aug 2022 08:23:51 -0600 Subject: [PATCH 01/10] Refactored variable declared in NetPlayServer.cpp OnConnect() from npver to netplay_version --- Source/Core/Core/NetPlayServer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index ddc62d4561..c17248bac9 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -393,10 +393,10 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) } socket->data = new PlayerId(pid); - std::string npver; - rpac >> npver; + std::string netplay_version; + rpac >> netplay_version; // Dolphin netplay version - if (npver != Common::GetScmRevGitStr()) + if (netplay_version != Common::GetScmRevGitStr()) return ConnectionError::VersionMismatch; // game is currently running or game start is pending From 5dea8aaed02cc0015e8f97e9b57049c69c81d962 Mon Sep 17 00:00:00 2001 From: Sage King Date: Thu, 4 Aug 2022 08:32:31 -0600 Subject: [PATCH 02/10] Added initializer braces to Client player; in NetPlayServer.cpp OnConnect() --- Source/Core/Core/NetPlayServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index c17248bac9..141ba474af 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -407,7 +407,7 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) if (m_players.size() >= 255) return ConnectionError::ServerFull; - Client player; + Client player{}; player.pid = pid; player.socket = socket; From 9d14d95737ea86052d8e0a29216fd1e40c8410b8 Mon Sep 17 00:00:00 2001 From: Sage King Date: Thu, 4 Aug 2022 08:26:46 -0600 Subject: [PATCH 03/10] Removed code duplicating comments in NetPlayServer.cpp OnConnect() --- Source/Core/Core/NetPlayServer.cpp | 72 ++++++++++++------------------ 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 141ba474af..69759490d1 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -381,7 +381,6 @@ static void SendSyncIdentifier(sf::Packet& spac, const SyncIdentifier& sync_iden // called from ---NETPLAY--- thread ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) { - // give new client first available id PlayerId pid = 1; for (auto i = m_players.begin(); i != m_players.end(); ++i) { @@ -395,15 +394,12 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) std::string netplay_version; rpac >> netplay_version; - // Dolphin netplay version if (netplay_version != Common::GetScmRevGitStr()) return ConnectionError::VersionMismatch; - // game is currently running or game start is pending if (m_is_running || m_start_pending) return ConnectionError::GameRunning; - // too many players if (m_players.size() >= 255) return ConnectionError::ServerFull; @@ -417,13 +413,10 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) if (StringUTF8CodePointCount(player.name) > MAX_NAME_LENGTH) return ConnectionError::NameTooLong; - // Extend reliable traffic timeout enet_peer_timeout(socket, 0, PEER_TIMEOUT, PEER_TIMEOUT); - // cause pings to be updated m_update_pings = true; - // try to automatically assign new user a pad for (PlayerId& mapping : m_pad_map) { if (mapping == 0) @@ -433,61 +426,54 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) } } - // send join message to already connected clients - sf::Packet spac; - spac << MessageID::PlayerJoin; - spac << player.pid << player.name << player.revision; - SendToClients(spac); + sf::Packet send_packet; + send_packet << MessageID::PlayerJoin; + send_packet << player.pid << player.name << player.revision; + SendToClients(send_packet); - // send new client success message with their ID - spac.clear(); - spac << MessageID::ConnectionSuccessful; - spac << player.pid; - Send(player.socket, spac); + send_packet.clear(); + send_packet << MessageID::ConnectionSuccessful; + send_packet << player.pid; + Send(player.socket, send_packet); - // send new client the selected game if (!m_selected_game_name.empty()) { - spac.clear(); - spac << MessageID::ChangeGame; - SendSyncIdentifier(spac, m_selected_game_identifier); - spac << m_selected_game_name; - Send(player.socket, spac); + send_packet.clear(); + send_packet << MessageID::ChangeGame; + SendSyncIdentifier(send_packet, m_selected_game_identifier); + send_packet << m_selected_game_name; + Send(player.socket, send_packet); } if (!m_host_input_authority) { - // send the pad buffer value - spac.clear(); - spac << MessageID::PadBuffer; - spac << m_target_buffer_size; - Send(player.socket, spac); + send_packet.clear(); + send_packet << MessageID::PadBuffer; + send_packet << m_target_buffer_size; + Send(player.socket, send_packet); } - // send input authority state - spac.clear(); - spac << MessageID::HostInputAuthority; - spac << m_host_input_authority; - Send(player.socket, spac); + send_packet.clear(); + send_packet << MessageID::HostInputAuthority; + send_packet << m_host_input_authority; + Send(player.socket, send_packet); - // sync values with new client for (const auto& p : m_players) { - spac.clear(); - spac << MessageID::PlayerJoin; - spac << p.second.pid << p.second.name << p.second.revision; - Send(player.socket, spac); + send_packet.clear(); + send_packet << MessageID::PlayerJoin; + send_packet << p.second.pid << p.second.name << p.second.revision; + Send(player.socket, send_packet); - spac.clear(); - spac << MessageID::GameStatus; - spac << p.second.pid << p.second.game_status; - Send(player.socket, spac); + send_packet.clear(); + send_packet << MessageID::GameStatus; + send_packet << p.second.pid << p.second.game_status; + Send(player.socket, send_packet); } if (Config::Get(Config::NETPLAY_ENABLE_QOS)) player.qos_session = Common::QoSSession(player.socket); - // add client to the player list { std::lock_guard lkp(m_crit.players); m_players.emplace(*PeerPlayerId(player.socket), std::move(player)); From d81756e9b97bc342953cb52ee7218a4a85afe208 Mon Sep 17 00:00:00 2001 From: Sage King Date: Thu, 4 Aug 2022 09:26:21 -0600 Subject: [PATCH 04/10] Refactored parameter to OnConnect() in NetPlayServer.cpp from rpac to received_packet --- Source/Core/Core/NetPlayServer.cpp | 8 ++++---- Source/Core/Core/NetPlayServer.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 69759490d1..e7f2f080fa 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -379,7 +379,7 @@ static void SendSyncIdentifier(sf::Packet& spac, const SyncIdentifier& sync_iden } // called from ---NETPLAY--- thread -ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) +ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& received_packet) { PlayerId pid = 1; for (auto i = m_players.begin(); i != m_players.end(); ++i) @@ -393,7 +393,7 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) socket->data = new PlayerId(pid); std::string netplay_version; - rpac >> netplay_version; + received_packet >> netplay_version; if (netplay_version != Common::GetScmRevGitStr()) return ConnectionError::VersionMismatch; @@ -407,8 +407,8 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) player.pid = pid; player.socket = socket; - rpac >> player.revision; - rpac >> player.name; + received_packet >> player.revision; + received_packet >> player.name; if (StringUTF8CodePointCount(player.name) > MAX_NAME_LENGTH) return ConnectionError::NameTooLong; diff --git a/Source/Core/Core/NetPlayServer.h b/Source/Core/Core/NetPlayServer.h index 67de180204..77b1f7f357 100644 --- a/Source/Core/Core/NetPlayServer.h +++ b/Source/Core/Core/NetPlayServer.h @@ -129,7 +129,7 @@ private: void SendToClients(const sf::Packet& packet, PlayerId skip_pid = 0, u8 channel_id = DEFAULT_CHANNEL); void Send(ENetPeer* socket, const sf::Packet& packet, u8 channel_id = DEFAULT_CHANNEL); - ConnectionError OnConnect(ENetPeer* socket, sf::Packet& rpac); + ConnectionError OnConnect(ENetPeer* socket, sf::Packet& received_packet); unsigned int OnDisconnect(const Client& player); unsigned int OnData(sf::Packet& packet, Client& player); From 2f367d7a9b716a1963a22f48788766d3445cd041 Mon Sep 17 00:00:00 2001 From: Sage King Date: Sat, 6 Aug 2022 10:23:27 -0600 Subject: [PATCH 05/10] Updated PEER_TIMOUT in NetPlayCommon.h to use chrono literals; Updated NetPlayServer.cpp OnConnect() by putting commonly used code into named functions --- Source/Core/Core/NetPlayCommon.h | 6 +- Source/Core/Core/NetPlayServer.cpp | 174 ++++++++++++++++++----------- Source/Core/Core/NetPlayServer.h | 12 ++ 3 files changed, 124 insertions(+), 68 deletions(-) diff --git a/Source/Core/Core/NetPlayCommon.h b/Source/Core/Core/NetPlayCommon.h index e77bd307db..a777728ac2 100644 --- a/Source/Core/Core/NetPlayCommon.h +++ b/Source/Core/Core/NetPlayCommon.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -14,7 +15,10 @@ namespace NetPlay { -constexpr u32 PEER_TIMEOUT = 30000; +using namespace std::chrono_literals; +// An arbitrary amount of time of no acknowledgement of sent packets before netplay decides a +// connection is disconnected +constexpr std::chrono::milliseconds PEER_TIMEOUT = 30s; bool CompressFileIntoPacket(const std::string& file_path, sf::Packet& packet); bool CompressFolderIntoPacket(const std::string& folder_path, sf::Packet& packet); diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index e7f2f080fa..7693cae752 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -379,19 +379,8 @@ static void SendSyncIdentifier(sf::Packet& spac, const SyncIdentifier& sync_iden } // called from ---NETPLAY--- thread -ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& received_packet) +ConnectionError NetPlayServer::OnConnect(ENetPeer* incoming_connection, sf::Packet& received_packet) { - PlayerId pid = 1; - for (auto i = m_players.begin(); i != m_players.end(); ++i) - { - if (i->second.pid == pid) - { - pid++; - i = m_players.begin(); - } - } - socket->data = new PlayerId(pid); - std::string netplay_version; received_packet >> netplay_version; if (netplay_version != Common::GetScmRevGitStr()) @@ -403,81 +392,49 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& received_ if (m_players.size() >= 255) return ConnectionError::ServerFull; - Client player{}; - player.pid = pid; - player.socket = socket; + Client new_player{}; + new_player.pid = GiveFirstAvailableIDTo(incoming_connection); + new_player.socket = incoming_connection; - received_packet >> player.revision; - received_packet >> player.name; + received_packet >> new_player.revision; + received_packet >> new_player.name; - if (StringUTF8CodePointCount(player.name) > MAX_NAME_LENGTH) + if (StringUTF8CodePointCount(new_player.name) > MAX_NAME_LENGTH) return ConnectionError::NameTooLong; - enet_peer_timeout(socket, 0, PEER_TIMEOUT, PEER_TIMEOUT); + enet_peer_timeout(incoming_connection, 0, PEER_TIMEOUT.count(), PEER_TIMEOUT.count()); + // force a ping on first netplay loop m_update_pings = true; - for (PlayerId& mapping : m_pad_map) - { - if (mapping == 0) - { - mapping = player.pid; - break; - } - } + AssignNewUserAPad(new_player); - sf::Packet send_packet; - send_packet << MessageID::PlayerJoin; - send_packet << player.pid << player.name << player.revision; - SendToClients(send_packet); + // tell other players a new player joined + SendResponse(MessageID::PlayerJoin); - send_packet.clear(); - send_packet << MessageID::ConnectionSuccessful; - send_packet << player.pid; - Send(player.socket, send_packet); + // tell new client they connected and their ID + SendResponse(MessageID::ConnectionSuccessful, new_player); + // tell new client the selected game if (!m_selected_game_name.empty()) - { - send_packet.clear(); - send_packet << MessageID::ChangeGame; - SendSyncIdentifier(send_packet, m_selected_game_identifier); - send_packet << m_selected_game_name; - Send(player.socket, send_packet); - } + SendResponse(MessageID::ChangeGame, new_player); if (!m_host_input_authority) - { - send_packet.clear(); - send_packet << MessageID::PadBuffer; - send_packet << m_target_buffer_size; - Send(player.socket, send_packet); - } + SendResponse(MessageID::PadBuffer, new_player); - send_packet.clear(); - send_packet << MessageID::HostInputAuthority; - send_packet << m_host_input_authority; - Send(player.socket, send_packet); + SendResponse(MessageID::HostInputAuthority, new_player); - for (const auto& p : m_players) - { - send_packet.clear(); - send_packet << MessageID::PlayerJoin; - send_packet << p.second.pid << p.second.name << p.second.revision; - Send(player.socket, send_packet); - - send_packet.clear(); - send_packet << MessageID::GameStatus; - send_packet << p.second.pid << p.second.game_status; - Send(player.socket, send_packet); - } + TellNewPlayerAboutExistingPlayers(new_player); if (Config::Get(Config::NETPLAY_ENABLE_QOS)) - player.qos_session = Common::QoSSession(player.socket); + new_player.qos_session = Common::QoSSession(new_player.socket); { std::lock_guard lkp(m_crit.players); - m_players.emplace(*PeerPlayerId(player.socket), std::move(player)); - UpdatePadMapping(); // sync pad mappings with everyone + // add new player to list of players + m_players.emplace(*PeerPlayerId(new_player.socket), std::move(new_player)); + // sync pad mappings with everyone + UpdatePadMapping(); UpdateGBAConfig(); UpdateWiimoteMapping(); } @@ -2071,6 +2028,89 @@ bool NetPlayServer::PlayerHasControllerMapped(const PlayerId pid) const std::any_of(m_wiimote_map.begin(), m_wiimote_map.end(), mapping_matches_player_id); } +void NetPlayServer::AssignNewUserAPad(const Client& player) +{ + for (PlayerId& mapping : m_pad_map) + { + if (mapping == Unmapped) + { + mapping = player.pid; + break; + } + } +} + +PlayerId NetPlayServer::GiveFirstAvailableIDTo(ENetPeer* player) +{ + PlayerId pid = 1; + for (auto i = m_players.begin(); i != m_players.end(); ++i) + { + if (i->second.pid == pid) + { + pid++; + i = m_players.begin(); + } + } + player->data = new PlayerId(pid); + return pid; +} + +void NetPlayServer::SendResponse(MessageID message_id, const Client& player) +{ + sf::Packet response; + switch (message_id) + { + case MessageID::PlayerJoin: + response << MessageID::PlayerJoin; + response << player.pid << player.name << player.revision; + break; + + case MessageID::ConnectionSuccessful: + response << MessageID::ConnectionSuccessful; + response << player.pid; + break; + + case MessageID::ChangeGame: + response << MessageID::ChangeGame; + SendSyncIdentifier(response, m_selected_game_identifier); + response << m_selected_game_name; + break; + + case MessageID::PadBuffer: + response << MessageID::PadBuffer; + response << m_target_buffer_size; + break; + + case MessageID::HostInputAuthority: + response << MessageID::HostInputAuthority; + response << m_host_input_authority; + break; + } + + // no player specified + if (player == Client{}) + SendToClients(response); + else + Send(player.socket, response); +} + +void NetPlayServer::TellNewPlayerAboutExistingPlayers(const Client& new_player) +{ + sf::Packet send_packet; + for (const auto& p : m_players) + { + send_packet.clear(); + send_packet << MessageID::PlayerJoin; + send_packet << p.second.pid << p.second.name << p.second.revision; + Send(new_player.socket, send_packet); + + send_packet.clear(); + send_packet << MessageID::GameStatus; + send_packet << p.second.pid << p.second.game_status; + Send(new_player.socket, send_packet); + } +} + u16 NetPlayServer::GetPort() const { return m_server->address.port; diff --git a/Source/Core/Core/NetPlayServer.h b/Source/Core/Core/NetPlayServer.h index 77b1f7f357..5688ce5a6d 100644 --- a/Source/Core/Core/NetPlayServer.h +++ b/Source/Core/Core/NetPlayServer.h @@ -103,6 +103,12 @@ private: AllExcept }; + enum MappedState + { + Unmapped, + Mapped + }; + struct AsyncQueueEntry { sf::Packet packet; @@ -147,6 +153,12 @@ private: void SetupIndex(); bool PlayerHasControllerMapped(PlayerId pid) const; + void AssignNewUserAPad(const Client& player); + // returns the PID given + PlayerId GiveFirstAvailableIDTo(ENetPeer* player); + void SendResponse(MessageID message_id, const Client& player = Client{}); + void TellNewPlayerAboutExistingPlayers(const Client& new_player); + NetSettings m_settings; bool m_is_running = false; From 477c20e28d1d512247bbc5744e1f2147d2249104 Mon Sep 17 00:00:00 2001 From: Sage King Date: Sun, 7 Aug 2022 09:37:28 -0600 Subject: [PATCH 06/10] Updated comment explaining enet_peer_timeout's use in NetPlayClient.cpp and NetPlayServer.cpp; Corrected syntax related to PEER_TIMEOUT in NetplayClient.cpp --- Source/Core/Core/NetPlayClient.cpp | 10 ++++++---- Source/Core/Core/NetPlayServer.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 9c01f7a080..05c6779e24 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -152,8 +152,9 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay return; } - // Extend reliable traffic timeout - enet_peer_timeout(m_server, 0, PEER_TIMEOUT, PEER_TIMEOUT); + // Update time in milliseconds of no acknoledgment of + // sent packets before a connection is deemed disconnected + enet_peer_timeout(m_server, 0, PEER_TIMEOUT.count(), PEER_TIMEOUT.count()); ENetEvent netEvent; int net = enet_host_service(m_client, &netEvent, 5000); @@ -211,8 +212,9 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay case ENET_EVENT_TYPE_CONNECT: m_server = netEvent.peer; - // Extend reliable traffic timeout - enet_peer_timeout(m_server, 0, PEER_TIMEOUT, PEER_TIMEOUT); + // Update time in milliseconds of no acknoledgment of + // sent packets before a connection is deemed disconnected + enet_peer_timeout(m_server, 0, PEER_TIMEOUT.count(), PEER_TIMEOUT.count()); if (Connect()) { diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 7693cae752..e9b5c271b5 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -402,6 +402,8 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* incoming_connection, sf::Pack if (StringUTF8CodePointCount(new_player.name) > MAX_NAME_LENGTH) return ConnectionError::NameTooLong; + // Update time in milliseconds of no acknoledgment of + // sent packets before a connection is deemed disconnected enet_peer_timeout(incoming_connection, 0, PEER_TIMEOUT.count(), PEER_TIMEOUT.count()); // force a ping on first netplay loop @@ -2085,6 +2087,10 @@ void NetPlayServer::SendResponse(MessageID message_id, const Client& player) response << MessageID::HostInputAuthority; response << m_host_input_authority; break; + default: + INFO_LOG_FMT(NETPLAY, "Warning! Call to SendResponse() failed to send a packet."); + return; + break; } // no player specified From a12099404e366d3ad2083eb394bd0744d6e1411c Mon Sep 17 00:00:00 2001 From: Sage King Date: Sun, 7 Aug 2022 13:28:10 -0600 Subject: [PATCH 07/10] Added SendResponseToAllPlayers() and SendResponseToPlayer() to NetPlayServer.cpp and refactored OnConnect to use them --- Source/Core/Core/NetPlayServer.cpp | 90 +++++++++++------------------- Source/Core/Core/NetPlayServer.h | 9 ++- 2 files changed, 40 insertions(+), 59 deletions(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index e9b5c271b5..9ea4555ca5 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -412,21 +413,35 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* incoming_connection, sf::Pack AssignNewUserAPad(new_player); // tell other players a new player joined - SendResponse(MessageID::PlayerJoin); + SendResponseToAllPlayers(MessageID::PlayerJoin, new_player.pid, new_player.name, + new_player.revision); // tell new client they connected and their ID - SendResponse(MessageID::ConnectionSuccessful, new_player); + SendResponseToPlayer(new_player, MessageID::ConnectionSuccessful, new_player.pid); // tell new client the selected game if (!m_selected_game_name.empty()) - SendResponse(MessageID::ChangeGame, new_player); + { + sf::Packet send_packet; + send_packet << MessageID::ChangeGame; + SendSyncIdentifier(send_packet, m_selected_game_identifier); + send_packet << m_selected_game_name; + Send(new_player.socket, send_packet); + } if (!m_host_input_authority) - SendResponse(MessageID::PadBuffer, new_player); + SendResponseToPlayer(new_player, MessageID::PadBuffer, m_target_buffer_size); - SendResponse(MessageID::HostInputAuthority, new_player); + SendResponseToPlayer(new_player, MessageID::HostInputAuthority, m_host_input_authority); - TellNewPlayerAboutExistingPlayers(new_player); + for (const auto& existing_player : m_players) + { + SendResponseToPlayer(new_player, MessageID::PlayerJoin, existing_player.second.pid, + existing_player.second.name, existing_player.second.revision); + + SendResponseToPlayer(new_player, MessageID::GameStatus, existing_player.second.pid, + existing_player.second.game_status); + } if (Config::Get(Config::NETPLAY_ENABLE_QOS)) new_player.qos_session = Common::QoSSession(new_player.socket); @@ -2057,64 +2072,25 @@ PlayerId NetPlayServer::GiveFirstAvailableIDTo(ENetPeer* player) return pid; } -void NetPlayServer::SendResponse(MessageID message_id, const Client& player) +template +void NetPlayServer::SendResponseToPlayer(const Client& player, const MessageID message_id, + Data&&... data_to_send) { sf::Packet response; - switch (message_id) - { - case MessageID::PlayerJoin: - response << MessageID::PlayerJoin; - response << player.pid << player.name << player.revision; - break; + response << message_id; + (response << ... << std::forward(data_to_send)); - case MessageID::ConnectionSuccessful: - response << MessageID::ConnectionSuccessful; - response << player.pid; - break; - - case MessageID::ChangeGame: - response << MessageID::ChangeGame; - SendSyncIdentifier(response, m_selected_game_identifier); - response << m_selected_game_name; - break; - - case MessageID::PadBuffer: - response << MessageID::PadBuffer; - response << m_target_buffer_size; - break; - - case MessageID::HostInputAuthority: - response << MessageID::HostInputAuthority; - response << m_host_input_authority; - break; - default: - INFO_LOG_FMT(NETPLAY, "Warning! Call to SendResponse() failed to send a packet."); - return; - break; - } - - // no player specified - if (player == Client{}) - SendToClients(response); - else - Send(player.socket, response); + Send(player.socket, response); } -void NetPlayServer::TellNewPlayerAboutExistingPlayers(const Client& new_player) +template +void NetPlayServer::SendResponseToAllPlayers(const MessageID message_id, Data&&... data_to_send) { - sf::Packet send_packet; - for (const auto& p : m_players) - { - send_packet.clear(); - send_packet << MessageID::PlayerJoin; - send_packet << p.second.pid << p.second.name << p.second.revision; - Send(new_player.socket, send_packet); + sf::Packet response; + response << message_id; + (response << ... << std::forward(data_to_send)); - send_packet.clear(); - send_packet << MessageID::GameStatus; - send_packet << p.second.pid << p.second.game_status; - Send(new_player.socket, send_packet); - } + SendToClients(response); } u16 NetPlayServer::GetPort() const diff --git a/Source/Core/Core/NetPlayServer.h b/Source/Core/Core/NetPlayServer.h index 5688ce5a6d..0b54f30ba2 100644 --- a/Source/Core/Core/NetPlayServer.h +++ b/Source/Core/Core/NetPlayServer.h @@ -132,6 +132,11 @@ private: u64 GetInitialNetPlayRTC() const; + template + void SendResponseToPlayer(const Client& player, const MessageID message_id, + Data&&... data_to_send); + template + void SendResponseToAllPlayers(const MessageID message_id, Data&&... data_to_send); void SendToClients(const sf::Packet& packet, PlayerId skip_pid = 0, u8 channel_id = DEFAULT_CHANNEL); void Send(ENetPeer* socket, const sf::Packet& packet, u8 channel_id = DEFAULT_CHANNEL); @@ -153,11 +158,11 @@ private: void SetupIndex(); bool PlayerHasControllerMapped(PlayerId pid) const; + // pulled from OnConnect() void AssignNewUserAPad(const Client& player); + // pulled from OnConnect() // returns the PID given PlayerId GiveFirstAvailableIDTo(ENetPeer* player); - void SendResponse(MessageID message_id, const Client& player = Client{}); - void TellNewPlayerAboutExistingPlayers(const Client& new_player); NetSettings m_settings; From 978b6a8724c38c03e2eb07c6ac5c4f3c146e9d09 Mon Sep 17 00:00:00 2001 From: Sage King Date: Sun, 7 Aug 2022 16:56:13 -0600 Subject: [PATCH 08/10] Added comment explaining obscure folding syntax in NetPlayServer.cpp --- Source/Core/Core/NetPlayServer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 9ea4555ca5..0d59486423 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -2078,6 +2078,7 @@ void NetPlayServer::SendResponseToPlayer(const Client& player, const MessageID m { sf::Packet response; response << message_id; + // this is a C++17 fold expression used to call the << operator for all of the data (response << ... << std::forward(data_to_send)); Send(player.socket, response); @@ -2088,6 +2089,7 @@ void NetPlayServer::SendResponseToAllPlayers(const MessageID message_id, Data&&. { sf::Packet response; response << message_id; + // this is a C++17 fold expression used to call the << operator for all of the data (response << ... << std::forward(data_to_send)); SendToClients(response); From 66276ac61ba3ae3a8b5f840cdb8616ee9bd5dc83 Mon Sep 17 00:00:00 2001 From: Sage King Date: Sun, 7 Aug 2022 18:39:07 -0600 Subject: [PATCH 09/10] Added type to SyncIndentifierComparison enum in SyncIdentifier.h in an attempt to fix a failed call to operator<< in SendResponse() --- Source/Core/Core/NetPlayServer.cpp | 3 ++- Source/Core/Core/NetPlayServer.h | 6 ------ Source/Core/Core/SyncIdentifier.h | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 0d59486423..981e980d17 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -2049,7 +2049,8 @@ void NetPlayServer::AssignNewUserAPad(const Client& player) { for (PlayerId& mapping : m_pad_map) { - if (mapping == Unmapped) + // 0 means unmapped + if (mapping == 0) { mapping = player.pid; break; diff --git a/Source/Core/Core/NetPlayServer.h b/Source/Core/Core/NetPlayServer.h index 0b54f30ba2..13a05ee070 100644 --- a/Source/Core/Core/NetPlayServer.h +++ b/Source/Core/Core/NetPlayServer.h @@ -103,12 +103,6 @@ private: AllExcept }; - enum MappedState - { - Unmapped, - Mapped - }; - struct AsyncQueueEntry { sf::Packet packet; diff --git a/Source/Core/Core/SyncIdentifier.h b/Source/Core/Core/SyncIdentifier.h index a144eb58e1..5e984476f9 100644 --- a/Source/Core/Core/SyncIdentifier.h +++ b/Source/Core/Core/SyncIdentifier.h @@ -36,7 +36,7 @@ struct SyncIdentifier // The order of entries in this enum matters, as the lowest value is // treated as the "best" available option. -enum class SyncIdentifierComparison +enum class SyncIdentifierComparison : u8 { SameGame, DifferentHash, From da803adf15401ba6615130a9667da6e771b618f9 Mon Sep 17 00:00:00 2001 From: Sage King Date: Tue, 9 Aug 2022 16:26:03 -0600 Subject: [PATCH 10/10] Work around for compiler bug on Debian and FreeBSD --- Source/Core/Core/NetPlayServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 981e980d17..c44af173ba 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -440,7 +440,7 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* incoming_connection, sf::Pack existing_player.second.name, existing_player.second.revision); SendResponseToPlayer(new_player, MessageID::GameStatus, existing_player.second.pid, - existing_player.second.game_status); + static_cast(existing_player.second.game_status)); } if (Config::Get(Config::NETPLAY_ENABLE_QOS))