diff options
Diffstat (limited to '')
| -rw-r--r-- | src/network/room.cpp | 35 | ||||
| -rw-r--r-- | src/network/room.h | 6 | ||||
| -rw-r--r-- | src/network/room_member.cpp | 53 | ||||
| -rw-r--r-- | src/network/room_member.h | 1 |
4 files changed, 70 insertions, 25 deletions
diff --git a/src/network/room.cpp b/src/network/room.cpp index 9af5b4ea0..da1679312 100644 --- a/src/network/room.cpp +++ b/src/network/room.cpp | |||
| @@ -74,6 +74,11 @@ public: | |||
| 74 | void SendMacCollision(ENetPeer* client); | 74 | void SendMacCollision(ENetPeer* client); |
| 75 | 75 | ||
| 76 | /** | 76 | /** |
| 77 | * Sends a ID_ROOM_VERSION_MISMATCH message telling the client that the MAC is invalid. | ||
| 78 | */ | ||
| 79 | void SendVersionMismatch(ENetPeer* client); | ||
| 80 | |||
| 81 | /** | ||
| 77 | * Notifies the member that its connection attempt was successful, | 82 | * Notifies the member that its connection attempt was successful, |
| 78 | * and it is now part of the room. | 83 | * and it is now part of the room. |
| 79 | */ | 84 | */ |
| @@ -170,6 +175,9 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
| 170 | MacAddress preferred_mac; | 175 | MacAddress preferred_mac; |
| 171 | packet >> preferred_mac; | 176 | packet >> preferred_mac; |
| 172 | 177 | ||
| 178 | u32 client_version; | ||
| 179 | packet >> client_version; | ||
| 180 | |||
| 173 | if (!IsValidNickname(nickname)) { | 181 | if (!IsValidNickname(nickname)) { |
| 174 | SendNameCollision(event->peer); | 182 | SendNameCollision(event->peer); |
| 175 | return; | 183 | return; |
| @@ -186,6 +194,11 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
| 186 | preferred_mac = GenerateMacAddress(); | 194 | preferred_mac = GenerateMacAddress(); |
| 187 | } | 195 | } |
| 188 | 196 | ||
| 197 | if (client_version != network_version) { | ||
| 198 | SendVersionMismatch(event->peer); | ||
| 199 | return; | ||
| 200 | } | ||
| 201 | |||
| 189 | // At this point the client is ready to be added to the room. | 202 | // At this point the client is ready to be added to the room. |
| 190 | Member member{}; | 203 | Member member{}; |
| 191 | member.mac_address = preferred_mac; | 204 | member.mac_address = preferred_mac; |
| @@ -232,6 +245,17 @@ void Room::RoomImpl::SendMacCollision(ENetPeer* client) { | |||
| 232 | enet_host_flush(server); | 245 | enet_host_flush(server); |
| 233 | } | 246 | } |
| 234 | 247 | ||
| 248 | void Room::RoomImpl::SendVersionMismatch(ENetPeer* client) { | ||
| 249 | Packet packet; | ||
| 250 | packet << static_cast<MessageID>(IdVersionMismatch); | ||
| 251 | packet << network_version; | ||
| 252 | |||
| 253 | ENetPacket* enet_packet = | ||
| 254 | enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); | ||
| 255 | enet_peer_send(client, 0, enet_packet); | ||
| 256 | enet_host_flush(server); | ||
| 257 | } | ||
| 258 | |||
| 235 | void Room::RoomImpl::SendJoinSuccess(ENetPeer* client, MacAddress mac_address) { | 259 | void Room::RoomImpl::SendJoinSuccess(ENetPeer* client, MacAddress mac_address) { |
| 236 | Packet packet; | 260 | Packet packet; |
| 237 | packet << static_cast<MessageID>(IdJoinSuccess); | 261 | packet << static_cast<MessageID>(IdJoinSuccess); |
| @@ -291,7 +315,7 @@ void Room::RoomImpl::HandleWifiPacket(const ENetEvent* event) { | |||
| 291 | if (destination_address == BroadcastMac) { // Send the data to everyone except the sender | 315 | if (destination_address == BroadcastMac) { // Send the data to everyone except the sender |
| 292 | for (const auto& member : members) { | 316 | for (const auto& member : members) { |
| 293 | if (member.peer != event->peer) | 317 | if (member.peer != event->peer) |
| 294 | enet_peer_send(member.peer, 0, event->packet); | 318 | enet_peer_send(member.peer, 0, enet_packet); |
| 295 | } | 319 | } |
| 296 | } else { // Send the data only to the destination client | 320 | } else { // Send the data only to the destination client |
| 297 | auto member = std::find_if(members.begin(), members.end(), | 321 | auto member = std::find_if(members.begin(), members.end(), |
| @@ -327,9 +351,9 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) { | |||
| 327 | 351 | ||
| 328 | ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(), | 352 | ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(), |
| 329 | ENET_PACKET_FLAG_RELIABLE); | 353 | ENET_PACKET_FLAG_RELIABLE); |
| 330 | for (auto it = members.begin(); it != members.end(); ++it) { | 354 | for (const auto& member : members) { |
| 331 | if (it->peer != event->peer) | 355 | if (member.peer != event->peer) |
| 332 | enet_peer_send(it->peer, 0, enet_packet); | 356 | enet_peer_send(member.peer, 0, enet_packet); |
| 333 | } | 357 | } |
| 334 | enet_host_flush(server); | 358 | enet_host_flush(server); |
| 335 | } | 359 | } |
| @@ -369,6 +393,9 @@ Room::~Room() = default; | |||
| 369 | void Room::Create(const std::string& name, const std::string& server_address, u16 server_port) { | 393 | void Room::Create(const std::string& name, const std::string& server_address, u16 server_port) { |
| 370 | ENetAddress address; | 394 | ENetAddress address; |
| 371 | address.host = ENET_HOST_ANY; | 395 | address.host = ENET_HOST_ANY; |
| 396 | if (!server_address.empty()) { | ||
| 397 | enet_address_set_host(&address, server_address.c_str()); | ||
| 398 | } | ||
| 372 | address.port = server_port; | 399 | address.port = server_port; |
| 373 | 400 | ||
| 374 | room_impl->server = enet_host_create(&address, MaxConcurrentConnections, NumChannels, 0, 0); | 401 | room_impl->server = enet_host_create(&address, MaxConcurrentConnections, NumChannels, 0, 0); |
diff --git a/src/network/room.h b/src/network/room.h index 82e3dc62c..ffa17599d 100644 --- a/src/network/room.h +++ b/src/network/room.h | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | namespace Network { | 12 | namespace Network { |
| 13 | 13 | ||
| 14 | constexpr u32 network_version = 1; ///< The version of this Room and RoomMember | ||
| 15 | |||
| 14 | constexpr u16 DefaultRoomPort = 1234; | 16 | constexpr u16 DefaultRoomPort = 1234; |
| 15 | constexpr size_t NumChannels = 1; // Number of channels used for the connection | 17 | constexpr size_t NumChannels = 1; // Number of channels used for the connection |
| 16 | 18 | ||
| @@ -37,7 +39,9 @@ enum RoomMessageTypes { | |||
| 37 | IdWifiPacket, | 39 | IdWifiPacket, |
| 38 | IdChatMessage, | 40 | IdChatMessage, |
| 39 | IdNameCollision, | 41 | IdNameCollision, |
| 40 | IdMacCollision | 42 | IdMacCollision, |
| 43 | IdVersionMismatch, | ||
| 44 | IdCloseRoom | ||
| 41 | }; | 45 | }; |
| 42 | 46 | ||
| 43 | /// This is what a server [person creating a server] would use. | 47 | /// 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 ec67aa5be..f6f8b0475 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <atomic> | 5 | #include <atomic> |
| 6 | #include <list> | ||
| 6 | #include <mutex> | 7 | #include <mutex> |
| 7 | #include <thread> | 8 | #include <thread> |
| 8 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| @@ -33,8 +34,10 @@ public: | |||
| 33 | 34 | ||
| 34 | std::mutex network_mutex; ///< Mutex that controls access to the `client` variable. | 35 | std::mutex network_mutex; ///< Mutex that controls access to the `client` variable. |
| 35 | /// Thread that receives and dispatches network packets | 36 | /// Thread that receives and dispatches network packets |
| 36 | std::unique_ptr<std::thread> receive_thread; | 37 | std::unique_ptr<std::thread> loop_thread; |
| 37 | void ReceiveLoop(); | 38 | std::mutex send_list_mutex; ///< Mutex that controls access to the `send_list` variable. |
| 39 | std::list<Packet> send_list; ///< A list that stores all packets to send the async | ||
| 40 | void MemberLoop(); | ||
| 38 | void StartLoop(); | 41 | void StartLoop(); |
| 39 | 42 | ||
| 40 | /** | 43 | /** |
| @@ -91,7 +94,7 @@ bool RoomMember::RoomMemberImpl::IsConnected() const { | |||
| 91 | return state == State::Joining || state == State::Joined; | 94 | return state == State::Joining || state == State::Joined; |
| 92 | } | 95 | } |
| 93 | 96 | ||
| 94 | void RoomMember::RoomMemberImpl::ReceiveLoop() { | 97 | void RoomMember::RoomMemberImpl::MemberLoop() { |
| 95 | // Receive packets while the connection is open | 98 | // Receive packets while the connection is open |
| 96 | while (IsConnected()) { | 99 | while (IsConnected()) { |
| 97 | std::lock_guard<std::mutex> lock(network_mutex); | 100 | std::lock_guard<std::mutex> lock(network_mutex); |
| @@ -121,6 +124,9 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() { | |||
| 121 | case IdMacCollision: | 124 | case IdMacCollision: |
| 122 | SetState(State::MacCollision); | 125 | SetState(State::MacCollision); |
| 123 | break; | 126 | break; |
| 127 | case IdVersionMismatch: | ||
| 128 | SetState(State::WrongVersion); | ||
| 129 | break; | ||
| 124 | default: | 130 | default: |
| 125 | break; | 131 | break; |
| 126 | } | 132 | } |
| @@ -128,22 +134,30 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() { | |||
| 128 | break; | 134 | break; |
| 129 | case ENET_EVENT_TYPE_DISCONNECT: | 135 | case ENET_EVENT_TYPE_DISCONNECT: |
| 130 | SetState(State::LostConnection); | 136 | SetState(State::LostConnection); |
| 137 | break; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | { | ||
| 141 | std::lock_guard<std::mutex> lock(send_list_mutex); | ||
| 142 | for (const auto& packet : send_list) { | ||
| 143 | ENetPacket* enetPacket = enet_packet_create(packet.GetData(), packet.GetDataSize(), | ||
| 144 | ENET_PACKET_FLAG_RELIABLE); | ||
| 145 | enet_peer_send(server, 0, enetPacket); | ||
| 131 | } | 146 | } |
| 147 | enet_host_flush(client); | ||
| 148 | send_list.clear(); | ||
| 132 | } | 149 | } |
| 133 | } | 150 | } |
| 134 | Disconnect(); | 151 | Disconnect(); |
| 135 | }; | 152 | }; |
| 136 | 153 | ||
| 137 | void RoomMember::RoomMemberImpl::StartLoop() { | 154 | void RoomMember::RoomMemberImpl::StartLoop() { |
| 138 | receive_thread = std::make_unique<std::thread>(&RoomMember::RoomMemberImpl::ReceiveLoop, this); | 155 | loop_thread = std::make_unique<std::thread>(&RoomMember::RoomMemberImpl::MemberLoop, this); |
| 139 | } | 156 | } |
| 140 | 157 | ||
| 141 | void RoomMember::RoomMemberImpl::Send(Packet& packet) { | 158 | void RoomMember::RoomMemberImpl::Send(Packet& packet) { |
| 142 | std::lock_guard<std::mutex> lock(network_mutex); | 159 | std::lock_guard<std::mutex> lock(send_list_mutex); |
| 143 | ENetPacket* enetPacket = | 160 | send_list.push_back(std::move(packet)); |
| 144 | enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); | ||
| 145 | enet_peer_send(server, 0, enetPacket); | ||
| 146 | enet_host_flush(client); | ||
| 147 | } | 161 | } |
| 148 | 162 | ||
| 149 | void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, | 163 | void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, |
| @@ -152,6 +166,7 @@ void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, | |||
| 152 | packet << static_cast<MessageID>(IdJoinRequest); | 166 | packet << static_cast<MessageID>(IdJoinRequest); |
| 153 | packet << nickname; | 167 | packet << nickname; |
| 154 | packet << preferred_mac; | 168 | packet << preferred_mac; |
| 169 | packet << network_version; | ||
| 155 | Send(packet); | 170 | Send(packet); |
| 156 | } | 171 | } |
| 157 | 172 | ||
| @@ -238,11 +253,9 @@ void RoomMember::RoomMemberImpl::Disconnect() { | |||
| 238 | room_information.member_slots = 0; | 253 | room_information.member_slots = 0; |
| 239 | room_information.name.clear(); | 254 | room_information.name.clear(); |
| 240 | 255 | ||
| 241 | if (server) { | 256 | if (!server) |
| 242 | enet_peer_disconnect(server, 0); | ||
| 243 | } else { | ||
| 244 | return; | 257 | return; |
| 245 | } | 258 | enet_peer_disconnect(server, 0); |
| 246 | 259 | ||
| 247 | ENetEvent event; | 260 | ENetEvent event; |
| 248 | while (enet_host_service(client, &event, ConnectionTimeoutMs) > 0) { | 261 | while (enet_host_service(client, &event, ConnectionTimeoutMs) > 0) { |
| @@ -296,14 +309,14 @@ RoomInformation RoomMember::GetRoomInformation() const { | |||
| 296 | void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port, | 309 | void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port, |
| 297 | u16 client_port) { | 310 | u16 client_port) { |
| 298 | // If the member is connected, kill the connection first | 311 | // If the member is connected, kill the connection first |
| 299 | if (room_member_impl->receive_thread && room_member_impl->receive_thread->joinable()) { | 312 | if (room_member_impl->loop_thread && room_member_impl->loop_thread->joinable()) { |
| 300 | room_member_impl->SetState(State::Error); | 313 | room_member_impl->SetState(State::Error); |
| 301 | room_member_impl->receive_thread->join(); | 314 | room_member_impl->loop_thread->join(); |
| 302 | room_member_impl->receive_thread.reset(); | 315 | room_member_impl->loop_thread.reset(); |
| 303 | } | 316 | } |
| 304 | // If the thread isn't running but the ptr still exists, reset it | 317 | // If the thread isn't running but the ptr still exists, reset it |
| 305 | else if (room_member_impl->receive_thread) { | 318 | else if (room_member_impl->loop_thread) { |
| 306 | room_member_impl->receive_thread.reset(); | 319 | room_member_impl->loop_thread.reset(); |
| 307 | } | 320 | } |
| 308 | 321 | ||
| 309 | ENetAddress address{}; | 322 | ENetAddress address{}; |
| @@ -361,8 +374,8 @@ void RoomMember::SendGameName(const std::string& game_name) { | |||
| 361 | 374 | ||
| 362 | void RoomMember::Leave() { | 375 | void RoomMember::Leave() { |
| 363 | room_member_impl->SetState(State::Idle); | 376 | room_member_impl->SetState(State::Idle); |
| 364 | room_member_impl->receive_thread->join(); | 377 | room_member_impl->loop_thread->join(); |
| 365 | room_member_impl->receive_thread.reset(); | 378 | room_member_impl->loop_thread.reset(); |
| 366 | } | 379 | } |
| 367 | 380 | ||
| 368 | } // namespace Network | 381 | } // namespace Network |
diff --git a/src/network/room_member.h b/src/network/room_member.h index d874cc5e4..6522f053c 100644 --- a/src/network/room_member.h +++ b/src/network/room_member.h | |||
| @@ -47,6 +47,7 @@ public: | |||
| 47 | // Reasons why connection was rejected | 47 | // Reasons why connection was rejected |
| 48 | NameCollision, ///< Somebody is already using this name | 48 | NameCollision, ///< Somebody is already using this name |
| 49 | MacCollision, ///< Somebody is already using that mac-address | 49 | MacCollision, ///< Somebody is already using that mac-address |
| 50 | WrongVersion, ///< The room version is not the same as for this RoomMember | ||
| 50 | CouldNotConnect ///< The room is not responding to a connection attempt | 51 | CouldNotConnect ///< The room is not responding to a connection attempt |
| 51 | }; | 52 | }; |
| 52 | 53 | ||