From e040bc9355db924bfc4cd9f2b60001afd41d4739 Mon Sep 17 00:00:00 2001 From: James Rowe Date: Fri, 20 Apr 2018 01:34:37 -0600 Subject: [PATCH] Multiplayer: Send an error message when connecting to a full room --- src/citra_qt/multiplayer/message.cpp | 2 ++ src/citra_qt/multiplayer/message.h | 1 + src/citra_qt/multiplayer/state.cpp | 3 +++ src/network/room.cpp | 26 +++++++++++++++++++++++++- src/network/room.h | 3 ++- src/network/room_member.cpp | 3 +++ src/network/room_member.h | 11 ++++++----- 7 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/citra_qt/multiplayer/message.cpp b/src/citra_qt/multiplayer/message.cpp index d2275e0e0..2cf76256f 100644 --- a/src/citra_qt/multiplayer/message.cpp +++ b/src/citra_qt/multiplayer/message.cpp @@ -22,6 +22,8 @@ const ConnectionError UNABLE_TO_CONNECT( QT_TR_NOOP("Unable to connect to the host. Verify that the connection settings are correct. If " "you still cannot connect, contact the room host and verify that the host is " "properly configured with the external port forwarded.")); +const ConnectionError ROOM_IS_FULL( + QT_TR_NOOP("Unable to connect to the room because it is already full.")); const ConnectionError COULD_NOT_CREATE_ROOM( QT_TR_NOOP("Creating a room failed. Please retry. Restarting Citra might be necessary.")); const ConnectionError HOST_BANNED( diff --git a/src/citra_qt/multiplayer/message.h b/src/citra_qt/multiplayer/message.h index 3b8613199..8e719de8e 100644 --- a/src/citra_qt/multiplayer/message.h +++ b/src/citra_qt/multiplayer/message.h @@ -27,6 +27,7 @@ extern const ConnectionError IP_ADDRESS_NOT_VALID; extern const ConnectionError PORT_NOT_VALID; extern const ConnectionError NO_INTERNET; extern const ConnectionError UNABLE_TO_CONNECT; +extern const ConnectionError ROOM_IS_FULL; extern const ConnectionError COULD_NOT_CREATE_ROOM; extern const ConnectionError HOST_BANNED; extern const ConnectionError WRONG_VERSION; diff --git a/src/citra_qt/multiplayer/state.cpp b/src/citra_qt/multiplayer/state.cpp index f1dec2ba3..461e1b5ca 100644 --- a/src/citra_qt/multiplayer/state.cpp +++ b/src/citra_qt/multiplayer/state.cpp @@ -102,6 +102,9 @@ void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& s case Network::RoomMember::State::MacCollision: NetworkMessage::ShowError(NetworkMessage::MAC_COLLISION); break; + case Network::RoomMember::State::RoomIsFull: + NetworkMessage::ShowError(NetworkMessage::ROOM_IS_FULL); + break; case Network::RoomMember::State::WrongPassword: NetworkMessage::ShowError(NetworkMessage::WRONG_PASSWORD); break; diff --git a/src/network/room.cpp b/src/network/room.cpp index f0d229d40..db2a1a1fe 100644 --- a/src/network/room.cpp +++ b/src/network/room.cpp @@ -68,6 +68,11 @@ public: */ bool IsValidMacAddress(const MacAddress& address) const; + /** + * Sends a ID_ROOM_IS_FULL message telling the client that the room is full. + */ + void SendRoomIsFull(ENetPeer* client); + /** * Sends a ID_ROOM_NAME_COLLISION message telling the client that the name is invalid. */ @@ -193,6 +198,13 @@ void Room::RoomImpl::StartLoop() { } void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { + { + std::lock_guard lock(member_mutex); + if (members.size() >= room_information.member_slots) { + SendRoomIsFull(event->peer); + return; + } + } Packet packet; packet.Append(event->packet->data, event->packet->dataLength); packet.IgnoreBytes(sizeof(u8)); // Ignore the message type @@ -295,6 +307,16 @@ void Room::RoomImpl::SendWrongPassword(ENetPeer* client) { enet_host_flush(server); } +void Room::RoomImpl::SendRoomIsFull(ENetPeer* client) { + Packet packet; + packet << static_cast(IdRoomIsFull); + + ENetPacket* enet_packet = + enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(client, 0, enet_packet); + enet_host_flush(server); +} + void Room::RoomImpl::SendVersionMismatch(ENetPeer* client) { Packet packet; packet << static_cast(IdVersionMismatch); @@ -527,7 +549,9 @@ bool Room::Create(const std::string& name, const std::string& server_address, u1 } address.port = server_port; - room_impl->server = enet_host_create(&address, max_connections, NumChannels, 0, 0); + // In order to send the room is full message to the connecting client, we need to leave one slot + // open so enet won't reject the incoming connection without telling us + room_impl->server = enet_host_create(&address, max_connections + 1, NumChannels, 0, 0); if (!room_impl->server) { return false; } diff --git a/src/network/room.h b/src/network/room.h index 6f8d15aeb..19bb5acce 100644 --- a/src/network/room.h +++ b/src/network/room.h @@ -57,7 +57,8 @@ enum RoomMessageTypes : u8 { IdMacCollision, IdVersionMismatch, IdWrongPassword, - IdCloseRoom + IdCloseRoom, + IdRoomIsFull, }; /// This is what a server [person creating a server] would use. diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index 601c67b0e..971c05c18 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -154,6 +154,9 @@ void RoomMember::RoomMemberImpl::MemberLoop() { HandleJoinPacket(&event); // Get the MAC Address for the client SetState(State::Joined); break; + case IdRoomIsFull: + SetState(State::RoomIsFull); + break; case IdNameCollision: SetState(State::NameCollision); break; diff --git a/src/network/room_member.h b/src/network/room_member.h index 12cff102a..b8a648f1d 100644 --- a/src/network/room_member.h +++ b/src/network/room_member.h @@ -54,11 +54,12 @@ public: LostConnection, ///< Connection closed // Reasons why connection was rejected - NameCollision, ///< Somebody is already using this name - MacCollision, ///< Somebody is already using that mac-address - WrongVersion, ///< The room version is not the same as for this RoomMember - WrongPassword, ///< The password doesn't match the one from the Room - CouldNotConnect ///< The room is not responding to a connection attempt + NameCollision, ///< Somebody is already using this name + MacCollision, ///< Somebody is already using that mac-address + WrongVersion, ///< The room version is not the same as for this RoomMember + WrongPassword, ///< The password doesn't match the one from the Room + CouldNotConnect, ///< The room is not responding to a connection attempt + RoomIsFull ///< Room is already at the maximum number of players }; struct MemberInformation {