diff options
| author | 2017-07-08 15:24:47 +0200 | |
|---|---|---|
| committer | 2017-07-16 21:28:47 +0200 | |
| commit | 589dc083a58425cadd8390ddd81854dcf054dd27 (patch) | |
| tree | b665a2ff519ddbfb7d3f6a035f076342d69c2148 | |
| parent | Merge pull request #2824 from jroweboy/mingw_compile_test (diff) | |
| download | yuzu-589dc083a58425cadd8390ddd81854dcf054dd27.tar.gz yuzu-589dc083a58425cadd8390ddd81854dcf054dd27.tar.xz yuzu-589dc083a58425cadd8390ddd81854dcf054dd27.zip | |
Network: Threads for Room and RoomMember
| -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 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <atomic> | ||
| 6 | #include <thread> | ||
| 5 | #include "enet/enet.h" | 7 | #include "enet/enet.h" |
| 6 | #include "network/room.h" | 8 | #include "network/room.h" |
| 7 | 9 | ||
| @@ -16,8 +18,38 @@ public: | |||
| 16 | 18 | ||
| 17 | std::atomic<State> state{State::Closed}; ///< Current state of the room. | 19 | std::atomic<State> state{State::Closed}; ///< Current state of the room. |
| 18 | RoomInformation room_information; ///< Information about this room. | 20 | RoomInformation room_information; ///< Information about this room. |
| 21 | |||
| 22 | /// Thread that receives and dispatches network packets | ||
| 23 | std::unique_ptr<std::thread> room_thread; | ||
| 24 | |||
| 25 | /// Thread function that will receive and dispatch messages until the room is destroyed. | ||
| 26 | void ServerLoop(); | ||
| 27 | void StartLoop(); | ||
| 19 | }; | 28 | }; |
| 20 | 29 | ||
| 30 | // RoomImpl | ||
| 31 | void Room::RoomImpl::ServerLoop() { | ||
| 32 | while (state != State::Closed) { | ||
| 33 | ENetEvent event; | ||
| 34 | if (enet_host_service(server, &event, 1000) > 0) { | ||
| 35 | switch (event.type) { | ||
| 36 | case ENET_EVENT_TYPE_RECEIVE: | ||
| 37 | // TODO(B3N30): Select the type of message and handle it | ||
| 38 | enet_packet_destroy(event.packet); | ||
| 39 | break; | ||
| 40 | case ENET_EVENT_TYPE_DISCONNECT: | ||
| 41 | // TODO(B3N30): Handle the disconnect from a client | ||
| 42 | break; | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | void Room::RoomImpl::StartLoop() { | ||
| 49 | room_thread = std::make_unique<std::thread>(&Room::RoomImpl::ServerLoop, this); | ||
| 50 | } | ||
| 51 | |||
| 52 | // Room | ||
| 21 | Room::Room() : room_impl{std::make_unique<RoomImpl>()} {} | 53 | Room::Room() : room_impl{std::make_unique<RoomImpl>()} {} |
| 22 | 54 | ||
| 23 | Room::~Room() = default; | 55 | Room::~Room() = default; |
| @@ -34,8 +66,7 @@ void Room::Create(const std::string& name, const std::string& server_address, u1 | |||
| 34 | 66 | ||
| 35 | room_impl->room_information.name = name; | 67 | room_impl->room_information.name = name; |
| 36 | room_impl->room_information.member_slots = MaxConcurrentConnections; | 68 | room_impl->room_information.member_slots = MaxConcurrentConnections; |
| 37 | 69 | room_impl->StartLoop(); | |
| 38 | // TODO(B3N30): Start the receiving thread | ||
| 39 | } | 70 | } |
| 40 | 71 | ||
| 41 | Room::State Room::GetState() const { | 72 | Room::State Room::GetState() const { |
| @@ -48,7 +79,8 @@ const RoomInformation& Room::GetRoomInformation() const { | |||
| 48 | 79 | ||
| 49 | void Room::Destroy() { | 80 | void Room::Destroy() { |
| 50 | room_impl->state = State::Closed; | 81 | room_impl->state = State::Closed; |
| 51 | // TODO(B3n30): Join the receiving thread | 82 | room_impl->room_thread->join(); |
| 83 | room_impl->room_thread.reset(); | ||
| 52 | 84 | ||
| 53 | if (room_impl->server) { | 85 | if (room_impl->server) { |
| 54 | enet_host_destroy(room_impl->server); | 86 | 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 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 8 | #include <memory> | 7 | #include <memory> |
| 9 | #include <string> | 8 | #include <string> |
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| @@ -19,6 +18,19 @@ struct RoomInformation { | |||
| 19 | u32 member_slots; ///< Maximum number of members in this room | 18 | u32 member_slots; ///< Maximum number of members in this room |
| 20 | }; | 19 | }; |
| 21 | 20 | ||
| 21 | // The different types of messages that can be sent. The first byte of each packet defines the type | ||
| 22 | typedef uint8_t MessageID; | ||
| 23 | enum RoomMessageTypes { | ||
| 24 | IdJoinRequest = 1, | ||
| 25 | IdJoinSuccess, | ||
| 26 | IdRoomInformation, | ||
| 27 | IdSetGameName, | ||
| 28 | IdWifiPacket, | ||
| 29 | IdChatMessage, | ||
| 30 | IdNameCollision, | ||
| 31 | IdMacCollision | ||
| 32 | }; | ||
| 33 | |||
| 22 | /// This is what a server [person creating a server] would use. | 34 | /// This is what a server [person creating a server] would use. |
| 23 | class Room final { | 35 | class Room final { |
| 24 | public: | 36 | 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 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <atomic> | ||
| 6 | #include <mutex> | ||
| 7 | #include <thread> | ||
| 5 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 6 | #include "enet/enet.h" | 9 | #include "enet/enet.h" |
| 7 | #include "network/room_member.h" | 10 | #include "network/room_member.h" |
| @@ -16,10 +19,65 @@ public: | |||
| 16 | ENetPeer* server = nullptr; ///< The server peer the client is connected to | 19 | ENetPeer* server = nullptr; ///< The server peer the client is connected to |
| 17 | 20 | ||
| 18 | std::atomic<State> state{State::Idle}; ///< Current state of the RoomMember. | 21 | std::atomic<State> state{State::Idle}; ///< Current state of the RoomMember. |
| 22 | void SetState(const State new_state); | ||
| 23 | bool IsConnected() const; | ||
| 19 | 24 | ||
| 20 | std::string nickname; ///< The nickname of this member. | 25 | std::string nickname; ///< The nickname of this member. |
| 26 | |||
| 27 | std::mutex network_mutex; ///< Mutex that controls access to the `client` variable. | ||
| 28 | /// Thread that receives and dispatches network packets | ||
| 29 | std::unique_ptr<std::thread> receive_thread; | ||
| 30 | void ReceiveLoop(); | ||
| 31 | void StartLoop(); | ||
| 21 | }; | 32 | }; |
| 22 | 33 | ||
| 34 | // RoomMemberImpl | ||
| 35 | void RoomMember::RoomMemberImpl::SetState(const State new_state) { | ||
| 36 | state = new_state; | ||
| 37 | // TODO(B3N30): Invoke the callback functions | ||
| 38 | } | ||
| 39 | |||
| 40 | bool RoomMember::RoomMemberImpl::IsConnected() const { | ||
| 41 | return state == State::Joining || state == State::Joined; | ||
| 42 | } | ||
| 43 | |||
| 44 | void RoomMember::RoomMemberImpl::ReceiveLoop() { | ||
| 45 | // Receive packets while the connection is open | ||
| 46 | while (IsConnected()) { | ||
| 47 | std::lock_guard<std::mutex> lock(network_mutex); | ||
| 48 | ENetEvent event; | ||
| 49 | if (enet_host_service(client, &event, 1000) > 0) { | ||
| 50 | if (event.type == ENET_EVENT_TYPE_RECEIVE) { | ||
| 51 | switch (event.packet->data[0]) { | ||
| 52 | // TODO(B3N30): Handle the other message types | ||
| 53 | case IdNameCollision: | ||
| 54 | SetState(State::NameCollision); | ||
| 55 | enet_packet_destroy(event.packet); | ||
| 56 | enet_peer_disconnect(server, 0); | ||
| 57 | enet_peer_reset(server); | ||
| 58 | return; | ||
| 59 | break; | ||
| 60 | case IdMacCollision: | ||
| 61 | SetState(State::MacCollision); | ||
| 62 | enet_packet_destroy(event.packet); | ||
| 63 | enet_peer_disconnect(server, 0); | ||
| 64 | enet_peer_reset(server); | ||
| 65 | return; | ||
| 66 | break; | ||
| 67 | default: | ||
| 68 | break; | ||
| 69 | } | ||
| 70 | enet_packet_destroy(event.packet); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | }; | ||
| 75 | |||
| 76 | void RoomMember::RoomMemberImpl::StartLoop() { | ||
| 77 | receive_thread = std::make_unique<std::thread>(&RoomMember::RoomMemberImpl::ReceiveLoop, this); | ||
| 78 | } | ||
| 79 | |||
| 80 | // RoomMember | ||
| 23 | RoomMember::RoomMember() : room_member_impl{std::make_unique<RoomMemberImpl>()} { | 81 | RoomMember::RoomMember() : room_member_impl{std::make_unique<RoomMemberImpl>()} { |
| 24 | room_member_impl->client = enet_host_create(nullptr, 1, NumChannels, 0, 0); | 82 | room_member_impl->client = enet_host_create(nullptr, 1, NumChannels, 0, 0); |
| 25 | ASSERT_MSG(room_member_impl->client != nullptr, "Could not create client"); | 83 | 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 | |||
| 44 | enet_host_connect(room_member_impl->client, &address, NumChannels, 0); | 102 | enet_host_connect(room_member_impl->client, &address, NumChannels, 0); |
| 45 | 103 | ||
| 46 | if (!room_member_impl->server) { | 104 | if (!room_member_impl->server) { |
| 47 | room_member_impl->state = State::Error; | 105 | room_member_impl->SetState(State::Error); |
| 48 | return; | 106 | return; |
| 49 | } | 107 | } |
| 50 | 108 | ||
| @@ -52,22 +110,27 @@ void RoomMember::Join(const std::string& nick, const char* server_addr, u16 serv | |||
| 52 | int net = enet_host_service(room_member_impl->client, &event, ConnectionTimeoutMs); | 110 | int net = enet_host_service(room_member_impl->client, &event, ConnectionTimeoutMs); |
| 53 | if (net > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { | 111 | if (net > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { |
| 54 | room_member_impl->nickname = nick; | 112 | room_member_impl->nickname = nick; |
| 55 | room_member_impl->state = State::Joining; | 113 | room_member_impl->SetState(State::Joining); |
| 114 | room_member_impl->StartLoop(); | ||
| 56 | // TODO(B3N30): Send a join request with the nickname to the server | 115 | // TODO(B3N30): Send a join request with the nickname to the server |
| 57 | // TODO(B3N30): Start the receive thread | ||
| 58 | } else { | 116 | } else { |
| 59 | room_member_impl->state = State::CouldNotConnect; | 117 | room_member_impl->SetState(State::CouldNotConnect); |
| 60 | } | 118 | } |
| 61 | } | 119 | } |
| 62 | 120 | ||
| 63 | bool RoomMember::IsConnected() const { | 121 | bool RoomMember::IsConnected() const { |
| 64 | return room_member_impl->state == State::Joining || room_member_impl->state == State::Joined; | 122 | return room_member_impl->IsConnected(); |
| 65 | } | 123 | } |
| 66 | 124 | ||
| 67 | void RoomMember::Leave() { | 125 | void RoomMember::Leave() { |
| 68 | enet_peer_disconnect(room_member_impl->server, 0); | 126 | ASSERT_MSG(room_member_impl->receive_thread != nullptr, "Must be in a room to leave it."); |
| 69 | room_member_impl->state = State::Idle; | 127 | { |
| 70 | // TODO(B3N30): Close the receive thread | 128 | std::lock_guard<std::mutex> lock(room_member_impl->network_mutex); |
| 129 | enet_peer_disconnect(room_member_impl->server, 0); | ||
| 130 | room_member_impl->SetState(State::Idle); | ||
| 131 | } | ||
| 132 | room_member_impl->receive_thread->join(); | ||
| 133 | room_member_impl->receive_thread.reset(); | ||
| 71 | enet_peer_reset(room_member_impl->server); | 134 | enet_peer_reset(room_member_impl->server); |
| 72 | } | 135 | } |
| 73 | 136 | ||
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 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 8 | #include <memory> | 7 | #include <memory> |
| 9 | #include <string> | 8 | #include <string> |
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |