summaryrefslogtreecommitdiff
path: root/src/network/room_member.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/room_member.cpp')
-rw-r--r--src/network/room_member.cpp79
1 files changed, 71 insertions, 8 deletions
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
35void RoomMember::RoomMemberImpl::SetState(const State new_state) {
36 state = new_state;
37 // TODO(B3N30): Invoke the callback functions
38}
39
40bool RoomMember::RoomMemberImpl::IsConnected() const {
41 return state == State::Joining || state == State::Joined;
42}
43
44void 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
76void RoomMember::RoomMemberImpl::StartLoop() {
77 receive_thread = std::make_unique<std::thread>(&RoomMember::RoomMemberImpl::ReceiveLoop, this);
78}
79
80// RoomMember
23RoomMember::RoomMember() : room_member_impl{std::make_unique<RoomMemberImpl>()} { 81RoomMember::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
63bool RoomMember::IsConnected() const { 121bool 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
67void RoomMember::Leave() { 125void 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