diff options
| -rw-r--r-- | src/network/room.cpp | 38 | ||||
| -rw-r--r-- | src/network/room.h | 14 | ||||
| -rw-r--r-- | src/network/room_member.cpp | 79 | ||||
| -rw-r--r-- | src/network/room_member.h | 1 | 
4 files changed, 119 insertions, 13 deletions
diff --git a/src/network/room.cpp b/src/network/room.cpp index 48de2f5cb..274cb4159 100644 --- a/src/network/room.cpp +++ b/src/network/room.cpp @@ -2,6 +2,8 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <atomic> +#include <thread>  #include "enet/enet.h"  #include "network/room.h" @@ -16,8 +18,38 @@ public:      std::atomic<State> state{State::Closed}; ///< Current state of the room.      RoomInformation room_information;        ///< Information about this room. + +    /// Thread that receives and dispatches network packets +    std::unique_ptr<std::thread> room_thread; + +    /// Thread function that will receive and dispatch messages until the room is destroyed. +    void ServerLoop(); +    void StartLoop();  }; +// RoomImpl +void Room::RoomImpl::ServerLoop() { +    while (state != State::Closed) { +        ENetEvent event; +        if (enet_host_service(server, &event, 1000) > 0) { +            switch (event.type) { +            case ENET_EVENT_TYPE_RECEIVE: +                // TODO(B3N30): Select the type of message and handle it +                enet_packet_destroy(event.packet); +                break; +            case ENET_EVENT_TYPE_DISCONNECT: +                // TODO(B3N30): Handle the disconnect from a client +                break; +            } +        } +    } +} + +void Room::RoomImpl::StartLoop() { +    room_thread = std::make_unique<std::thread>(&Room::RoomImpl::ServerLoop, this); +} + +// Room  Room::Room() : room_impl{std::make_unique<RoomImpl>()} {}  Room::~Room() = default; @@ -34,8 +66,7 @@ void Room::Create(const std::string& name, const std::string& server_address, u1      room_impl->room_information.name = name;      room_impl->room_information.member_slots = MaxConcurrentConnections; - -    // TODO(B3N30): Start the receiving thread +    room_impl->StartLoop();  }  Room::State Room::GetState() const { @@ -48,7 +79,8 @@ const RoomInformation& Room::GetRoomInformation() const {  void Room::Destroy() {      room_impl->state = State::Closed; -    // TODO(B3n30): Join the receiving thread +    room_impl->room_thread->join(); +    room_impl->room_thread.reset();      if (room_impl->server) {          enet_host_destroy(room_impl->server); diff --git a/src/network/room.h b/src/network/room.h index 70c64d5f1..0a6217c11 100644 --- a/src/network/room.h +++ b/src/network/room.h @@ -4,7 +4,6 @@  #pragma once -#include <atomic>  #include <memory>  #include <string>  #include "common/common_types.h" @@ -19,6 +18,19 @@ struct RoomInformation {      u32 member_slots; ///< Maximum number of members in this room  }; +// The different types of messages that can be sent. The first byte of each packet defines the type +typedef uint8_t MessageID; +enum RoomMessageTypes { +    IdJoinRequest = 1, +    IdJoinSuccess, +    IdRoomInformation, +    IdSetGameName, +    IdWifiPacket, +    IdChatMessage, +    IdNameCollision, +    IdMacCollision +}; +  /// This is what a server [person creating a server] would use.  class Room final {  public: 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 <atomic> +#include <mutex> +#include <thread>  #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{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<std::thread> 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<std::mutex> 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<std::thread>(&RoomMember::RoomMemberImpl::ReceiveLoop, this); +} + +// RoomMember  RoomMember::RoomMember() : room_member_impl{std::make_unique<RoomMemberImpl>()} {      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<std::mutex> 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);  } diff --git a/src/network/room_member.h b/src/network/room_member.h index 177622b69..89ec6ae5a 100644 --- a/src/network/room_member.h +++ b/src/network/room_member.h @@ -4,7 +4,6 @@  #pragma once -#include <atomic>  #include <memory>  #include <string>  #include "common/common_types.h"  | 
