summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar B3n302017-07-08 16:47:24 +0200
committerGravatar B3n302017-07-16 21:29:02 +0200
commit2af9a7146d17e89840c2c9c4f9134c992d27361c (patch)
treef52f855e81dcf75a1b46e6b6189f0e5f5c095989 /src
parentNetwork: Added Packet class for serialization (diff)
downloadyuzu-2af9a7146d17e89840c2c9c4f9134c992d27361c.tar.gz
yuzu-2af9a7146d17e89840c2c9c4f9134c992d27361c.tar.xz
yuzu-2af9a7146d17e89840c2c9c4f9134c992d27361c.zip
Network: Handle join request in Room
Diffstat (limited to 'src')
-rw-r--r--src/network/room.cpp200
-rw-r--r--src/network/room.h6
2 files changed, 205 insertions, 1 deletions
diff --git a/src/network/room.cpp b/src/network/room.cpp
index 274cb4159..3502264e1 100644
--- a/src/network/room.cpp
+++ b/src/network/room.cpp
@@ -3,8 +3,11 @@
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 <random>
6#include <thread> 7#include <thread>
8#include <vector>
7#include "enet/enet.h" 9#include "enet/enet.h"
10#include "network/packet.h"
8#include "network/room.h" 11#include "network/room.h"
9 12
10namespace Network { 13namespace Network {
@@ -14,17 +17,87 @@ static constexpr u32 MaxConcurrentConnections = 10;
14 17
15class Room::RoomImpl { 18class Room::RoomImpl {
16public: 19public:
20 // This MAC address is used to generate a 'Nintendo' like Mac address.
21 const MacAddress NintendoOUI = {0x00, 0x1F, 0x32, 0x00, 0x00, 0x00};
22 std::mt19937 random_gen; ///< Random number generator. Used for GenerateMacAddress
23
17 ENetHost* server = nullptr; ///< Network interface. 24 ENetHost* server = nullptr; ///< Network interface.
18 25
19 std::atomic<State> state{State::Closed}; ///< Current state of the room. 26 std::atomic<State> state{State::Closed}; ///< Current state of the room.
20 RoomInformation room_information; ///< Information about this room. 27 RoomInformation room_information; ///< Information about this room.
21 28
29 struct Member {
30 std::string nickname; ///< The nickname of the member.
31 std::string game_name; ///< The current game of the member
32 MacAddress mac_address; ///< The assigned mac address of the member.
33 ENetPeer* peer; ///< The remote peer.
34 };
35 using MemberList = std::vector<Member>;
36 MemberList members; ///< Information about the members of this room.
37
38 RoomImpl() : random_gen(std::random_device()()) {}
39
22 /// Thread that receives and dispatches network packets 40 /// Thread that receives and dispatches network packets
23 std::unique_ptr<std::thread> room_thread; 41 std::unique_ptr<std::thread> room_thread;
24 42
25 /// Thread function that will receive and dispatch messages until the room is destroyed. 43 /// Thread function that will receive and dispatch messages until the room is destroyed.
26 void ServerLoop(); 44 void ServerLoop();
27 void StartLoop(); 45 void StartLoop();
46
47 /**
48 * Parses and answers a room join request from a client.
49 * Validates the uniqueness of the username and assigns the MAC address
50 * that the client will use for the remainder of the connection.
51 */
52 void HandleJoinRequest(const ENetEvent* event);
53
54 /**
55 * Returns whether the nickname is valid, ie. isn't already taken by someone else in the room.
56 */
57 bool IsValidNickname(const std::string& nickname) const;
58
59 /**
60 * Returns whether the MAC address is valid, ie. isn't already taken by someone else in the
61 * room.
62 */
63 bool IsValidMacAddress(const MacAddress& address) const;
64
65 /**
66 * Sends a ID_ROOM_NAME_COLLISION message telling the client that the name is invalid.
67 */
68 void SendNameCollision(ENetPeer* client);
69
70 /**
71 * Sends a ID_ROOM_MAC_COLLISION message telling the client that the MAC is invalid.
72 */
73 void SendMacCollision(ENetPeer* client);
74
75 /**
76 * Notifies the member that its connection attempt was successful,
77 * and it is now part of the room.
78 */
79 void SendJoinSuccess(ENetPeer* client, MacAddress mac_address);
80
81 /**
82 * Sends the information about the room, along with the list of members
83 * to every connected client in the room.
84 * The packet has the structure:
85 * <MessageID>ID_ROOM_INFORMATION
86 * <String> room_name
87 * <uint32_t> member_slots: The max number of clients allowed in this room
88 * <uint32_t> num_members: the number of currently joined clients
89 * This is followed by the following three values for each member:
90 * <String> nickname of that member
91 * <MacAddress> mac_address of that member
92 * <String> game_name of that member
93 */
94 void BroadcastRoomInformation();
95
96 /**
97 * Generates a free MAC address to assign to a new client.
98 * The first 3 bytes are the NintendoOUI 0x00, 0x1F, 0x32
99 */
100 MacAddress GenerateMacAddress();
28}; 101};
29 102
30// RoomImpl 103// RoomImpl
@@ -34,7 +107,12 @@ void Room::RoomImpl::ServerLoop() {
34 if (enet_host_service(server, &event, 1000) > 0) { 107 if (enet_host_service(server, &event, 1000) > 0) {
35 switch (event.type) { 108 switch (event.type) {
36 case ENET_EVENT_TYPE_RECEIVE: 109 case ENET_EVENT_TYPE_RECEIVE:
37 // TODO(B3N30): Select the type of message and handle it 110 switch (event.packet->data[0]) {
111 case IdJoinRequest:
112 HandleJoinRequest(&event);
113 break;
114 // TODO(B3N30): Handle the other message types
115 }
38 enet_packet_destroy(event.packet); 116 enet_packet_destroy(event.packet);
39 break; 117 break;
40 case ENET_EVENT_TYPE_DISCONNECT: 118 case ENET_EVENT_TYPE_DISCONNECT:
@@ -49,6 +127,126 @@ void Room::RoomImpl::StartLoop() {
49 room_thread = std::make_unique<std::thread>(&Room::RoomImpl::ServerLoop, this); 127 room_thread = std::make_unique<std::thread>(&Room::RoomImpl::ServerLoop, this);
50} 128}
51 129
130void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
131 Packet packet;
132 packet.Append(event->packet->data, event->packet->dataLength);
133 packet.IgnoreBytes(sizeof(MessageID));
134 std::string nickname;
135 packet >> nickname;
136
137 MacAddress preferred_mac;
138 packet >> preferred_mac;
139
140 if (!IsValidNickname(nickname)) {
141 SendNameCollision(event->peer);
142 return;
143 }
144
145 if (preferred_mac != NoPreferredMac) {
146 // Verify if the preferred mac is available
147 if (!IsValidMacAddress(preferred_mac)) {
148 SendMacCollision(event->peer);
149 return;
150 }
151 } else {
152 // Assign a MAC address of this client automatically
153 preferred_mac = GenerateMacAddress();
154 }
155
156 // At this point the client is ready to be added to the room.
157 Member member{};
158 member.mac_address = preferred_mac;
159 member.nickname = nickname;
160 member.peer = event->peer;
161
162 members.push_back(member);
163
164 // Notify everyone that the room information has changed.
165 BroadcastRoomInformation();
166 SendJoinSuccess(event->peer, preferred_mac);
167}
168
169bool Room::RoomImpl::IsValidNickname(const std::string& nickname) const {
170 // A nickname is valid if it is not already taken by anybody else in the room.
171 // TODO(B3N30): Check for empty names, spaces, etc.
172 for (const Member& member : members) {
173 if (member.nickname == nickname) {
174 return false;
175 }
176 }
177 return true;
178}
179
180bool Room::RoomImpl::IsValidMacAddress(const MacAddress& address) const {
181 // A MAC address is valid if it is not already taken by anybody else in the room.
182 for (const Member& member : members) {
183 if (member.mac_address == address) {
184 return false;
185 }
186 }
187 return true;
188}
189
190void Room::RoomImpl::SendNameCollision(ENetPeer* client) {
191 Packet packet;
192 packet << static_cast<MessageID>(IdNameCollision);
193
194 ENetPacket* enet_packet =
195 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
196 enet_peer_send(client, 0, enet_packet);
197 enet_host_flush(server);
198}
199
200void Room::RoomImpl::SendMacCollision(ENetPeer* client) {
201 Packet packet;
202 packet << static_cast<MessageID>(IdMacCollision);
203
204 ENetPacket* enet_packet =
205 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
206 enet_peer_send(client, 0, enet_packet);
207 enet_host_flush(server);
208}
209
210void Room::RoomImpl::SendJoinSuccess(ENetPeer* client, MacAddress mac_address) {
211 Packet packet;
212 packet << static_cast<MessageID>(IdJoinSuccess);
213 packet << mac_address;
214 ENetPacket* enet_packet =
215 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
216 enet_peer_send(client, 0, enet_packet);
217 enet_host_flush(server);
218}
219
220void Room::RoomImpl::BroadcastRoomInformation() {
221 Packet packet;
222 packet << static_cast<MessageID>(IdRoomInformation);
223 packet << room_information.name;
224 packet << room_information.member_slots;
225
226 packet << static_cast<uint32_t>(members.size());
227 for (const auto& member : members) {
228 packet << member.nickname;
229 packet << member.mac_address;
230 packet << member.game_name;
231 }
232
233 ENetPacket* enet_packet =
234 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
235 enet_host_broadcast(server, 0, enet_packet);
236 enet_host_flush(server);
237}
238
239MacAddress Room::RoomImpl::GenerateMacAddress() {
240 MacAddress result_mac = NintendoOUI;
241 std::uniform_int_distribution<> dis(0x00, 0xFF); // Random byte between 0 and 0xFF
242 do {
243 for (int i = 3; i < result_mac.size(); ++i) {
244 result_mac[i] = dis(random_gen);
245 }
246 } while (!IsValidMacAddress(result_mac));
247 return result_mac;
248}
249
52// Room 250// Room
53Room::Room() : room_impl{std::make_unique<RoomImpl>()} {} 251Room::Room() : room_impl{std::make_unique<RoomImpl>()} {}
54 252
diff --git a/src/network/room.h b/src/network/room.h
index 0a6217c11..ca663058f 100644
--- a/src/network/room.h
+++ b/src/network/room.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <memory> 8#include <memory>
8#include <string> 9#include <string>
9#include "common/common_types.h" 10#include "common/common_types.h"
@@ -18,6 +19,11 @@ struct RoomInformation {
18 u32 member_slots; ///< Maximum number of members in this room 19 u32 member_slots; ///< Maximum number of members in this room
19}; 20};
20 21
22using MacAddress = std::array<uint8_t, 6>;
23/// A special MAC address that tells the room we're joining to assign us a MAC address
24/// automatically.
25const MacAddress NoPreferredMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
26
21// The different types of messages that can be sent. The first byte of each packet defines the type 27// The different types of messages that can be sent. The first byte of each packet defines the type
22typedef uint8_t MessageID; 28typedef uint8_t MessageID;
23enum RoomMessageTypes { 29enum RoomMessageTypes {