summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/network/room.cpp35
-rw-r--r--src/network/room.h6
-rw-r--r--src/network/room_member.cpp53
-rw-r--r--src/network/room_member.h1
4 files changed, 70 insertions, 25 deletions
diff --git a/src/network/room.cpp b/src/network/room.cpp
index 9af5b4ea0..da1679312 100644
--- a/src/network/room.cpp
+++ b/src/network/room.cpp
@@ -74,6 +74,11 @@ public:
74 void SendMacCollision(ENetPeer* client); 74 void SendMacCollision(ENetPeer* client);
75 75
76 /** 76 /**
77 * Sends a ID_ROOM_VERSION_MISMATCH message telling the client that the MAC is invalid.
78 */
79 void SendVersionMismatch(ENetPeer* client);
80
81 /**
77 * Notifies the member that its connection attempt was successful, 82 * Notifies the member that its connection attempt was successful,
78 * and it is now part of the room. 83 * and it is now part of the room.
79 */ 84 */
@@ -170,6 +175,9 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
170 MacAddress preferred_mac; 175 MacAddress preferred_mac;
171 packet >> preferred_mac; 176 packet >> preferred_mac;
172 177
178 u32 client_version;
179 packet >> client_version;
180
173 if (!IsValidNickname(nickname)) { 181 if (!IsValidNickname(nickname)) {
174 SendNameCollision(event->peer); 182 SendNameCollision(event->peer);
175 return; 183 return;
@@ -186,6 +194,11 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
186 preferred_mac = GenerateMacAddress(); 194 preferred_mac = GenerateMacAddress();
187 } 195 }
188 196
197 if (client_version != network_version) {
198 SendVersionMismatch(event->peer);
199 return;
200 }
201
189 // At this point the client is ready to be added to the room. 202 // At this point the client is ready to be added to the room.
190 Member member{}; 203 Member member{};
191 member.mac_address = preferred_mac; 204 member.mac_address = preferred_mac;
@@ -232,6 +245,17 @@ void Room::RoomImpl::SendMacCollision(ENetPeer* client) {
232 enet_host_flush(server); 245 enet_host_flush(server);
233} 246}
234 247
248void Room::RoomImpl::SendVersionMismatch(ENetPeer* client) {
249 Packet packet;
250 packet << static_cast<MessageID>(IdVersionMismatch);
251 packet << network_version;
252
253 ENetPacket* enet_packet =
254 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
255 enet_peer_send(client, 0, enet_packet);
256 enet_host_flush(server);
257}
258
235void Room::RoomImpl::SendJoinSuccess(ENetPeer* client, MacAddress mac_address) { 259void Room::RoomImpl::SendJoinSuccess(ENetPeer* client, MacAddress mac_address) {
236 Packet packet; 260 Packet packet;
237 packet << static_cast<MessageID>(IdJoinSuccess); 261 packet << static_cast<MessageID>(IdJoinSuccess);
@@ -291,7 +315,7 @@ void Room::RoomImpl::HandleWifiPacket(const ENetEvent* event) {
291 if (destination_address == BroadcastMac) { // Send the data to everyone except the sender 315 if (destination_address == BroadcastMac) { // Send the data to everyone except the sender
292 for (const auto& member : members) { 316 for (const auto& member : members) {
293 if (member.peer != event->peer) 317 if (member.peer != event->peer)
294 enet_peer_send(member.peer, 0, event->packet); 318 enet_peer_send(member.peer, 0, enet_packet);
295 } 319 }
296 } else { // Send the data only to the destination client 320 } else { // Send the data only to the destination client
297 auto member = std::find_if(members.begin(), members.end(), 321 auto member = std::find_if(members.begin(), members.end(),
@@ -327,9 +351,9 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) {
327 351
328 ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(), 352 ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(),
329 ENET_PACKET_FLAG_RELIABLE); 353 ENET_PACKET_FLAG_RELIABLE);
330 for (auto it = members.begin(); it != members.end(); ++it) { 354 for (const auto& member : members) {
331 if (it->peer != event->peer) 355 if (member.peer != event->peer)
332 enet_peer_send(it->peer, 0, enet_packet); 356 enet_peer_send(member.peer, 0, enet_packet);
333 } 357 }
334 enet_host_flush(server); 358 enet_host_flush(server);
335} 359}
@@ -369,6 +393,9 @@ Room::~Room() = default;
369void Room::Create(const std::string& name, const std::string& server_address, u16 server_port) { 393void Room::Create(const std::string& name, const std::string& server_address, u16 server_port) {
370 ENetAddress address; 394 ENetAddress address;
371 address.host = ENET_HOST_ANY; 395 address.host = ENET_HOST_ANY;
396 if (!server_address.empty()) {
397 enet_address_set_host(&address, server_address.c_str());
398 }
372 address.port = server_port; 399 address.port = server_port;
373 400
374 room_impl->server = enet_host_create(&address, MaxConcurrentConnections, NumChannels, 0, 0); 401 room_impl->server = enet_host_create(&address, MaxConcurrentConnections, NumChannels, 0, 0);
diff --git a/src/network/room.h b/src/network/room.h
index 82e3dc62c..ffa17599d 100644
--- a/src/network/room.h
+++ b/src/network/room.h
@@ -11,6 +11,8 @@
11 11
12namespace Network { 12namespace Network {
13 13
14constexpr u32 network_version = 1; ///< The version of this Room and RoomMember
15
14constexpr u16 DefaultRoomPort = 1234; 16constexpr u16 DefaultRoomPort = 1234;
15constexpr size_t NumChannels = 1; // Number of channels used for the connection 17constexpr size_t NumChannels = 1; // Number of channels used for the connection
16 18
@@ -37,7 +39,9 @@ enum RoomMessageTypes {
37 IdWifiPacket, 39 IdWifiPacket,
38 IdChatMessage, 40 IdChatMessage,
39 IdNameCollision, 41 IdNameCollision,
40 IdMacCollision 42 IdMacCollision,
43 IdVersionMismatch,
44 IdCloseRoom
41}; 45};
42 46
43/// This is what a server [person creating a server] would use. 47/// This is what a server [person creating a server] would use.
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 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <atomic> 5#include <atomic>
6#include <list>
6#include <mutex> 7#include <mutex>
7#include <thread> 8#include <thread>
8#include "common/assert.h" 9#include "common/assert.h"
@@ -33,8 +34,10 @@ public:
33 34
34 std::mutex network_mutex; ///< Mutex that controls access to the `client` variable. 35 std::mutex network_mutex; ///< Mutex that controls access to the `client` variable.
35 /// Thread that receives and dispatches network packets 36 /// Thread that receives and dispatches network packets
36 std::unique_ptr<std::thread> receive_thread; 37 std::unique_ptr<std::thread> loop_thread;
37 void ReceiveLoop(); 38 std::mutex send_list_mutex; ///< Mutex that controls access to the `send_list` variable.
39 std::list<Packet> send_list; ///< A list that stores all packets to send the async
40 void MemberLoop();
38 void StartLoop(); 41 void StartLoop();
39 42
40 /** 43 /**
@@ -91,7 +94,7 @@ bool RoomMember::RoomMemberImpl::IsConnected() const {
91 return state == State::Joining || state == State::Joined; 94 return state == State::Joining || state == State::Joined;
92} 95}
93 96
94void RoomMember::RoomMemberImpl::ReceiveLoop() { 97void RoomMember::RoomMemberImpl::MemberLoop() {
95 // Receive packets while the connection is open 98 // Receive packets while the connection is open
96 while (IsConnected()) { 99 while (IsConnected()) {
97 std::lock_guard<std::mutex> lock(network_mutex); 100 std::lock_guard<std::mutex> lock(network_mutex);
@@ -121,6 +124,9 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() {
121 case IdMacCollision: 124 case IdMacCollision:
122 SetState(State::MacCollision); 125 SetState(State::MacCollision);
123 break; 126 break;
127 case IdVersionMismatch:
128 SetState(State::WrongVersion);
129 break;
124 default: 130 default:
125 break; 131 break;
126 } 132 }
@@ -128,22 +134,30 @@ void RoomMember::RoomMemberImpl::ReceiveLoop() {
128 break; 134 break;
129 case ENET_EVENT_TYPE_DISCONNECT: 135 case ENET_EVENT_TYPE_DISCONNECT:
130 SetState(State::LostConnection); 136 SetState(State::LostConnection);
137 break;
138 }
139 }
140 {
141 std::lock_guard<std::mutex> lock(send_list_mutex);
142 for (const auto& packet : send_list) {
143 ENetPacket* enetPacket = enet_packet_create(packet.GetData(), packet.GetDataSize(),
144 ENET_PACKET_FLAG_RELIABLE);
145 enet_peer_send(server, 0, enetPacket);
131 } 146 }
147 enet_host_flush(client);
148 send_list.clear();
132 } 149 }
133 } 150 }
134 Disconnect(); 151 Disconnect();
135}; 152};
136 153
137void RoomMember::RoomMemberImpl::StartLoop() { 154void RoomMember::RoomMemberImpl::StartLoop() {
138 receive_thread = std::make_unique<std::thread>(&RoomMember::RoomMemberImpl::ReceiveLoop, this); 155 loop_thread = std::make_unique<std::thread>(&RoomMember::RoomMemberImpl::MemberLoop, this);
139} 156}
140 157
141void RoomMember::RoomMemberImpl::Send(Packet& packet) { 158void RoomMember::RoomMemberImpl::Send(Packet& packet) {
142 std::lock_guard<std::mutex> lock(network_mutex); 159 std::lock_guard<std::mutex> lock(send_list_mutex);
143 ENetPacket* enetPacket = 160 send_list.push_back(std::move(packet));
144 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
145 enet_peer_send(server, 0, enetPacket);
146 enet_host_flush(client);
147} 161}
148 162
149void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, 163void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname,
@@ -152,6 +166,7 @@ void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname,
152 packet << static_cast<MessageID>(IdJoinRequest); 166 packet << static_cast<MessageID>(IdJoinRequest);
153 packet << nickname; 167 packet << nickname;
154 packet << preferred_mac; 168 packet << preferred_mac;
169 packet << network_version;
155 Send(packet); 170 Send(packet);
156} 171}
157 172
@@ -238,11 +253,9 @@ void RoomMember::RoomMemberImpl::Disconnect() {
238 room_information.member_slots = 0; 253 room_information.member_slots = 0;
239 room_information.name.clear(); 254 room_information.name.clear();
240 255
241 if (server) { 256 if (!server)
242 enet_peer_disconnect(server, 0);
243 } else {
244 return; 257 return;
245 } 258 enet_peer_disconnect(server, 0);
246 259
247 ENetEvent event; 260 ENetEvent event;
248 while (enet_host_service(client, &event, ConnectionTimeoutMs) > 0) { 261 while (enet_host_service(client, &event, ConnectionTimeoutMs) > 0) {
@@ -296,14 +309,14 @@ RoomInformation RoomMember::GetRoomInformation() const {
296void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port, 309void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port,
297 u16 client_port) { 310 u16 client_port) {
298 // If the member is connected, kill the connection first 311 // If the member is connected, kill the connection first
299 if (room_member_impl->receive_thread && room_member_impl->receive_thread->joinable()) { 312 if (room_member_impl->loop_thread && room_member_impl->loop_thread->joinable()) {
300 room_member_impl->SetState(State::Error); 313 room_member_impl->SetState(State::Error);
301 room_member_impl->receive_thread->join(); 314 room_member_impl->loop_thread->join();
302 room_member_impl->receive_thread.reset(); 315 room_member_impl->loop_thread.reset();
303 } 316 }
304 // If the thread isn't running but the ptr still exists, reset it 317 // If the thread isn't running but the ptr still exists, reset it
305 else if (room_member_impl->receive_thread) { 318 else if (room_member_impl->loop_thread) {
306 room_member_impl->receive_thread.reset(); 319 room_member_impl->loop_thread.reset();
307 } 320 }
308 321
309 ENetAddress address{}; 322 ENetAddress address{};
@@ -361,8 +374,8 @@ void RoomMember::SendGameName(const std::string& game_name) {
361 374
362void RoomMember::Leave() { 375void RoomMember::Leave() {
363 room_member_impl->SetState(State::Idle); 376 room_member_impl->SetState(State::Idle);
364 room_member_impl->receive_thread->join(); 377 room_member_impl->loop_thread->join();
365 room_member_impl->receive_thread.reset(); 378 room_member_impl->loop_thread.reset();
366} 379}
367 380
368} // namespace Network 381} // namespace Network
diff --git a/src/network/room_member.h b/src/network/room_member.h
index d874cc5e4..6522f053c 100644
--- a/src/network/room_member.h
+++ b/src/network/room_member.h
@@ -47,6 +47,7 @@ public:
47 // Reasons why connection was rejected 47 // Reasons why connection was rejected
48 NameCollision, ///< Somebody is already using this name 48 NameCollision, ///< Somebody is already using this name
49 MacCollision, ///< Somebody is already using that mac-address 49 MacCollision, ///< Somebody is already using that mac-address
50 WrongVersion, ///< The room version is not the same as for this RoomMember
50 CouldNotConnect ///< The room is not responding to a connection attempt 51 CouldNotConnect ///< The room is not responding to a connection attempt
51 }; 52 };
52 53