diff options
Diffstat (limited to 'src/network/room.cpp')
| -rw-r--r-- | src/network/room.cpp | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/src/network/room.cpp b/src/network/room.cpp index 0fdb5e68f..9af5b4ea0 100644 --- a/src/network/room.cpp +++ b/src/network/room.cpp | |||
| @@ -85,8 +85,8 @@ public: | |||
| 85 | * The packet has the structure: | 85 | * The packet has the structure: |
| 86 | * <MessageID>ID_ROOM_INFORMATION | 86 | * <MessageID>ID_ROOM_INFORMATION |
| 87 | * <String> room_name | 87 | * <String> room_name |
| 88 | * <uint32_t> member_slots: The max number of clients allowed in this room | 88 | * <u32> member_slots: The max number of clients allowed in this room |
| 89 | * <uint32_t> num_members: the number of currently joined clients | 89 | * <u32> num_members: the number of currently joined clients |
| 90 | * This is followed by the following three values for each member: | 90 | * This is followed by the following three values for each member: |
| 91 | * <String> nickname of that member | 91 | * <String> nickname of that member |
| 92 | * <MacAddress> mac_address of that member | 92 | * <MacAddress> mac_address of that member |
| @@ -113,6 +113,12 @@ public: | |||
| 113 | void HandleChatPacket(const ENetEvent* event); | 113 | void HandleChatPacket(const ENetEvent* event); |
| 114 | 114 | ||
| 115 | /** | 115 | /** |
| 116 | * Extracts the game name from a received ENet packet and broadcasts it. | ||
| 117 | * @param event The ENet event that was received. | ||
| 118 | */ | ||
| 119 | void HandleGameNamePacket(const ENetEvent* event); | ||
| 120 | |||
| 121 | /** | ||
| 116 | * Removes the client from the members list if it was in it and announces the change | 122 | * Removes the client from the members list if it was in it and announces the change |
| 117 | * to all other clients. | 123 | * to all other clients. |
| 118 | */ | 124 | */ |
| @@ -130,7 +136,9 @@ void Room::RoomImpl::ServerLoop() { | |||
| 130 | case IdJoinRequest: | 136 | case IdJoinRequest: |
| 131 | HandleJoinRequest(&event); | 137 | HandleJoinRequest(&event); |
| 132 | break; | 138 | break; |
| 133 | // TODO(B3N30): Handle the other message types | 139 | case IdSetGameName: |
| 140 | HandleGameNamePacket(&event); | ||
| 141 | break; | ||
| 134 | case IdWifiPacket: | 142 | case IdWifiPacket: |
| 135 | HandleWifiPacket(&event); | 143 | HandleWifiPacket(&event); |
| 136 | break; | 144 | break; |
| @@ -184,7 +192,7 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
| 184 | member.nickname = nickname; | 192 | member.nickname = nickname; |
| 185 | member.peer = event->peer; | 193 | member.peer = event->peer; |
| 186 | 194 | ||
| 187 | members.push_back(member); | 195 | members.push_back(std::move(member)); |
| 188 | 196 | ||
| 189 | // Notify everyone that the room information has changed. | 197 | // Notify everyone that the room information has changed. |
| 190 | BroadcastRoomInformation(); | 198 | BroadcastRoomInformation(); |
| @@ -194,22 +202,14 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
| 194 | bool Room::RoomImpl::IsValidNickname(const std::string& nickname) const { | 202 | bool Room::RoomImpl::IsValidNickname(const std::string& nickname) const { |
| 195 | // A nickname is valid if it is not already taken by anybody else in the room. | 203 | // A nickname is valid if it is not already taken by anybody else in the room. |
| 196 | // TODO(B3N30): Check for empty names, spaces, etc. | 204 | // TODO(B3N30): Check for empty names, spaces, etc. |
| 197 | for (const Member& member : members) { | 205 | return std::all_of(members.begin(), members.end(), |
| 198 | if (member.nickname == nickname) { | 206 | [&nickname](const auto& member) { return member.nickname != nickname; }); |
| 199 | return false; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | return true; | ||
| 203 | } | 207 | } |
| 204 | 208 | ||
| 205 | bool Room::RoomImpl::IsValidMacAddress(const MacAddress& address) const { | 209 | bool Room::RoomImpl::IsValidMacAddress(const MacAddress& address) const { |
| 206 | // A MAC address is valid if it is not already taken by anybody else in the room. | 210 | // A MAC address is valid if it is not already taken by anybody else in the room. |
| 207 | for (const Member& member : members) { | 211 | return std::all_of(members.begin(), members.end(), |
| 208 | if (member.mac_address == address) { | 212 | [&address](const auto& member) { return member.mac_address != address; }); |
| 209 | return false; | ||
| 210 | } | ||
| 211 | } | ||
| 212 | return true; | ||
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | void Room::RoomImpl::SendNameCollision(ENetPeer* client) { | 215 | void Room::RoomImpl::SendNameCollision(ENetPeer* client) { |
| @@ -248,7 +248,7 @@ void Room::RoomImpl::BroadcastRoomInformation() { | |||
| 248 | packet << room_information.name; | 248 | packet << room_information.name; |
| 249 | packet << room_information.member_slots; | 249 | packet << room_information.member_slots; |
| 250 | 250 | ||
| 251 | packet << static_cast<uint32_t>(members.size()); | 251 | packet << static_cast<u32>(members.size()); |
| 252 | for (const auto& member : members) { | 252 | for (const auto& member : members) { |
| 253 | packet << member.nickname; | 253 | packet << member.nickname; |
| 254 | packet << member.mac_address; | 254 | packet << member.mac_address; |
| @@ -262,10 +262,11 @@ void Room::RoomImpl::BroadcastRoomInformation() { | |||
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | MacAddress Room::RoomImpl::GenerateMacAddress() { | 264 | MacAddress Room::RoomImpl::GenerateMacAddress() { |
| 265 | MacAddress result_mac = NintendoOUI; | 265 | MacAddress result_mac = |
| 266 | NintendoOUI; // The first three bytes of each MAC address will be the NintendoOUI | ||
| 266 | std::uniform_int_distribution<> dis(0x00, 0xFF); // Random byte between 0 and 0xFF | 267 | std::uniform_int_distribution<> dis(0x00, 0xFF); // Random byte between 0 and 0xFF |
| 267 | do { | 268 | do { |
| 268 | for (int i = 3; i < result_mac.size(); ++i) { | 269 | for (size_t i = 3; i < result_mac.size(); ++i) { |
| 269 | result_mac[i] = dis(random_gen); | 270 | result_mac[i] = dis(random_gen); |
| 270 | } | 271 | } |
| 271 | } while (!IsValidMacAddress(result_mac)); | 272 | } while (!IsValidMacAddress(result_mac)); |
| @@ -273,9 +274,33 @@ MacAddress Room::RoomImpl::GenerateMacAddress() { | |||
| 273 | } | 274 | } |
| 274 | 275 | ||
| 275 | void Room::RoomImpl::HandleWifiPacket(const ENetEvent* event) { | 276 | void Room::RoomImpl::HandleWifiPacket(const ENetEvent* event) { |
| 276 | for (auto it = members.begin(); it != members.end(); ++it) { | 277 | Packet in_packet; |
| 277 | if (it->peer != event->peer) | 278 | in_packet.Append(event->packet->data, event->packet->dataLength); |
| 278 | enet_peer_send(it->peer, 0, event->packet); | 279 | in_packet.IgnoreBytes(sizeof(MessageID)); |
| 280 | in_packet.IgnoreBytes(sizeof(u8)); // WifiPacket Type | ||
| 281 | in_packet.IgnoreBytes(sizeof(u8)); // WifiPacket Channel | ||
| 282 | in_packet.IgnoreBytes(sizeof(MacAddress)); // WifiPacket Transmitter Address | ||
| 283 | MacAddress destination_address; | ||
| 284 | in_packet >> destination_address; | ||
| 285 | |||
| 286 | Packet out_packet; | ||
| 287 | out_packet.Append(event->packet->data, event->packet->dataLength); | ||
| 288 | ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(), | ||
| 289 | ENET_PACKET_FLAG_RELIABLE); | ||
| 290 | |||
| 291 | if (destination_address == BroadcastMac) { // Send the data to everyone except the sender | ||
| 292 | for (const auto& member : members) { | ||
| 293 | if (member.peer != event->peer) | ||
| 294 | enet_peer_send(member.peer, 0, event->packet); | ||
| 295 | } | ||
| 296 | } else { // Send the data only to the destination client | ||
| 297 | auto member = std::find_if(members.begin(), members.end(), | ||
| 298 | [destination_address](const Member& member) -> bool { | ||
| 299 | return member.mac_address == destination_address; | ||
| 300 | }); | ||
| 301 | if (member != members.end()) { | ||
| 302 | enet_peer_send(member->peer, 0, enet_packet); | ||
| 303 | } | ||
| 279 | } | 304 | } |
| 280 | enet_host_flush(server); | 305 | enet_host_flush(server); |
| 281 | } | 306 | } |
| @@ -287,7 +312,7 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) { | |||
| 287 | in_packet.IgnoreBytes(sizeof(MessageID)); | 312 | in_packet.IgnoreBytes(sizeof(MessageID)); |
| 288 | std::string message; | 313 | std::string message; |
| 289 | in_packet >> message; | 314 | in_packet >> message; |
| 290 | auto CompareNetworkAddress = [&](const Member member) -> bool { | 315 | auto CompareNetworkAddress = [event](const Member member) -> bool { |
| 291 | return member.peer == event->peer; | 316 | return member.peer == event->peer; |
| 292 | }; | 317 | }; |
| 293 | const auto sending_member = std::find_if(members.begin(), members.end(), CompareNetworkAddress); | 318 | const auto sending_member = std::find_if(members.begin(), members.end(), CompareNetworkAddress); |
| @@ -309,13 +334,30 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) { | |||
| 309 | enet_host_flush(server); | 334 | enet_host_flush(server); |
| 310 | } | 335 | } |
| 311 | 336 | ||
| 337 | void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) { | ||
| 338 | Packet in_packet; | ||
| 339 | in_packet.Append(event->packet->data, event->packet->dataLength); | ||
| 340 | |||
| 341 | in_packet.IgnoreBytes(sizeof(MessageID)); | ||
| 342 | std::string game_name; | ||
| 343 | in_packet >> game_name; | ||
| 344 | auto member = | ||
| 345 | std::find_if(members.begin(), members.end(), | ||
| 346 | [event](const Member& member) -> bool { return member.peer == event->peer; }); | ||
| 347 | if (member != members.end()) { | ||
| 348 | member->game_name = game_name; | ||
| 349 | BroadcastRoomInformation(); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 312 | void Room::RoomImpl::HandleClientDisconnection(ENetPeer* client) { | 353 | void Room::RoomImpl::HandleClientDisconnection(ENetPeer* client) { |
| 313 | // Remove the client from the members list. | 354 | // Remove the client from the members list. |
| 314 | members.erase(std::remove_if(members.begin(), members.end(), | 355 | members.erase(std::remove_if(members.begin(), members.end(), |
| 315 | [&](const Member& member) { return member.peer == client; }), | 356 | [client](const Member& member) { return member.peer == client; }), |
| 316 | members.end()); | 357 | members.end()); |
| 317 | 358 | ||
| 318 | // Announce the change to all clients. | 359 | // Announce the change to all clients. |
| 360 | enet_peer_disconnect(client, 0); | ||
| 319 | BroadcastRoomInformation(); | 361 | BroadcastRoomInformation(); |
| 320 | } | 362 | } |
| 321 | 363 | ||
| @@ -327,7 +369,6 @@ Room::~Room() = default; | |||
| 327 | void Room::Create(const std::string& name, const std::string& server_address, u16 server_port) { | 369 | void Room::Create(const std::string& name, const std::string& server_address, u16 server_port) { |
| 328 | ENetAddress address; | 370 | ENetAddress address; |
| 329 | address.host = ENET_HOST_ANY; | 371 | address.host = ENET_HOST_ANY; |
| 330 | enet_address_set_host(&address, server_address.c_str()); | ||
| 331 | address.port = server_port; | 372 | address.port = server_port; |
| 332 | 373 | ||
| 333 | room_impl->server = enet_host_create(&address, MaxConcurrentConnections, NumChannels, 0, 0); | 374 | room_impl->server = enet_host_create(&address, MaxConcurrentConnections, NumChannels, 0, 0); |
| @@ -357,6 +398,9 @@ void Room::Destroy() { | |||
| 357 | } | 398 | } |
| 358 | room_impl->room_information = {}; | 399 | room_impl->room_information = {}; |
| 359 | room_impl->server = nullptr; | 400 | room_impl->server = nullptr; |
| 401 | room_impl->members.clear(); | ||
| 402 | room_impl->room_information.member_slots = 0; | ||
| 403 | room_impl->room_information.name.clear(); | ||
| 360 | } | 404 | } |
| 361 | 405 | ||
| 362 | } // namespace Network | 406 | } // namespace Network |