void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { Packet packet; packet.Append(event->packet->data, event->packet->dataLength); packet.IgnoreBytes(sizeof(u8)); // Ignore the message type std::string nickname; packet >> nickname; MacAddress preferred_mac; packet >> preferred_mac; u32 client_version; packet >> client_version; std::string pass; packet >> pass; if (pass != password) { SendWrongPassword(event->peer); return; } if (!IsValidNickname(nickname)) { SendNameCollision(event->peer); return; } if (preferred_mac != NoPreferredMac) { // Verify if the preferred mac is available if (!IsValidMacAddress(preferred_mac)) { SendMacCollision(event->peer); return; } } else { // Assign a MAC address of this client automatically preferred_mac = GenerateMacAddress(); } if (client_version != network_version) { SendVersionMismatch(event->peer); return; } // At this point the client is ready to be added to the room. Member member{}; member.mac_address = preferred_mac; member.nickname = nickname; member.peer = event->peer; { std::lock_guard<std::mutex> lock(member_mutex); members.push_back(std::move(member)); } // Notify everyone that the room information has changed. BroadcastRoomInformation(); SendJoinSuccess(event->peer, preferred_mac); }
void Room::RoomImpl::HandleClientDisconnection(ENetPeer* client) { // Remove the client from the members list. { std::lock_guard<std::mutex> lock(member_mutex); members.erase( std::remove_if(members.begin(), members.end(), [client](const Member& member) { return member.peer == client; }), members.end()); } // Announce the change to all clients. enet_peer_disconnect(client, 0); BroadcastRoomInformation(); }
void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) { Packet in_packet; in_packet.Append(event->packet->data, event->packet->dataLength); in_packet.IgnoreBytes(sizeof(u8)); // Ignore the message type GameInfo game_info; in_packet >> game_info.name; in_packet >> game_info.id; { std::lock_guard<std::mutex> lock(member_mutex); auto member = std::find_if(members.begin(), members.end(), [event](const Member& member) -> bool { return member.peer == event->peer; }); if (member != members.end()) { member->game_info = game_info; } } BroadcastRoomInformation(); }
void Room::RoomImpl::HandleClientDisconnection(ENetPeer* client) { // Remove the client from the members list. std::string nickname, username; { std::lock_guard lock(member_mutex); auto member = std::find_if(members.begin(), members.end(), [client](const Member& member) { return member.peer == client; }); if (member != members.end()) { nickname = member->nickname; username = member->user_data.username; members.erase(member); } } // Announce the change to all clients. enet_peer_disconnect(client, 0); if (!nickname.empty()) SendStatusMessage(IdMemberLeave, nickname, username); BroadcastRoomInformation(); }
void Room::RoomImpl::HandleModKickPacket(const ENetEvent* event) { if (!HasModPermission(event->peer)) { SendModPermissionDenied(event->peer); return; } Packet packet; packet.Append(event->packet->data, event->packet->dataLength); packet.IgnoreBytes(sizeof(u8)); // Ignore the message type std::string nickname; packet >> nickname; std::string username; { std::lock_guard lock(member_mutex); const auto target_member = std::find_if(members.begin(), members.end(), [&nickname](const auto& member) { return member.nickname == nickname; }); if (target_member == members.end()) { SendModNoSuchUser(event->peer); return; } // Notify the kicked member SendUserKicked(target_member->peer); username = target_member->user_data.username; enet_peer_disconnect(target_member->peer, 0); members.erase(target_member); } // Announce the change to all clients. SendStatusMessage(IdMemberKicked, nickname, username); BroadcastRoomInformation(); }
void Room::RoomImpl::HandleModBanPacket(const ENetEvent* event) { if (!HasModPermission(event->peer)) { SendModPermissionDenied(event->peer); return; } Packet packet; packet.Append(event->packet->data, event->packet->dataLength); packet.IgnoreBytes(sizeof(u8)); // Ignore the message type std::string nickname; packet >> nickname; std::string username; std::string ip; { std::lock_guard lock(member_mutex); const auto target_member = std::find_if(members.begin(), members.end(), [&nickname](const auto& member) { return member.nickname == nickname; }); if (target_member == members.end()) { SendModNoSuchUser(event->peer); return; } // Notify the banned member SendUserBanned(target_member->peer); nickname = target_member->nickname; username = target_member->user_data.username; char ip_raw[256]; enet_address_get_host_ip(&target_member->peer->address, ip_raw, sizeof(ip_raw) - 1); ip = ip_raw; enet_peer_disconnect(target_member->peer, 0); members.erase(target_member); } { std::lock_guard lock(ban_list_mutex); if (!username.empty()) { // Ban the forum username if (std::find(username_ban_list.begin(), username_ban_list.end(), username) == username_ban_list.end()) { username_ban_list.emplace_back(username); } } // Ban the member's IP as well if (std::find(ip_ban_list.begin(), ip_ban_list.end(), ip) == ip_ban_list.end()) { ip_ban_list.emplace_back(ip); } } // Announce the change to all clients. SendStatusMessage(IdMemberBanned, nickname, username); BroadcastRoomInformation(); }
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 std::string nickname; packet >> nickname; std::string console_id_hash; packet >> console_id_hash; MacAddress preferred_mac; packet >> preferred_mac; u32 client_version; packet >> client_version; std::string pass; packet >> pass; std::string token; packet >> token; if (pass != password) { SendWrongPassword(event->peer); return; } if (!IsValidNickname(nickname)) { SendNameCollision(event->peer); return; } if (preferred_mac != NoPreferredMac) { // Verify if the preferred mac is available if (!IsValidMacAddress(preferred_mac)) { SendMacCollision(event->peer); return; } } else { // Assign a MAC address of this client automatically preferred_mac = GenerateMacAddress(); } if (!IsValidConsoleId(console_id_hash)) { SendConsoleIdCollision(event->peer); return; } if (client_version != network_version) { SendVersionMismatch(event->peer); return; } // At this point the client is ready to be added to the room. Member member{}; member.mac_address = preferred_mac; member.console_id_hash = console_id_hash; member.nickname = nickname; member.peer = event->peer; std::string uid; { std::lock_guard lock(verify_UID_mutex); uid = verify_UID; } member.user_data = verify_backend->LoadUserData(uid, token); { std::lock_guard lock(ban_list_mutex); // Check username ban if (!member.user_data.username.empty() && std::find(username_ban_list.begin(), username_ban_list.end(), member.user_data.username) != username_ban_list.end()) { SendUserBanned(event->peer); return; } // Check IP ban char ip_raw[256]; enet_address_get_host_ip(&event->peer->address, ip_raw, sizeof(ip_raw) - 1); std::string ip = ip_raw; if (std::find(ip_ban_list.begin(), ip_ban_list.end(), ip) != ip_ban_list.end()) { SendUserBanned(event->peer); return; } } // Notify everyone that the user has joined. SendStatusMessage(IdMemberJoin, member.nickname, member.user_data.username); { std::lock_guard lock(member_mutex); members.push_back(std::move(member)); } // Notify everyone that the room information has changed. BroadcastRoomInformation(); if (HasModPermission(event->peer)) { SendJoinSuccessAsMod(event->peer, preferred_mac); } else { SendJoinSuccess(event->peer, preferred_mac); } }