mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Network: Made send async in RoomMember
This commit is contained in:
		
							parent
							
								
									859be35d54
								
							
						
					
					
						commit
						a0626221a5
					
				
					 4 changed files with 70 additions and 25 deletions
				
			
		|  | @ -73,6 +73,11 @@ public: | |||
|      */ | ||||
|     void SendMacCollision(ENetPeer* client); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sends a ID_ROOM_VERSION_MISMATCH message telling the client that the MAC is invalid. | ||||
|      */ | ||||
|     void SendVersionMismatch(ENetPeer* client); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Notifies the member that its connection attempt was successful, | ||||
|      * and it is now part of the room. | ||||
|  | @ -170,6 +175,9 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
|     MacAddress preferred_mac; | ||||
|     packet >> preferred_mac; | ||||
| 
 | ||||
|     u32 client_version; | ||||
|     packet >> client_version; | ||||
| 
 | ||||
|     if (!IsValidNickname(nickname)) { | ||||
|         SendNameCollision(event->peer); | ||||
|         return; | ||||
|  | @ -186,6 +194,11 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
|         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; | ||||
|  | @ -232,6 +245,17 @@ void Room::RoomImpl::SendMacCollision(ENetPeer* client) { | |||
|     enet_host_flush(server); | ||||
| } | ||||
| 
 | ||||
| void Room::RoomImpl::SendVersionMismatch(ENetPeer* client) { | ||||
|     Packet packet; | ||||
|     packet << static_cast<MessageID>(IdVersionMismatch); | ||||
|     packet << network_version; | ||||
| 
 | ||||
|     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::SendJoinSuccess(ENetPeer* client, MacAddress mac_address) { | ||||
|     Packet packet; | ||||
|     packet << static_cast<MessageID>(IdJoinSuccess); | ||||
|  | @ -291,7 +315,7 @@ void Room::RoomImpl::HandleWifiPacket(const ENetEvent* event) { | |||
|     if (destination_address == BroadcastMac) { // Send the data to everyone except the sender
 | ||||
|         for (const auto& member : members) { | ||||
|             if (member.peer != event->peer) | ||||
|                 enet_peer_send(member.peer, 0, event->packet); | ||||
|                 enet_peer_send(member.peer, 0, enet_packet); | ||||
|         } | ||||
|     } else { // Send the data only to the destination client
 | ||||
|         auto member = std::find_if(members.begin(), members.end(), | ||||
|  | @ -327,9 +351,9 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) { | |||
| 
 | ||||
|     ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(), | ||||
|                                                  ENET_PACKET_FLAG_RELIABLE); | ||||
|     for (auto it = members.begin(); it != members.end(); ++it) { | ||||
|         if (it->peer != event->peer) | ||||
|             enet_peer_send(it->peer, 0, enet_packet); | ||||
|     for (const auto& member : members) { | ||||
|         if (member.peer != event->peer) | ||||
|             enet_peer_send(member.peer, 0, enet_packet); | ||||
|     } | ||||
|     enet_host_flush(server); | ||||
| } | ||||
|  | @ -369,6 +393,9 @@ Room::~Room() = default; | |||
| void Room::Create(const std::string& name, const std::string& server_address, u16 server_port) { | ||||
|     ENetAddress address; | ||||
|     address.host = ENET_HOST_ANY; | ||||
|     if (!server_address.empty()) { | ||||
|         enet_address_set_host(&address, server_address.c_str()); | ||||
|     } | ||||
|     address.port = server_port; | ||||
| 
 | ||||
|     room_impl->server = enet_host_create(&address, MaxConcurrentConnections, NumChannels, 0, 0); | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ | |||
| 
 | ||||
| namespace Network { | ||||
| 
 | ||||
| constexpr u32 network_version = 1; ///< The version of this Room and RoomMember
 | ||||
| 
 | ||||
| constexpr u16 DefaultRoomPort = 1234; | ||||
| constexpr size_t NumChannels = 1; // Number of channels used for the connection
 | ||||
| 
 | ||||
|  | @ -37,7 +39,9 @@ enum RoomMessageTypes { | |||
|     IdWifiPacket, | ||||
|     IdChatMessage, | ||||
|     IdNameCollision, | ||||
|     IdMacCollision | ||||
|     IdMacCollision, | ||||
|     IdVersionMismatch, | ||||
|     IdCloseRoom | ||||
| }; | ||||
| 
 | ||||
| /// This is what a server [person creating a server] would use.
 | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <atomic> | ||||
| #include <list> | ||||
| #include <mutex> | ||||
| #include <thread> | ||||
| #include "common/assert.h" | ||||
|  | @ -33,8 +34,10 @@ public: | |||
| 
 | ||||
|     std::mutex network_mutex; ///< Mutex that controls access to the `client` variable.
 | ||||
|     /// Thread that receives and dispatches network packets
 | ||||
|     std::unique_ptr<std::thread> receive_thread; | ||||
|     void ReceiveLoop(); | ||||
|     std::unique_ptr<std::thread> loop_thread; | ||||
|     std::mutex send_list_mutex;  ///< Mutex that controls access to the `send_list` variable.
 | ||||
|     std::list<Packet> send_list; ///< A list that stores all packets to send the async
 | ||||
|     void MemberLoop(); | ||||
|     void StartLoop(); | ||||
| 
 | ||||
|     /**
 | ||||
|  | @ -91,7 +94,7 @@ bool RoomMember::RoomMemberImpl::IsConnected() const { | |||
|     return state == State::Joining || state == State::Joined; | ||||
| } | ||||
| 
 | ||||
| void RoomMember::RoomMemberImpl::ReceiveLoop() { | ||||
| void RoomMember::RoomMemberImpl::MemberLoop() { | ||||
|     // Receive packets while the connection is open
 | ||||
|     while (IsConnected()) { | ||||
|         std::lock_guard<std::mutex> lock(network_mutex); | ||||
|  | @ -121,6 +124,9 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() { | |||
|                 case IdMacCollision: | ||||
|                     SetState(State::MacCollision); | ||||
|                     break; | ||||
|                 case IdVersionMismatch: | ||||
|                     SetState(State::WrongVersion); | ||||
|                     break; | ||||
|                 default: | ||||
|                     break; | ||||
|                 } | ||||
|  | @ -128,22 +134,30 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() { | |||
|                 break; | ||||
|             case ENET_EVENT_TYPE_DISCONNECT: | ||||
|                 SetState(State::LostConnection); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         { | ||||
|             std::lock_guard<std::mutex> lock(send_list_mutex); | ||||
|             for (const auto& packet : send_list) { | ||||
|                 ENetPacket* enetPacket = enet_packet_create(packet.GetData(), packet.GetDataSize(), | ||||
|                                                             ENET_PACKET_FLAG_RELIABLE); | ||||
|                 enet_peer_send(server, 0, enetPacket); | ||||
|             } | ||||
|             enet_host_flush(client); | ||||
|             send_list.clear(); | ||||
|         } | ||||
|     } | ||||
|     Disconnect(); | ||||
| }; | ||||
| 
 | ||||
| void RoomMember::RoomMemberImpl::StartLoop() { | ||||
|     receive_thread = std::make_unique<std::thread>(&RoomMember::RoomMemberImpl::ReceiveLoop, this); | ||||
|     loop_thread = std::make_unique<std::thread>(&RoomMember::RoomMemberImpl::MemberLoop, this); | ||||
| } | ||||
| 
 | ||||
| void RoomMember::RoomMemberImpl::Send(Packet& packet) { | ||||
|     std::lock_guard<std::mutex> lock(network_mutex); | ||||
|     ENetPacket* enetPacket = | ||||
|         enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); | ||||
|     enet_peer_send(server, 0, enetPacket); | ||||
|     enet_host_flush(client); | ||||
|     std::lock_guard<std::mutex> lock(send_list_mutex); | ||||
|     send_list.push_back(std::move(packet)); | ||||
| } | ||||
| 
 | ||||
| void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, | ||||
|  | @ -152,6 +166,7 @@ void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, | |||
|     packet << static_cast<MessageID>(IdJoinRequest); | ||||
|     packet << nickname; | ||||
|     packet << preferred_mac; | ||||
|     packet << network_version; | ||||
|     Send(packet); | ||||
| } | ||||
| 
 | ||||
|  | @ -238,11 +253,9 @@ void RoomMember::RoomMemberImpl::Disconnect() { | |||
|     room_information.member_slots = 0; | ||||
|     room_information.name.clear(); | ||||
| 
 | ||||
|     if (server) { | ||||
|         enet_peer_disconnect(server, 0); | ||||
|     } else { | ||||
|     if (!server) | ||||
|         return; | ||||
|     } | ||||
|     enet_peer_disconnect(server, 0); | ||||
| 
 | ||||
|     ENetEvent event; | ||||
|     while (enet_host_service(client, &event, ConnectionTimeoutMs) > 0) { | ||||
|  | @ -296,14 +309,14 @@ RoomInformation RoomMember::GetRoomInformation() const { | |||
| void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port, | ||||
|                       u16 client_port) { | ||||
|     // If the member is connected, kill the connection first
 | ||||
|     if (room_member_impl->receive_thread && room_member_impl->receive_thread->joinable()) { | ||||
|     if (room_member_impl->loop_thread && room_member_impl->loop_thread->joinable()) { | ||||
|         room_member_impl->SetState(State::Error); | ||||
|         room_member_impl->receive_thread->join(); | ||||
|         room_member_impl->receive_thread.reset(); | ||||
|         room_member_impl->loop_thread->join(); | ||||
|         room_member_impl->loop_thread.reset(); | ||||
|     } | ||||
|     // If the thread isn't running but the ptr still exists, reset it
 | ||||
|     else if (room_member_impl->receive_thread) { | ||||
|         room_member_impl->receive_thread.reset(); | ||||
|     else if (room_member_impl->loop_thread) { | ||||
|         room_member_impl->loop_thread.reset(); | ||||
|     } | ||||
| 
 | ||||
|     ENetAddress address{}; | ||||
|  | @ -361,8 +374,8 @@ void RoomMember::SendGameName(const std::string& game_name) { | |||
| 
 | ||||
| void RoomMember::Leave() { | ||||
|     room_member_impl->SetState(State::Idle); | ||||
|     room_member_impl->receive_thread->join(); | ||||
|     room_member_impl->receive_thread.reset(); | ||||
|     room_member_impl->loop_thread->join(); | ||||
|     room_member_impl->loop_thread.reset(); | ||||
| } | ||||
| 
 | ||||
| } // namespace Network
 | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ public: | |||
|         // 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
 | ||||
|         CouldNotConnect ///< The room is not responding to a connection attempt
 | ||||
|     }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue