summaryrefslogtreecommitdiff
path: root/src/network/room.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/room.cpp')
-rw-r--r--src/network/room.cpp84
1 files changed, 63 insertions, 21 deletions
diff --git a/src/network/room.cpp b/src/network/room.cpp
index fbbaf8b93..261049ab0 100644
--- a/src/network/room.cpp
+++ b/src/network/room.cpp
@@ -4,9 +4,9 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <atomic> 6#include <atomic>
7#include <mutex>
7#include <random> 8#include <random>
8#include <thread> 9#include <thread>
9#include <vector>
10#include "enet/enet.h" 10#include "enet/enet.h"
11#include "network/packet.h" 11#include "network/packet.h"
12#include "network/room.h" 12#include "network/room.h"
@@ -29,12 +29,14 @@ public:
29 29
30 struct Member { 30 struct Member {
31 std::string nickname; ///< The nickname of the member. 31 std::string nickname; ///< The nickname of the member.
32 std::string game_name; ///< The current game of the member 32 GameInfo game_info; ///< The current game of the member
33 MacAddress mac_address; ///< The assigned mac address of the member. 33 MacAddress mac_address; ///< The assigned mac address of the member.
34 ENetPeer* peer; ///< The remote peer. 34 ENetPeer* peer; ///< The remote peer.
35 }; 35 };
36 using MemberList = std::vector<Member>; 36 using MemberList = std::vector<Member>;
37 MemberList members; ///< Information about the members of this room. 37 MemberList members; ///< Information about the members of this room
38 mutable std::mutex member_mutex; ///< Mutex for locking the members list
39 /// This should be a std::shared_mutex as soon as C++17 is supported
38 40
39 RoomImpl() 41 RoomImpl()
40 : random_gen(std::random_device()()), NintendoOUI{0x00, 0x1F, 0x32, 0x00, 0x00, 0x00} {} 42 : random_gen(std::random_device()()), NintendoOUI{0x00, 0x1F, 0x32, 0x00, 0x00, 0x00} {}
@@ -147,7 +149,7 @@ void Room::RoomImpl::ServerLoop() {
147 case IdJoinRequest: 149 case IdJoinRequest:
148 HandleJoinRequest(&event); 150 HandleJoinRequest(&event);
149 break; 151 break;
150 case IdSetGameName: 152 case IdSetGameInfo:
151 HandleGameNamePacket(&event); 153 HandleGameNamePacket(&event);
152 break; 154 break;
153 case IdWifiPacket: 155 case IdWifiPacket:
@@ -213,7 +215,10 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
213 member.nickname = nickname; 215 member.nickname = nickname;
214 member.peer = event->peer; 216 member.peer = event->peer;
215 217
216 members.push_back(std::move(member)); 218 {
219 std::lock_guard<std::mutex> lock(member_mutex);
220 members.push_back(std::move(member));
221 }
217 222
218 // Notify everyone that the room information has changed. 223 // Notify everyone that the room information has changed.
219 BroadcastRoomInformation(); 224 BroadcastRoomInformation();
@@ -223,12 +228,14 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
223bool Room::RoomImpl::IsValidNickname(const std::string& nickname) const { 228bool Room::RoomImpl::IsValidNickname(const std::string& nickname) const {
224 // A nickname is valid if it is not already taken by anybody else in the room. 229 // A nickname is valid if it is not already taken by anybody else in the room.
225 // TODO(B3N30): Check for empty names, spaces, etc. 230 // TODO(B3N30): Check for empty names, spaces, etc.
231 std::lock_guard<std::mutex> lock(member_mutex);
226 return std::all_of(members.begin(), members.end(), 232 return std::all_of(members.begin(), members.end(),
227 [&nickname](const auto& member) { return member.nickname != nickname; }); 233 [&nickname](const auto& member) { return member.nickname != nickname; });
228} 234}
229 235
230bool Room::RoomImpl::IsValidMacAddress(const MacAddress& address) const { 236bool Room::RoomImpl::IsValidMacAddress(const MacAddress& address) const {
231 // A MAC address is valid if it is not already taken by anybody else in the room. 237 // A MAC address is valid if it is not already taken by anybody else in the room.
238 std::lock_guard<std::mutex> lock(member_mutex);
232 return std::all_of(members.begin(), members.end(), 239 return std::all_of(members.begin(), members.end(),
233 [&address](const auto& member) { return member.mac_address != address; }); 240 [&address](const auto& member) { return member.mac_address != address; });
234} 241}
@@ -279,6 +286,7 @@ void Room::RoomImpl::SendCloseMessage() {
279 packet << static_cast<u8>(IdCloseRoom); 286 packet << static_cast<u8>(IdCloseRoom);
280 ENetPacket* enet_packet = 287 ENetPacket* enet_packet =
281 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); 288 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
289 std::lock_guard<std::mutex> lock(member_mutex);
282 for (auto& member : members) { 290 for (auto& member : members) {
283 enet_peer_send(member.peer, 0, enet_packet); 291 enet_peer_send(member.peer, 0, enet_packet);
284 } 292 }
@@ -295,10 +303,14 @@ void Room::RoomImpl::BroadcastRoomInformation() {
295 packet << room_information.member_slots; 303 packet << room_information.member_slots;
296 304
297 packet << static_cast<u32>(members.size()); 305 packet << static_cast<u32>(members.size());
298 for (const auto& member : members) { 306 {
299 packet << member.nickname; 307 std::lock_guard<std::mutex> lock(member_mutex);
300 packet << member.mac_address; 308 for (const auto& member : members) {
301 packet << member.game_name; 309 packet << member.nickname;
310 packet << member.mac_address;
311 packet << member.game_info.name;
312 packet << member.game_info.id;
313 }
302 } 314 }
303 315
304 ENetPacket* enet_packet = 316 ENetPacket* enet_packet =
@@ -335,11 +347,13 @@ void Room::RoomImpl::HandleWifiPacket(const ENetEvent* event) {
335 ENET_PACKET_FLAG_RELIABLE); 347 ENET_PACKET_FLAG_RELIABLE);
336 348
337 if (destination_address == BroadcastMac) { // Send the data to everyone except the sender 349 if (destination_address == BroadcastMac) { // Send the data to everyone except the sender
350 std::lock_guard<std::mutex> lock(member_mutex);
338 for (const auto& member : members) { 351 for (const auto& member : members) {
339 if (member.peer != event->peer) 352 if (member.peer != event->peer)
340 enet_peer_send(member.peer, 0, enet_packet); 353 enet_peer_send(member.peer, 0, enet_packet);
341 } 354 }
342 } else { // Send the data only to the destination client 355 } else { // Send the data only to the destination client
356 std::lock_guard<std::mutex> lock(member_mutex);
343 auto member = std::find_if(members.begin(), members.end(), 357 auto member = std::find_if(members.begin(), members.end(),
344 [destination_address](const Member& member) -> bool { 358 [destination_address](const Member& member) -> bool {
345 return member.mac_address == destination_address; 359 return member.mac_address == destination_address;
@@ -361,6 +375,8 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) {
361 auto CompareNetworkAddress = [event](const Member member) -> bool { 375 auto CompareNetworkAddress = [event](const Member member) -> bool {
362 return member.peer == event->peer; 376 return member.peer == event->peer;
363 }; 377 };
378
379 std::lock_guard<std::mutex> lock(member_mutex);
364 const auto sending_member = std::find_if(members.begin(), members.end(), CompareNetworkAddress); 380 const auto sending_member = std::find_if(members.begin(), members.end(), CompareNetworkAddress);
365 if (sending_member == members.end()) { 381 if (sending_member == members.end()) {
366 return; // Received a chat message from a unknown sender 382 return; // Received a chat message from a unknown sender
@@ -385,22 +401,32 @@ void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) {
385 in_packet.Append(event->packet->data, event->packet->dataLength); 401 in_packet.Append(event->packet->data, event->packet->dataLength);
386 402
387 in_packet.IgnoreBytes(sizeof(u8)); // Igonore the message type 403 in_packet.IgnoreBytes(sizeof(u8)); // Igonore the message type
388 std::string game_name; 404 GameInfo game_info;
389 in_packet >> game_name; 405 in_packet >> game_info.name;
390 auto member = 406 in_packet >> game_info.id;
391 std::find_if(members.begin(), members.end(), 407
392 [event](const Member& member) -> bool { return member.peer == event->peer; }); 408 {
393 if (member != members.end()) { 409 std::lock_guard<std::mutex> lock(member_mutex);
394 member->game_name = game_name; 410 auto member =
395 BroadcastRoomInformation(); 411 std::find_if(members.begin(), members.end(), [event](const Member& member) -> bool {
412 return member.peer == event->peer;
413 });
414 if (member != members.end()) {
415 member->game_info = game_info;
416 }
396 } 417 }
418 BroadcastRoomInformation();
397} 419}
398 420
399void Room::RoomImpl::HandleClientDisconnection(ENetPeer* client) { 421void Room::RoomImpl::HandleClientDisconnection(ENetPeer* client) {
400 // Remove the client from the members list. 422 // Remove the client from the members list.
401 members.erase(std::remove_if(members.begin(), members.end(), 423 {
402 [client](const Member& member) { return member.peer == client; }), 424 std::lock_guard<std::mutex> lock(member_mutex);
403 members.end()); 425 members.erase(
426 std::remove_if(members.begin(), members.end(),
427 [client](const Member& member) { return member.peer == client; }),
428 members.end());
429 }
404 430
405 // Announce the change to all clients. 431 // Announce the change to all clients.
406 enet_peer_disconnect(client, 0); 432 enet_peer_disconnect(client, 0);
@@ -437,6 +463,19 @@ const RoomInformation& Room::GetRoomInformation() const {
437 return room_impl->room_information; 463 return room_impl->room_information;
438} 464}
439 465
466std::vector<Room::Member> Room::GetRoomMemberList() const {
467 std::vector<Room::Member> member_list;
468 std::lock_guard<std::mutex> lock(room_impl->member_mutex);
469 for (const auto& member_impl : room_impl->members) {
470 Member member;
471 member.nickname = member_impl.nickname;
472 member.mac_address = member_impl.mac_address;
473 member.game_info = member_impl.game_info;
474 member_list.push_back(member);
475 }
476 return member_list;
477};
478
440void Room::Destroy() { 479void Room::Destroy() {
441 room_impl->state = State::Closed; 480 room_impl->state = State::Closed;
442 room_impl->room_thread->join(); 481 room_impl->room_thread->join();
@@ -447,7 +486,10 @@ void Room::Destroy() {
447 } 486 }
448 room_impl->room_information = {}; 487 room_impl->room_information = {};
449 room_impl->server = nullptr; 488 room_impl->server = nullptr;
450 room_impl->members.clear(); 489 {
490 std::lock_guard<std::mutex> lock(room_impl->member_mutex);
491 room_impl->members.clear();
492 }
451 room_impl->room_information.member_slots = 0; 493 room_impl->room_information.member_slots = 0;
452 room_impl->room_information.name.clear(); 494 room_impl->room_information.name.clear();
453} 495}