From 589dc083a58425cadd8390ddd81854dcf054dd27 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 8 Jul 2017 15:24:47 +0200 Subject: Network: Threads for Room and RoomMember --- src/network/room_member.cpp | 79 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 8 deletions(-) (limited to 'src/network/room_member.cpp') diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index c87f009f4..e1a0dfdab 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include +#include #include "common/assert.h" #include "enet/enet.h" #include "network/room_member.h" @@ -16,10 +19,65 @@ public: ENetPeer* server = nullptr; ///< The server peer the client is connected to std::atomic state{State::Idle}; ///< Current state of the RoomMember. + void SetState(const State new_state); + bool IsConnected() const; std::string nickname; ///< The nickname of this member. + + std::mutex network_mutex; ///< Mutex that controls access to the `client` variable. + /// Thread that receives and dispatches network packets + std::unique_ptr receive_thread; + void ReceiveLoop(); + void StartLoop(); }; +// RoomMemberImpl +void RoomMember::RoomMemberImpl::SetState(const State new_state) { + state = new_state; + // TODO(B3N30): Invoke the callback functions +} + +bool RoomMember::RoomMemberImpl::IsConnected() const { + return state == State::Joining || state == State::Joined; +} + +void RoomMember::RoomMemberImpl::ReceiveLoop() { + // Receive packets while the connection is open + while (IsConnected()) { + std::lock_guard lock(network_mutex); + ENetEvent event; + if (enet_host_service(client, &event, 1000) > 0) { + if (event.type == ENET_EVENT_TYPE_RECEIVE) { + switch (event.packet->data[0]) { + // TODO(B3N30): Handle the other message types + case IdNameCollision: + SetState(State::NameCollision); + enet_packet_destroy(event.packet); + enet_peer_disconnect(server, 0); + enet_peer_reset(server); + return; + break; + case IdMacCollision: + SetState(State::MacCollision); + enet_packet_destroy(event.packet); + enet_peer_disconnect(server, 0); + enet_peer_reset(server); + return; + break; + default: + break; + } + enet_packet_destroy(event.packet); + } + } + } +}; + +void RoomMember::RoomMemberImpl::StartLoop() { + receive_thread = std::make_unique(&RoomMember::RoomMemberImpl::ReceiveLoop, this); +} + +// RoomMember RoomMember::RoomMember() : room_member_impl{std::make_unique()} { room_member_impl->client = enet_host_create(nullptr, 1, NumChannels, 0, 0); ASSERT_MSG(room_member_impl->client != nullptr, "Could not create client"); @@ -44,7 +102,7 @@ void RoomMember::Join(const std::string& nick, const char* server_addr, u16 serv enet_host_connect(room_member_impl->client, &address, NumChannels, 0); if (!room_member_impl->server) { - room_member_impl->state = State::Error; + room_member_impl->SetState(State::Error); return; } @@ -52,22 +110,27 @@ void RoomMember::Join(const std::string& nick, const char* server_addr, u16 serv int net = enet_host_service(room_member_impl->client, &event, ConnectionTimeoutMs); if (net > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { room_member_impl->nickname = nick; - room_member_impl->state = State::Joining; + room_member_impl->SetState(State::Joining); + room_member_impl->StartLoop(); // TODO(B3N30): Send a join request with the nickname to the server - // TODO(B3N30): Start the receive thread } else { - room_member_impl->state = State::CouldNotConnect; + room_member_impl->SetState(State::CouldNotConnect); } } bool RoomMember::IsConnected() const { - return room_member_impl->state == State::Joining || room_member_impl->state == State::Joined; + return room_member_impl->IsConnected(); } void RoomMember::Leave() { - enet_peer_disconnect(room_member_impl->server, 0); - room_member_impl->state = State::Idle; - // TODO(B3N30): Close the receive thread + ASSERT_MSG(room_member_impl->receive_thread != nullptr, "Must be in a room to leave it."); + { + std::lock_guard lock(room_member_impl->network_mutex); + enet_peer_disconnect(room_member_impl->server, 0); + room_member_impl->SetState(State::Idle); + } + room_member_impl->receive_thread->join(); + room_member_impl->receive_thread.reset(); enet_peer_reset(room_member_impl->server); } -- cgit v1.2.3 From 77677e205ebf1a6c47114ac1d449fc78be250c6d Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 8 Jul 2017 18:31:35 +0200 Subject: Network: Send JoinRequest and handle the answer in RoomMember --- src/network/room_member.cpp | 109 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) (limited to 'src/network/room_member.cpp') diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index e1a0dfdab..09573ee43 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -7,6 +7,7 @@ #include #include "common/assert.h" #include "enet/enet.h" +#include "network/packet.h" #include "network/room_member.h" namespace Network { @@ -18,17 +19,49 @@ public: ENetHost* client = nullptr; ///< ENet network interface. ENetPeer* server = nullptr; ///< The server peer the client is connected to + /// Information about the clients connected to the same room as us. + MemberList member_information; + /// Information about the room we're connected to. + RoomInformation room_information; + std::atomic state{State::Idle}; ///< Current state of the RoomMember. void SetState(const State new_state); bool IsConnected() const; - std::string nickname; ///< The nickname of this member. + std::string nickname; ///< The nickname of this member. + MacAddress mac_address; ///< The mac_address of this member. std::mutex network_mutex; ///< Mutex that controls access to the `client` variable. /// Thread that receives and dispatches network packets std::unique_ptr receive_thread; void ReceiveLoop(); void StartLoop(); + + /** + * Sends data to the room. It will be send on channel 0 with flag RELIABLE + * @param packet The data to send + */ + void Send(Packet& packet); + /** + * Sends a request to the server, asking for permission to join a room with the specified + * nickname and preferred mac. + * @params nickname The desired nickname. + * @params preferred_mac The preferred MAC address to use in the room, the NoPreferredMac tells + * the server to assign one for us. + */ + void SendJoinRequest(const std::string& nickname, + const MacAddress& preferred_mac = NoPreferredMac); + + /** + * Extracts a MAC Address from a received ENet packet. + * @param event The ENet event that was received. + */ + void HandleJoinPacket(const ENetEvent* event); + /** + * Extracts RoomInformation and MemberInformation from a received RakNet packet. + * @param event The ENet event that was received. + */ + void HandleRoomInformationPacket(const ENetEvent* event); }; // RoomMemberImpl @@ -50,6 +83,17 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() { if (event.type == ENET_EVENT_TYPE_RECEIVE) { switch (event.packet->data[0]) { // TODO(B3N30): Handle the other message types + case IdRoomInformation: + HandleRoomInformationPacket(&event); + break; + case IdJoinSuccess: + // The join request was successful, we are now in the room. + // If we joined successfully, there must be at least one client in the room: us. + ASSERT_MSG(member_information.size() > 0, + "We have not yet received member information."); + HandleJoinPacket(&event); // Get the MAC Address for the client + SetState(State::Joined); + break; case IdNameCollision: SetState(State::NameCollision); enet_packet_destroy(event.packet); @@ -77,6 +121,59 @@ void RoomMember::RoomMemberImpl::StartLoop() { receive_thread = std::make_unique(&RoomMember::RoomMemberImpl::ReceiveLoop, this); } +void RoomMember::RoomMemberImpl::Send(Packet& packet) { + ENetPacket* enetPacket = + enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(server, 0, enetPacket); + enet_host_flush(client); +} + +void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, + const MacAddress& preferred_mac) { + Packet packet; + packet << static_cast(IdJoinRequest); + packet << nickname; + packet << preferred_mac; + Send(packet); +} + +void RoomMember::RoomMemberImpl::HandleRoomInformationPacket(const ENetEvent* event) { + Packet packet; + packet.Append(event->packet->data, event->packet->dataLength); + + // Ignore the first byte, which is the message id. + packet.IgnoreBytes(sizeof(MessageID)); + + RoomInformation info{}; + packet >> info.name; + packet >> info.member_slots; + room_information.name = info.name; + room_information.member_slots = info.member_slots; + + uint32_t num_members; + packet >> num_members; + member_information.resize(num_members); + + for (auto& member : member_information) { + packet >> member.nickname; + packet >> member.mac_address; + packet >> member.game_name; + } + // TODO(B3N30): Invoke callbacks +} + +void RoomMember::RoomMemberImpl::HandleJoinPacket(const ENetEvent* event) { + Packet packet; + packet.Append(event->packet->data, event->packet->dataLength); + + // Ignore the first byte, which is the message id. + packet.IgnoreBytes(sizeof(MessageID)); + + // Parse the MAC Address from the BitStream + packet >> mac_address; + // TODO(B3N30): Invoke callbacks +} + // RoomMember RoomMember::RoomMember() : room_member_impl{std::make_unique()} { room_member_impl->client = enet_host_create(nullptr, 1, NumChannels, 0, 0); @@ -92,6 +189,14 @@ RoomMember::State RoomMember::GetState() const { return room_member_impl->state; } +const RoomMember::MemberList& RoomMember::GetMemberInformation() const { + return room_member_impl->member_information; +} + +RoomInformation RoomMember::GetRoomInformation() const { + return room_member_impl->room_information; +} + void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port, u16 client_port) { ENetAddress address{}; @@ -112,7 +217,7 @@ void RoomMember::Join(const std::string& nick, const char* server_addr, u16 serv room_member_impl->nickname = nick; room_member_impl->SetState(State::Joining); room_member_impl->StartLoop(); - // TODO(B3N30): Send a join request with the nickname to the server + room_member_impl->SendJoinRequest(nick); } else { room_member_impl->SetState(State::CouldNotConnect); } -- cgit v1.2.3 From 641346c15c0091d59259f6acc5f8789efe16c937 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 9 Jul 2017 10:40:11 +0200 Subject: Network: Enable to send WifiPackets --- src/network/room_member.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'src/network/room_member.cpp') diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index 09573ee43..f919e4de0 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -62,6 +62,12 @@ public: * @param event The ENet event that was received. */ void HandleRoomInformationPacket(const ENetEvent* event); + + /** + * Extracts a WifiPacket from a received ENet packet. + * @param event The ENet event that was received. + */ + void HandleWifiPackets(const ENetEvent* event); }; // RoomMemberImpl @@ -174,6 +180,34 @@ void RoomMember::RoomMemberImpl::HandleJoinPacket(const ENetEvent* event) { // TODO(B3N30): Invoke callbacks } +void RoomMember::RoomMemberImpl::HandleWifiPackets(const ENetEvent* event) { + WifiPacket wifi_packet{}; + Packet packet; + packet.Append(event->packet->data, event->packet->dataLength); + + // Ignore the first byte, which is the message id. + packet.IgnoreBytes(sizeof(MessageID)); + + // Parse the WifiPacket from the BitStream + uint8_t frame_type; + packet >> frame_type; + WifiPacket::PacketType type = static_cast(frame_type); + + wifi_packet.type = type; + packet >> wifi_packet.channel; + packet >> wifi_packet.transmitter_address; + packet >> wifi_packet.destination_address; + + uint32_t data_length; + packet >> data_length; + + std::vector data(data_length); + packet >> data; + + wifi_packet.data = std::move(data); + // TODO(B3N30): Invoke callbacks +} + // RoomMember RoomMember::RoomMember() : room_member_impl{std::make_unique()} { room_member_impl->client = enet_host_create(nullptr, 1, NumChannels, 0, 0); @@ -227,6 +261,18 @@ bool RoomMember::IsConnected() const { return room_member_impl->IsConnected(); } +void RoomMember::SendWifiPacket(const WifiPacket& wifi_packet) { + Packet packet; + packet << static_cast(IdWifiPacket); + packet << static_cast(wifi_packet.type); + packet << wifi_packet.channel; + packet << wifi_packet.transmitter_address; + packet << wifi_packet.destination_address; + packet << static_cast(wifi_packet.data.size()); + packet << wifi_packet.data; + room_member_impl->Send(packet); +} + void RoomMember::Leave() { ASSERT_MSG(room_member_impl->receive_thread != nullptr, "Must be in a room to leave it."); { -- cgit v1.2.3 From 42e57c121896818f9fbde5ddd9b7dbb5b2a267b1 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 9 Jul 2017 12:26:03 +0200 Subject: Network: Enable sending and receiving chat messages --- src/network/room_member.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'src/network/room_member.cpp') diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index f919e4de0..d68bb551d 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -68,6 +68,12 @@ public: * @param event The ENet event that was received. */ void HandleWifiPackets(const ENetEvent* event); + + /** + * Extracts a chat entry from a received ENet packet and adds it to the chat queue. + * @param event The ENet event that was received. + */ + void HandleChatPacket(const ENetEvent* event); }; // RoomMemberImpl @@ -89,6 +95,9 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() { if (event.type == ENET_EVENT_TYPE_RECEIVE) { switch (event.packet->data[0]) { // TODO(B3N30): Handle the other message types + case IdChatMessage: + HandleChatPacket(&event); + break; case IdRoomInformation: HandleRoomInformationPacket(&event); break; @@ -208,6 +217,19 @@ void RoomMember::RoomMemberImpl::HandleWifiPackets(const ENetEvent* event) { // TODO(B3N30): Invoke callbacks } +void RoomMember::RoomMemberImpl::HandleChatPacket(const ENetEvent* event) { + Packet packet; + packet.Append(event->packet->data, event->packet->dataLength); + + // Ignore the first byte, which is the message id. + packet.IgnoreBytes(sizeof(MessageID)); + + ChatEntry chat_entry{}; + packet >> chat_entry.nickname; + packet >> chat_entry.message; + // TODO(B3N30): Invoke callbacks +} + // RoomMember RoomMember::RoomMember() : room_member_impl{std::make_unique()} { room_member_impl->client = enet_host_create(nullptr, 1, NumChannels, 0, 0); @@ -273,6 +295,13 @@ void RoomMember::SendWifiPacket(const WifiPacket& wifi_packet) { room_member_impl->Send(packet); } +void RoomMember::SendChatMessage(const std::string& message) { + Packet packet; + packet << static_cast(IdChatMessage); + packet << message; + room_member_impl->Send(packet); +} + void RoomMember::Leave() { ASSERT_MSG(room_member_impl->receive_thread != nullptr, "Must be in a room to leave it."); { -- cgit v1.2.3 From 859be35d54fda177a237e0c24bc1eaca76f1936d Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sun, 9 Jul 2017 15:06:02 +0200 Subject: Network: Send the game title --- src/network/room_member.cpp | 97 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 23 deletions(-) (limited to 'src/network/room_member.cpp') diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index d68bb551d..ec67aa5be 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -74,6 +74,11 @@ public: * @param event The ENet event that was received. */ void HandleChatPacket(const ENetEvent* event); + + /** + * Disconnects the RoomMember from the Room + */ + void Disconnect(); }; // RoomMemberImpl @@ -92,7 +97,8 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() { std::lock_guard lock(network_mutex); ENetEvent event; if (enet_host_service(client, &event, 1000) > 0) { - if (event.type == ENET_EVENT_TYPE_RECEIVE) { + switch (event.type) { + case ENET_EVENT_TYPE_RECEIVE: switch (event.packet->data[0]) { // TODO(B3N30): Handle the other message types case IdChatMessage: @@ -111,25 +117,21 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() { break; case IdNameCollision: SetState(State::NameCollision); - enet_packet_destroy(event.packet); - enet_peer_disconnect(server, 0); - enet_peer_reset(server); - return; break; case IdMacCollision: SetState(State::MacCollision); - enet_packet_destroy(event.packet); - enet_peer_disconnect(server, 0); - enet_peer_reset(server); - return; break; default: break; } enet_packet_destroy(event.packet); + break; + case ENET_EVENT_TYPE_DISCONNECT: + SetState(State::LostConnection); } } } + Disconnect(); }; void RoomMember::RoomMemberImpl::StartLoop() { @@ -137,6 +139,7 @@ void RoomMember::RoomMemberImpl::StartLoop() { } void RoomMember::RoomMemberImpl::Send(Packet& packet) { + std::lock_guard lock(network_mutex); ENetPacket* enetPacket = enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(server, 0, enetPacket); @@ -165,7 +168,7 @@ void RoomMember::RoomMemberImpl::HandleRoomInformationPacket(const ENetEvent* ev room_information.name = info.name; room_information.member_slots = info.member_slots; - uint32_t num_members; + u32 num_members; packet >> num_members; member_information.resize(num_members); @@ -198,7 +201,7 @@ void RoomMember::RoomMemberImpl::HandleWifiPackets(const ENetEvent* event) { packet.IgnoreBytes(sizeof(MessageID)); // Parse the WifiPacket from the BitStream - uint8_t frame_type; + u8 frame_type; packet >> frame_type; WifiPacket::PacketType type = static_cast(frame_type); @@ -207,10 +210,10 @@ void RoomMember::RoomMemberImpl::HandleWifiPackets(const ENetEvent* event) { packet >> wifi_packet.transmitter_address; packet >> wifi_packet.destination_address; - uint32_t data_length; + u32 data_length; packet >> data_length; - std::vector data(data_length); + std::vector data(data_length); packet >> data; wifi_packet.data = std::move(data); @@ -230,6 +233,33 @@ void RoomMember::RoomMemberImpl::HandleChatPacket(const ENetEvent* event) { // TODO(B3N30): Invoke callbacks } +void RoomMember::RoomMemberImpl::Disconnect() { + member_information.clear(); + room_information.member_slots = 0; + room_information.name.clear(); + + if (server) { + enet_peer_disconnect(server, 0); + } else { + return; + } + + ENetEvent event; + while (enet_host_service(client, &event, ConnectionTimeoutMs) > 0) { + switch (event.type) { + case ENET_EVENT_TYPE_RECEIVE: + enet_packet_destroy(event.packet); // Ignore all incoming data + break; + case ENET_EVENT_TYPE_DISCONNECT: + server = nullptr; + return; + } + } + // didn't disconnect gracefully force disconnect + enet_peer_reset(server); + server = nullptr; +} + // RoomMember RoomMember::RoomMember() : room_member_impl{std::make_unique()} { room_member_impl->client = enet_host_create(nullptr, 1, NumChannels, 0, 0); @@ -249,16 +279,36 @@ const RoomMember::MemberList& RoomMember::GetMemberInformation() const { return room_member_impl->member_information; } +const std::string& RoomMember::GetNickname() const { + return room_member_impl->nickname; +} + +const MacAddress& RoomMember::GetMacAddress() const { + if (GetState() == State::Joined) + return room_member_impl->mac_address; + return MacAddress{}; +} + RoomInformation RoomMember::GetRoomInformation() const { return room_member_impl->room_information; } 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()) { + room_member_impl->SetState(State::Error); + room_member_impl->receive_thread->join(); + room_member_impl->receive_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(); + } + ENetAddress address{}; enet_address_set_host(&address, server_addr); address.port = server_port; - room_member_impl->server = enet_host_connect(room_member_impl->client, &address, NumChannels, 0); @@ -286,11 +336,11 @@ bool RoomMember::IsConnected() const { void RoomMember::SendWifiPacket(const WifiPacket& wifi_packet) { Packet packet; packet << static_cast(IdWifiPacket); - packet << static_cast(wifi_packet.type); + packet << static_cast(wifi_packet.type); packet << wifi_packet.channel; packet << wifi_packet.transmitter_address; packet << wifi_packet.destination_address; - packet << static_cast(wifi_packet.data.size()); + packet << static_cast(wifi_packet.data.size()); packet << wifi_packet.data; room_member_impl->Send(packet); } @@ -302,16 +352,17 @@ void RoomMember::SendChatMessage(const std::string& message) { room_member_impl->Send(packet); } +void RoomMember::SendGameName(const std::string& game_name) { + Packet packet; + packet << static_cast(IdSetGameName); + packet << game_name; + room_member_impl->Send(packet); +} + void RoomMember::Leave() { - ASSERT_MSG(room_member_impl->receive_thread != nullptr, "Must be in a room to leave it."); - { - std::lock_guard lock(room_member_impl->network_mutex); - enet_peer_disconnect(room_member_impl->server, 0); - room_member_impl->SetState(State::Idle); - } + room_member_impl->SetState(State::Idle); room_member_impl->receive_thread->join(); room_member_impl->receive_thread.reset(); - enet_peer_reset(room_member_impl->server); } } // namespace Network -- cgit v1.2.3 From a0626221a52056669c0b6d19b37d4189c1671fb7 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Fri, 14 Jul 2017 09:20:39 +0200 Subject: Network: Made send async in RoomMember --- src/network/room_member.cpp | 53 ++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'src/network/room_member.cpp') 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 @@ // Refer to the license.txt file included. #include +#include #include #include #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 receive_thread; - void ReceiveLoop(); + std::unique_ptr loop_thread; + std::mutex send_list_mutex; ///< Mutex that controls access to the `send_list` variable. + std::list 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 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 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(&RoomMember::RoomMemberImpl::ReceiveLoop, this); + loop_thread = std::make_unique(&RoomMember::RoomMemberImpl::MemberLoop, this); } void RoomMember::RoomMemberImpl::Send(Packet& packet) { - std::lock_guard 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 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(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 -- cgit v1.2.3 From 253d3dd3d889eb61131810b04137ee3f9445db64 Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 15 Jul 2017 11:39:27 +0200 Subject: Network: Propagate Room closing to connected members --- src/network/room_member.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/network/room_member.cpp') diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index f6f8b0475..8fd226ba5 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -127,6 +127,9 @@ void RoomMember::RoomMemberImpl::MemberLoop() { case IdVersionMismatch: SetState(State::WrongVersion); break; + case IdCloseRoom: + SetState(State::LostConnection); + break; default: break; } @@ -307,7 +310,7 @@ RoomInformation RoomMember::GetRoomInformation() const { } void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port, - u16 client_port) { + u16 client_port, const MacAddress& preferred_mac) { // If the member is connected, kill the connection first if (room_member_impl->loop_thread && room_member_impl->loop_thread->joinable()) { room_member_impl->SetState(State::Error); @@ -336,7 +339,7 @@ void RoomMember::Join(const std::string& nick, const char* server_addr, u16 serv room_member_impl->nickname = nick; room_member_impl->SetState(State::Joining); room_member_impl->StartLoop(); - room_member_impl->SendJoinRequest(nick); + room_member_impl->SendJoinRequest(nick, preferred_mac); } else { room_member_impl->SetState(State::CouldNotConnect); } -- cgit v1.2.3 From 77df82f5d66683f4928c4ad37f1deb77b79bb7df Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 15 Jul 2017 21:24:11 +0200 Subject: Network: Changed timeout for receiving packets to 100ms --- src/network/room_member.cpp | 52 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 27 deletions(-) (limited to 'src/network/room_member.cpp') diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp index 8fd226ba5..dac9bacae 100644 --- a/src/network/room_member.cpp +++ b/src/network/room_member.cpp @@ -38,13 +38,15 @@ public: std::mutex send_list_mutex; ///< Mutex that controls access to the `send_list` variable. std::list send_list; ///< A list that stores all packets to send the async void MemberLoop(); + void StartLoop(); /** * Sends data to the room. It will be send on channel 0 with flag RELIABLE * @param packet The data to send */ - void Send(Packet& packet); + void Send(Packet&& packet); + /** * Sends a request to the server, asking for permission to join a room with the specified * nickname and preferred mac. @@ -99,11 +101,13 @@ void RoomMember::RoomMemberImpl::MemberLoop() { while (IsConnected()) { std::lock_guard lock(network_mutex); ENetEvent event; - if (enet_host_service(client, &event, 1000) > 0) { + if (enet_host_service(client, &event, 100) > 0) { switch (event.type) { case ENET_EVENT_TYPE_RECEIVE: switch (event.packet->data[0]) { - // TODO(B3N30): Handle the other message types + case IdWifiPacket: + HandleWifiPackets(&event); + break; case IdChatMessage: HandleChatPacket(&event); break; @@ -130,8 +134,6 @@ void RoomMember::RoomMemberImpl::MemberLoop() { case IdCloseRoom: SetState(State::LostConnection); break; - default: - break; } enet_packet_destroy(event.packet); break; @@ -158,7 +160,7 @@ void RoomMember::RoomMemberImpl::StartLoop() { loop_thread = std::make_unique(&RoomMember::RoomMemberImpl::MemberLoop, this); } -void RoomMember::RoomMemberImpl::Send(Packet& packet) { +void RoomMember::RoomMemberImpl::Send(Packet&& packet) { std::lock_guard lock(send_list_mutex); send_list.push_back(std::move(packet)); } @@ -166,11 +168,11 @@ void RoomMember::RoomMemberImpl::Send(Packet& packet) { void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, const MacAddress& preferred_mac) { Packet packet; - packet << static_cast(IdJoinRequest); + packet << static_cast(IdJoinRequest); packet << nickname; packet << preferred_mac; packet << network_version; - Send(packet); + Send(std::move(packet)); } void RoomMember::RoomMemberImpl::HandleRoomInformationPacket(const ENetEvent* event) { @@ -178,7 +180,7 @@ void RoomMember::RoomMemberImpl::HandleRoomInformationPacket(const ENetEvent* ev packet.Append(event->packet->data, event->packet->dataLength); // Ignore the first byte, which is the message id. - packet.IgnoreBytes(sizeof(MessageID)); + packet.IgnoreBytes(sizeof(u8)); // Igonore the message type RoomInformation info{}; packet >> info.name; @@ -203,9 +205,9 @@ void RoomMember::RoomMemberImpl::HandleJoinPacket(const ENetEvent* event) { packet.Append(event->packet->data, event->packet->dataLength); // Ignore the first byte, which is the message id. - packet.IgnoreBytes(sizeof(MessageID)); + packet.IgnoreBytes(sizeof(u8)); // Igonore the message type - // Parse the MAC Address from the BitStream + // Parse the MAC Address from the packet packet >> mac_address; // TODO(B3N30): Invoke callbacks } @@ -216,9 +218,9 @@ void RoomMember::RoomMemberImpl::HandleWifiPackets(const ENetEvent* event) { packet.Append(event->packet->data, event->packet->dataLength); // Ignore the first byte, which is the message id. - packet.IgnoreBytes(sizeof(MessageID)); + packet.IgnoreBytes(sizeof(u8)); // Igonore the message type - // Parse the WifiPacket from the BitStream + // Parse the WifiPacket from the packet u8 frame_type; packet >> frame_type; WifiPacket::PacketType type = static_cast(frame_type); @@ -231,10 +233,8 @@ void RoomMember::RoomMemberImpl::HandleWifiPackets(const ENetEvent* event) { u32 data_length; packet >> data_length; - std::vector data(data_length); - packet >> data; + packet >> wifi_packet.data; - wifi_packet.data = std::move(data); // TODO(B3N30): Invoke callbacks } @@ -243,7 +243,7 @@ void RoomMember::RoomMemberImpl::HandleChatPacket(const ENetEvent* event) { packet.Append(event->packet->data, event->packet->dataLength); // Ignore the first byte, which is the message id. - packet.IgnoreBytes(sizeof(MessageID)); + packet.IgnoreBytes(sizeof(u8)); ChatEntry chat_entry{}; packet >> chat_entry.nickname; @@ -300,9 +300,8 @@ const std::string& RoomMember::GetNickname() const { } const MacAddress& RoomMember::GetMacAddress() const { - if (GetState() == State::Joined) - return room_member_impl->mac_address; - return MacAddress{}; + ASSERT_MSG(IsConnected(), "Tried to get MAC address while not connected"); + return room_member_impl->mac_address; } RoomInformation RoomMember::GetRoomInformation() const { @@ -351,28 +350,27 @@ bool RoomMember::IsConnected() const { void RoomMember::SendWifiPacket(const WifiPacket& wifi_packet) { Packet packet; - packet << static_cast(IdWifiPacket); + packet << static_cast(IdWifiPacket); packet << static_cast(wifi_packet.type); packet << wifi_packet.channel; packet << wifi_packet.transmitter_address; packet << wifi_packet.destination_address; - packet << static_cast(wifi_packet.data.size()); packet << wifi_packet.data; - room_member_impl->Send(packet); + room_member_impl->Send(std::move(packet)); } void RoomMember::SendChatMessage(const std::string& message) { Packet packet; - packet << static_cast(IdChatMessage); + packet << static_cast(IdChatMessage); packet << message; - room_member_impl->Send(packet); + room_member_impl->Send(std::move(packet)); } void RoomMember::SendGameName(const std::string& game_name) { Packet packet; - packet << static_cast(IdSetGameName); + packet << static_cast(IdSetGameName); packet << game_name; - room_member_impl->Send(packet); + room_member_impl->Send(std::move(packet)); } void RoomMember::Leave() { -- cgit v1.2.3