From 77677e205ebf1a6c47114ac1d449fc78be250c6d Mon Sep 17 00:00:00 2001 From: B3n30 Date: Sat, 8 Jul 2017 18:31:35 +0200 Subject: [PATCH] Network: Send JoinRequest and handle the answer in RoomMember --- src/network/room_member.cpp | 109 +++++++++++++++++++++++++++++++++++- src/network/room_member.h | 18 ++++++ 2 files changed, 125 insertions(+), 2 deletions(-) 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); } diff --git a/src/network/room_member.h b/src/network/room_member.h index 89ec6ae5a..f8bdbaea8 100644 --- a/src/network/room_member.h +++ b/src/network/room_member.h @@ -6,6 +6,7 @@ #include #include +#include #include "common/common_types.h" #include "network/room.h" @@ -31,6 +32,14 @@ public: CouldNotConnect ///< The room is not responding to a connection attempt }; + struct MemberInformation { + std::string nickname; ///< Nickname of the member. + std::string game_name; ///< Name of the game they're currently playing, or empty if they're + /// not playing anything. + MacAddress mac_address; ///< MAC address associated with this member. + }; + using MemberList = std::vector; + RoomMember(); ~RoomMember(); @@ -39,6 +48,15 @@ public: */ State GetState() const; + /** + * Returns information about the members in the room we're currently connected to. + */ + const MemberList& GetMemberInformation() const; + /** + * Returns information about the room we're currently connected to. + */ + RoomInformation GetRoomInformation() const; + /** * Returns whether we're connected to a server or not. */