summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/room.cpp170
-rw-r--r--src/network/room.h14
-rw-r--r--src/network/room_member.cpp123
-rw-r--r--src/network/room_member.h70
4 files changed, 168 insertions, 209 deletions
diff --git a/src/network/room.cpp b/src/network/room.cpp
index 3fc3a0383..b06797bf1 100644
--- a/src/network/room.cpp
+++ b/src/network/room.cpp
@@ -20,9 +20,7 @@ namespace Network {
20 20
21class Room::RoomImpl { 21class Room::RoomImpl {
22public: 22public:
23 // This MAC address is used to generate a 'Nintendo' like Mac address. 23 std::mt19937 random_gen; ///< Random number generator. Used for GenerateFakeIPAddress
24 const MacAddress NintendoOUI;
25 std::mt19937 random_gen; ///< Random number generator. Used for GenerateMacAddress
26 24
27 ENetHost* server = nullptr; ///< Network interface. 25 ENetHost* server = nullptr; ///< Network interface.
28 26
@@ -35,10 +33,9 @@ public:
35 std::string password; ///< The password required to connect to this room. 33 std::string password; ///< The password required to connect to this room.
36 34
37 struct Member { 35 struct Member {
38 std::string nickname; ///< The nickname of the member. 36 std::string nickname; ///< The nickname of the member.
39 std::string console_id_hash; ///< A hash of the console ID of the member. 37 GameInfo game_info; ///< The current game of the member
40 GameInfo game_info; ///< The current game of the member 38 IPv4Address fake_ip; ///< The assigned fake ip address of the member.
41 MacAddress mac_address; ///< The assigned mac address of the member.
42 /// Data of the user, often including authenticated forum username. 39 /// Data of the user, often including authenticated forum username.
43 VerifyUser::UserData user_data; 40 VerifyUser::UserData user_data;
44 ENetPeer* peer; ///< The remote peer. 41 ENetPeer* peer; ///< The remote peer.
@@ -51,8 +48,7 @@ public:
51 IPBanList ip_ban_list; ///< List of banned IP addresses 48 IPBanList ip_ban_list; ///< List of banned IP addresses
52 mutable std::mutex ban_list_mutex; ///< Mutex for the ban lists 49 mutable std::mutex ban_list_mutex; ///< Mutex for the ban lists
53 50
54 RoomImpl() 51 RoomImpl() : random_gen(std::random_device()()) {}
55 : NintendoOUI{0x00, 0x1F, 0x32, 0x00, 0x00, 0x00}, random_gen(std::random_device()()) {}
56 52
57 /// Thread that receives and dispatches network packets 53 /// Thread that receives and dispatches network packets
58 std::unique_ptr<std::thread> room_thread; 54 std::unique_ptr<std::thread> room_thread;
@@ -101,16 +97,10 @@ public:
101 bool IsValidNickname(const std::string& nickname) const; 97 bool IsValidNickname(const std::string& nickname) const;
102 98
103 /** 99 /**
104 * Returns whether the MAC address is valid, ie. isn't already taken by someone else in the 100 * Returns whether the fake ip address is valid, ie. isn't already taken by someone else in the
105 * room. 101 * room.
106 */ 102 */
107 bool IsValidMacAddress(const MacAddress& address) const; 103 bool IsValidFakeIPAddress(const IPv4Address& address) const;
108
109 /**
110 * Returns whether the console ID (hash) is valid, ie. isn't already taken by someone else in
111 * the room.
112 */
113 bool IsValidConsoleId(const std::string& console_id_hash) const;
114 104
115 /** 105 /**
116 * Returns whether a user has mod permissions. 106 * Returns whether a user has mod permissions.
@@ -128,15 +118,9 @@ public:
128 void SendNameCollision(ENetPeer* client); 118 void SendNameCollision(ENetPeer* client);
129 119
130 /** 120 /**
131 * Sends a ID_ROOM_MAC_COLLISION message telling the client that the MAC is invalid. 121 * Sends a ID_ROOM_IP_COLLISION message telling the client that the IP is invalid.
132 */ 122 */
133 void SendMacCollision(ENetPeer* client); 123 void SendIPCollision(ENetPeer* client);
134
135 /**
136 * Sends a IdConsoleIdCollison message telling the client that another member with the same
137 * console ID exists.
138 */
139 void SendConsoleIdCollision(ENetPeer* client);
140 124
141 /** 125 /**
142 * Sends a ID_ROOM_VERSION_MISMATCH message telling the client that the version is invalid. 126 * Sends a ID_ROOM_VERSION_MISMATCH message telling the client that the version is invalid.
@@ -152,13 +136,13 @@ public:
152 * Notifies the member that its connection attempt was successful, 136 * Notifies the member that its connection attempt was successful,
153 * and it is now part of the room. 137 * and it is now part of the room.
154 */ 138 */
155 void SendJoinSuccess(ENetPeer* client, MacAddress mac_address); 139 void SendJoinSuccess(ENetPeer* client, IPv4Address fake_ip);
156 140
157 /** 141 /**
158 * Notifies the member that its connection attempt was successful, 142 * Notifies the member that its connection attempt was successful,
159 * and it is now part of the room, and it has been granted mod permissions. 143 * and it is now part of the room, and it has been granted mod permissions.
160 */ 144 */
161 void SendJoinSuccessAsMod(ENetPeer* client, MacAddress mac_address); 145 void SendJoinSuccessAsMod(ENetPeer* client, IPv4Address fake_ip);
162 146
163 /** 147 /**
164 * Sends a IdHostKicked message telling the client that they have been kicked. 148 * Sends a IdHostKicked message telling the client that they have been kicked.
@@ -210,7 +194,7 @@ public:
210 * <u32> num_members: the number of currently joined clients 194 * <u32> num_members: the number of currently joined clients
211 * This is followed by the following three values for each member: 195 * This is followed by the following three values for each member:
212 * <String> nickname of that member 196 * <String> nickname of that member
213 * <MacAddress> mac_address of that member 197 * <IPv4Address> fake_ip of that member
214 * <String> game_name of that member 198 * <String> game_name of that member
215 */ 199 */
216 void BroadcastRoomInformation(); 200 void BroadcastRoomInformation();
@@ -219,13 +203,13 @@ public:
219 * Generates a free MAC address to assign to a new client. 203 * Generates a free MAC address to assign to a new client.
220 * The first 3 bytes are the NintendoOUI 0x00, 0x1F, 0x32 204 * The first 3 bytes are the NintendoOUI 0x00, 0x1F, 0x32
221 */ 205 */
222 MacAddress GenerateMacAddress(); 206 IPv4Address GenerateFakeIPAddress();
223 207
224 /** 208 /**
225 * Broadcasts this packet to all members except the sender. 209 * Broadcasts this packet to all members except the sender.
226 * @param event The ENet event containing the data 210 * @param event The ENet event containing the data
227 */ 211 */
228 void HandleWifiPacket(const ENetEvent* event); 212 void HandleProxyPacket(const ENetEvent* event);
229 213
230 /** 214 /**
231 * Extracts a chat entry from a received ENet packet and adds it to the chat queue. 215 * Extracts a chat entry from a received ENet packet and adds it to the chat queue.
@@ -250,7 +234,7 @@ public:
250void Room::RoomImpl::ServerLoop() { 234void Room::RoomImpl::ServerLoop() {
251 while (state != State::Closed) { 235 while (state != State::Closed) {
252 ENetEvent event; 236 ENetEvent event;
253 if (enet_host_service(server, &event, 16) > 0) { 237 if (enet_host_service(server, &event, 50) > 0) {
254 switch (event.type) { 238 switch (event.type) {
255 case ENET_EVENT_TYPE_RECEIVE: 239 case ENET_EVENT_TYPE_RECEIVE:
256 switch (event.packet->data[0]) { 240 switch (event.packet->data[0]) {
@@ -260,8 +244,8 @@ void Room::RoomImpl::ServerLoop() {
260 case IdSetGameInfo: 244 case IdSetGameInfo:
261 HandleGameNamePacket(&event); 245 HandleGameNamePacket(&event);
262 break; 246 break;
263 case IdWifiPacket: 247 case IdProxyPacket:
264 HandleWifiPacket(&event); 248 HandleProxyPacket(&event);
265 break; 249 break;
266 case IdChatMessage: 250 case IdChatMessage:
267 HandleChatPacket(&event); 251 HandleChatPacket(&event);
@@ -313,11 +297,8 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
313 std::string nickname; 297 std::string nickname;
314 packet.Read(nickname); 298 packet.Read(nickname);
315 299
316 std::string console_id_hash; 300 IPv4Address preferred_fake_ip;
317 packet.Read(console_id_hash); 301 packet.Read(preferred_fake_ip);
318
319 MacAddress preferred_mac;
320 packet.Read(preferred_mac);
321 302
322 u32 client_version; 303 u32 client_version;
323 packet.Read(client_version); 304 packet.Read(client_version);
@@ -338,20 +319,15 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
338 return; 319 return;
339 } 320 }
340 321
341 if (preferred_mac != NoPreferredMac) { 322 if (preferred_fake_ip != NoPreferredIP) {
342 // Verify if the preferred mac is available 323 // Verify if the preferred fake ip is available
343 if (!IsValidMacAddress(preferred_mac)) { 324 if (!IsValidFakeIPAddress(preferred_fake_ip)) {
344 SendMacCollision(event->peer); 325 SendIPCollision(event->peer);
345 return; 326 return;
346 } 327 }
347 } else { 328 } else {
348 // Assign a MAC address of this client automatically 329 // Assign a fake ip address of this client automatically
349 preferred_mac = GenerateMacAddress(); 330 preferred_fake_ip = GenerateFakeIPAddress();
350 }
351
352 if (!IsValidConsoleId(console_id_hash)) {
353 SendConsoleIdCollision(event->peer);
354 return;
355 } 331 }
356 332
357 if (client_version != network_version) { 333 if (client_version != network_version) {
@@ -361,8 +337,7 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
361 337
362 // At this point the client is ready to be added to the room. 338 // At this point the client is ready to be added to the room.
363 Member member{}; 339 Member member{};
364 member.mac_address = preferred_mac; 340 member.fake_ip = preferred_fake_ip;
365 member.console_id_hash = console_id_hash;
366 member.nickname = nickname; 341 member.nickname = nickname;
367 member.peer = event->peer; 342 member.peer = event->peer;
368 343
@@ -408,9 +383,9 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
408 // Notify everyone that the room information has changed. 383 // Notify everyone that the room information has changed.
409 BroadcastRoomInformation(); 384 BroadcastRoomInformation();
410 if (HasModPermission(event->peer)) { 385 if (HasModPermission(event->peer)) {
411 SendJoinSuccessAsMod(event->peer, preferred_mac); 386 SendJoinSuccessAsMod(event->peer, preferred_fake_ip);
412 } else { 387 } else {
413 SendJoinSuccess(event->peer, preferred_mac); 388 SendJoinSuccess(event->peer, preferred_fake_ip);
414 } 389 }
415} 390}
416 391
@@ -575,19 +550,11 @@ bool Room::RoomImpl::IsValidNickname(const std::string& nickname) const {
575 [&nickname](const auto& member) { return member.nickname != nickname; }); 550 [&nickname](const auto& member) { return member.nickname != nickname; });
576} 551}
577 552
578bool Room::RoomImpl::IsValidMacAddress(const MacAddress& address) const { 553bool Room::RoomImpl::IsValidFakeIPAddress(const IPv4Address& address) const {
579 // A MAC address is valid if it is not already taken by anybody else in the room. 554 // An IP address is valid if it is not already taken by anybody else in the room.
580 std::lock_guard lock(member_mutex); 555 std::lock_guard lock(member_mutex);
581 return std::all_of(members.begin(), members.end(), 556 return std::all_of(members.begin(), members.end(),
582 [&address](const auto& member) { return member.mac_address != address; }); 557 [&address](const auto& member) { return member.fake_ip != address; });
583}
584
585bool Room::RoomImpl::IsValidConsoleId(const std::string& console_id_hash) const {
586 // A Console ID is valid if it is not already taken by anybody else in the room.
587 std::lock_guard lock(member_mutex);
588 return std::all_of(members.begin(), members.end(), [&console_id_hash](const auto& member) {
589 return member.console_id_hash != console_id_hash;
590 });
591} 558}
592 559
593bool Room::RoomImpl::HasModPermission(const ENetPeer* client) const { 560bool Room::RoomImpl::HasModPermission(const ENetPeer* client) const {
@@ -621,19 +588,9 @@ void Room::RoomImpl::SendNameCollision(ENetPeer* client) {
621 enet_host_flush(server); 588 enet_host_flush(server);
622} 589}
623 590
624void Room::RoomImpl::SendMacCollision(ENetPeer* client) { 591void Room::RoomImpl::SendIPCollision(ENetPeer* client) {
625 Packet packet; 592 Packet packet;
626 packet.Write(static_cast<u8>(IdMacCollision)); 593 packet.Write(static_cast<u8>(IdIpCollision));
627
628 ENetPacket* enet_packet =
629 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
630 enet_peer_send(client, 0, enet_packet);
631 enet_host_flush(server);
632}
633
634void Room::RoomImpl::SendConsoleIdCollision(ENetPeer* client) {
635 Packet packet;
636 packet.Write(static_cast<u8>(IdConsoleIdCollision));
637 594
638 ENetPacket* enet_packet = 595 ENetPacket* enet_packet =
639 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); 596 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
@@ -672,20 +629,20 @@ void Room::RoomImpl::SendVersionMismatch(ENetPeer* client) {
672 enet_host_flush(server); 629 enet_host_flush(server);
673} 630}
674 631
675void Room::RoomImpl::SendJoinSuccess(ENetPeer* client, MacAddress mac_address) { 632void Room::RoomImpl::SendJoinSuccess(ENetPeer* client, IPv4Address fake_ip) {
676 Packet packet; 633 Packet packet;
677 packet.Write(static_cast<u8>(IdJoinSuccess)); 634 packet.Write(static_cast<u8>(IdJoinSuccess));
678 packet.Write(mac_address); 635 packet.Write(fake_ip);
679 ENetPacket* enet_packet = 636 ENetPacket* enet_packet =
680 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); 637 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
681 enet_peer_send(client, 0, enet_packet); 638 enet_peer_send(client, 0, enet_packet);
682 enet_host_flush(server); 639 enet_host_flush(server);
683} 640}
684 641
685void Room::RoomImpl::SendJoinSuccessAsMod(ENetPeer* client, MacAddress mac_address) { 642void Room::RoomImpl::SendJoinSuccessAsMod(ENetPeer* client, IPv4Address fake_ip) {
686 Packet packet; 643 Packet packet;
687 packet.Write(static_cast<u8>(IdJoinSuccessAsMod)); 644 packet.Write(static_cast<u8>(IdJoinSuccessAsMod));
688 packet.Write(mac_address); 645 packet.Write(fake_ip);
689 ENetPacket* enet_packet = 646 ENetPacket* enet_packet =
690 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); 647 enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE);
691 enet_peer_send(client, 0, enet_packet); 648 enet_peer_send(client, 0, enet_packet);
@@ -818,7 +775,7 @@ void Room::RoomImpl::BroadcastRoomInformation() {
818 std::lock_guard lock(member_mutex); 775 std::lock_guard lock(member_mutex);
819 for (const auto& member : members) { 776 for (const auto& member : members) {
820 packet.Write(member.nickname); 777 packet.Write(member.nickname);
821 packet.Write(member.mac_address); 778 packet.Write(member.fake_ip);
822 packet.Write(member.game_info.name); 779 packet.Write(member.game_info.name);
823 packet.Write(member.game_info.id); 780 packet.Write(member.game_info.id);
824 packet.Write(member.user_data.username); 781 packet.Write(member.user_data.username);
@@ -833,34 +790,43 @@ void Room::RoomImpl::BroadcastRoomInformation() {
833 enet_host_flush(server); 790 enet_host_flush(server);
834} 791}
835 792
836MacAddress Room::RoomImpl::GenerateMacAddress() { 793IPv4Address Room::RoomImpl::GenerateFakeIPAddress() {
837 MacAddress result_mac = 794 IPv4Address result_ip{192, 168, 0, 0};
838 NintendoOUI; // The first three bytes of each MAC address will be the NintendoOUI 795 std::uniform_int_distribution<> dis(0x01, 0xFE); // Random byte between 1 and 0xFE
839 std::uniform_int_distribution<> dis(0x00, 0xFF); // Random byte between 0 and 0xFF
840 do { 796 do {
841 for (std::size_t i = 3; i < result_mac.size(); ++i) { 797 for (std::size_t i = 2; i < result_ip.size(); ++i) {
842 result_mac[i] = dis(random_gen); 798 result_ip[i] = dis(random_gen);
843 } 799 }
844 } while (!IsValidMacAddress(result_mac)); 800 } while (!IsValidFakeIPAddress(result_ip));
845 return result_mac; 801
802 return result_ip;
846} 803}
847 804
848void Room::RoomImpl::HandleWifiPacket(const ENetEvent* event) { 805void Room::RoomImpl::HandleProxyPacket(const ENetEvent* event) {
849 Packet in_packet; 806 Packet in_packet;
850 in_packet.Append(event->packet->data, event->packet->dataLength); 807 in_packet.Append(event->packet->data, event->packet->dataLength);
851 in_packet.IgnoreBytes(sizeof(u8)); // Message type 808 in_packet.IgnoreBytes(sizeof(u8)); // Message type
852 in_packet.IgnoreBytes(sizeof(u8)); // WifiPacket Type 809
853 in_packet.IgnoreBytes(sizeof(u8)); // WifiPacket Channel 810 in_packet.IgnoreBytes(sizeof(u8)); // Domain
854 in_packet.IgnoreBytes(sizeof(MacAddress)); // WifiPacket Transmitter Address 811 in_packet.IgnoreBytes(sizeof(IPv4Address)); // IP
855 MacAddress destination_address; 812 in_packet.IgnoreBytes(sizeof(u16)); // Port
856 in_packet.Read(destination_address); 813
814 in_packet.IgnoreBytes(sizeof(u8)); // Domain
815 IPv4Address remote_ip;
816 in_packet.Read(remote_ip); // IP
817 in_packet.IgnoreBytes(sizeof(u16)); // Port
818
819 in_packet.IgnoreBytes(sizeof(u8)); // Protocol
820 bool broadcast;
821 in_packet.Read(broadcast); // Broadcast
857 822
858 Packet out_packet; 823 Packet out_packet;
859 out_packet.Append(event->packet->data, event->packet->dataLength); 824 out_packet.Append(event->packet->data, event->packet->dataLength);
860 ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(), 825 ENetPacket* enet_packet = enet_packet_create(out_packet.GetData(), out_packet.GetDataSize(),
861 ENET_PACKET_FLAG_RELIABLE); 826 ENET_PACKET_FLAG_RELIABLE);
862 827
863 if (destination_address == BroadcastMac) { // Send the data to everyone except the sender 828 const auto& destination_address = remote_ip;
829 if (broadcast) { // Send the data to everyone except the sender
864 std::lock_guard lock(member_mutex); 830 std::lock_guard lock(member_mutex);
865 bool sent_packet = false; 831 bool sent_packet = false;
866 for (const auto& member : members) { 832 for (const auto& member : members) {
@@ -877,16 +843,16 @@ void Room::RoomImpl::HandleWifiPacket(const ENetEvent* event) {
877 std::lock_guard lock(member_mutex); 843 std::lock_guard lock(member_mutex);
878 auto member = std::find_if(members.begin(), members.end(), 844 auto member = std::find_if(members.begin(), members.end(),
879 [destination_address](const Member& member_entry) -> bool { 845 [destination_address](const Member& member_entry) -> bool {
880 return member_entry.mac_address == destination_address; 846 return member_entry.fake_ip == destination_address;
881 }); 847 });
882 if (member != members.end()) { 848 if (member != members.end()) {
883 enet_peer_send(member->peer, 0, enet_packet); 849 enet_peer_send(member->peer, 0, enet_packet);
884 } else { 850 } else {
885 LOG_ERROR(Network, 851 LOG_ERROR(Network,
886 "Attempting to send to unknown MAC address: " 852 "Attempting to send to unknown IP address: "
887 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}", 853 "{}.{}.{}.{}",
888 destination_address[0], destination_address[1], destination_address[2], 854 destination_address[0], destination_address[1], destination_address[2],
889 destination_address[3], destination_address[4], destination_address[5]); 855 destination_address[3]);
890 enet_packet_destroy(enet_packet); 856 enet_packet_destroy(enet_packet);
891 } 857 }
892 } 858 }
@@ -1073,7 +1039,7 @@ std::vector<Member> Room::GetRoomMemberList() const {
1073 member.username = member_impl.user_data.username; 1039 member.username = member_impl.user_data.username;
1074 member.display_name = member_impl.user_data.display_name; 1040 member.display_name = member_impl.user_data.display_name;
1075 member.avatar_url = member_impl.user_data.avatar_url; 1041 member.avatar_url = member_impl.user_data.avatar_url;
1076 member.mac_address = member_impl.mac_address; 1042 member.fake_ip = member_impl.fake_ip;
1077 member.game = member_impl.game_info; 1043 member.game = member_impl.game_info;
1078 member_list.push_back(member); 1044 member_list.push_back(member);
1079 } 1045 }
diff --git a/src/network/room.h b/src/network/room.h
index 6f7e3b5b5..c2a4b1a70 100644
--- a/src/network/room.h
+++ b/src/network/room.h
@@ -9,12 +9,12 @@
9#include <vector> 9#include <vector>
10#include "common/announce_multiplayer_room.h" 10#include "common/announce_multiplayer_room.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/socket_types.h"
12#include "network/verify_user.h" 13#include "network/verify_user.h"
13 14
14namespace Network { 15namespace Network {
15 16
16using AnnounceMultiplayerRoom::GameInfo; 17using AnnounceMultiplayerRoom::GameInfo;
17using AnnounceMultiplayerRoom::MacAddress;
18using AnnounceMultiplayerRoom::Member; 18using AnnounceMultiplayerRoom::Member;
19using AnnounceMultiplayerRoom::RoomInformation; 19using AnnounceMultiplayerRoom::RoomInformation;
20 20
@@ -29,12 +29,9 @@ static constexpr u32 MaxConcurrentConnections = 254;
29 29
30constexpr std::size_t NumChannels = 1; // Number of channels used for the connection 30constexpr std::size_t NumChannels = 1; // Number of channels used for the connection
31 31
32/// A special MAC address that tells the room we're joining to assign us a MAC address 32/// A special IP address that tells the room we're joining to assign us a IP address
33/// automatically. 33/// automatically.
34constexpr MacAddress NoPreferredMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 34constexpr IPv4Address NoPreferredIP = {0xFF, 0xFF, 0xFF, 0xFF};
35
36// 802.11 broadcast MAC address
37constexpr MacAddress BroadcastMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
38 35
39// The different types of messages that can be sent. The first byte of each packet defines the type 36// The different types of messages that can be sent. The first byte of each packet defines the type
40enum RoomMessageTypes : u8 { 37enum RoomMessageTypes : u8 {
@@ -42,15 +39,14 @@ enum RoomMessageTypes : u8 {
42 IdJoinSuccess, 39 IdJoinSuccess,
43 IdRoomInformation, 40 IdRoomInformation,
44 IdSetGameInfo, 41 IdSetGameInfo,
45 IdWifiPacket, 42 IdProxyPacket,
46 IdChatMessage, 43 IdChatMessage,
47 IdNameCollision, 44 IdNameCollision,
48 IdMacCollision, 45 IdIpCollision,
49 IdVersionMismatch, 46 IdVersionMismatch,
50 IdWrongPassword, 47 IdWrongPassword,
51 IdCloseRoom, 48 IdCloseRoom,
52 IdRoomIsFull, 49 IdRoomIsFull,
53 IdConsoleIdCollision,
54 IdStatusMessage, 50 IdStatusMessage,
55 IdHostKicked, 51 IdHostKicked,
56 IdHostBanned, 52 IdHostBanned,
diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp
index e4f823e98..9f08bf611 100644
--- a/src/network/room_member.cpp
+++ b/src/network/room_member.cpp
@@ -7,6 +7,7 @@
7#include <set> 7#include <set>
8#include <thread> 8#include <thread>
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/socket_types.h"
10#include "enet/enet.h" 11#include "enet/enet.h"
11#include "network/packet.h" 12#include "network/packet.h"
12#include "network/room_member.h" 13#include "network/room_member.h"
@@ -38,7 +39,7 @@ public:
38 std::string username; ///< The username of this member. 39 std::string username; ///< The username of this member.
39 mutable std::mutex username_mutex; ///< Mutex for locking username. 40 mutable std::mutex username_mutex; ///< Mutex for locking username.
40 41
41 MacAddress mac_address; ///< The mac_address of this member. 42 IPv4Address fake_ip; ///< The fake ip of this member.
42 43
43 std::mutex network_mutex; ///< Mutex that controls access to the `client` variable. 44 std::mutex network_mutex; ///< Mutex that controls access to the `client` variable.
44 /// Thread that receives and dispatches network packets 45 /// Thread that receives and dispatches network packets
@@ -56,7 +57,7 @@ public:
56 CallbackSet<T>& Get(); 57 CallbackSet<T>& Get();
57 58
58 private: 59 private:
59 CallbackSet<WifiPacket> callback_set_wifi_packet; 60 CallbackSet<ProxyPacket> callback_set_proxy_packet;
60 CallbackSet<ChatEntry> callback_set_chat_messages; 61 CallbackSet<ChatEntry> callback_set_chat_messages;
61 CallbackSet<StatusMessageEntry> callback_set_status_messages; 62 CallbackSet<StatusMessageEntry> callback_set_status_messages;
62 CallbackSet<RoomInformation> callback_set_room_information; 63 CallbackSet<RoomInformation> callback_set_room_information;
@@ -78,15 +79,15 @@ public:
78 79
79 /** 80 /**
80 * Sends a request to the server, asking for permission to join a room with the specified 81 * Sends a request to the server, asking for permission to join a room with the specified
81 * nickname and preferred mac. 82 * nickname and preferred fake ip.
82 * @params nickname The desired nickname. 83 * @params nickname The desired nickname.
83 * @params console_id_hash A hash of the Console ID. 84 * @params preferred_fake_ip The preferred IP address to use in the room, the NoPreferredIP
84 * @params preferred_mac The preferred MAC address to use in the room, the NoPreferredMac tells 85 * tells
85 * @params password The password for the room 86 * @params password The password for the room
86 * the server to assign one for us. 87 * the server to assign one for us.
87 */ 88 */
88 void SendJoinRequest(const std::string& nickname_, const std::string& console_id_hash, 89 void SendJoinRequest(const std::string& nickname_,
89 const MacAddress& preferred_mac = NoPreferredMac, 90 const IPv4Address& preferred_fake_ip = NoPreferredIP,
90 const std::string& password = "", const std::string& token = ""); 91 const std::string& password = "", const std::string& token = "");
91 92
92 /** 93 /**
@@ -101,10 +102,10 @@ public:
101 void HandleRoomInformationPacket(const ENetEvent* event); 102 void HandleRoomInformationPacket(const ENetEvent* event);
102 103
103 /** 104 /**
104 * Extracts a WifiPacket from a received ENet packet. 105 * Extracts a ProxyPacket from a received ENet packet.
105 * @param event The ENet event that was received. 106 * @param event The ENet event that was received.
106 */ 107 */
107 void HandleWifiPackets(const ENetEvent* event); 108 void HandleProxyPackets(const ENetEvent* event);
108 109
109 /** 110 /**
110 * Extracts a chat entry from a received ENet packet and adds it to the chat queue. 111 * Extracts a chat entry from a received ENet packet and adds it to the chat queue.
@@ -158,12 +159,12 @@ void RoomMember::RoomMemberImpl::MemberLoop() {
158 while (IsConnected()) { 159 while (IsConnected()) {
159 std::lock_guard lock(network_mutex); 160 std::lock_guard lock(network_mutex);
160 ENetEvent event; 161 ENetEvent event;
161 if (enet_host_service(client, &event, 16) > 0) { 162 if (enet_host_service(client, &event, 100) > 0) {
162 switch (event.type) { 163 switch (event.type) {
163 case ENET_EVENT_TYPE_RECEIVE: 164 case ENET_EVENT_TYPE_RECEIVE:
164 switch (event.packet->data[0]) { 165 switch (event.packet->data[0]) {
165 case IdWifiPacket: 166 case IdProxyPacket:
166 HandleWifiPackets(&event); 167 HandleProxyPackets(&event);
167 break; 168 break;
168 case IdChatMessage: 169 case IdChatMessage:
169 HandleChatPacket(&event); 170 HandleChatPacket(&event);
@@ -198,13 +199,9 @@ void RoomMember::RoomMemberImpl::MemberLoop() {
198 SetState(State::Idle); 199 SetState(State::Idle);
199 SetError(Error::NameCollision); 200 SetError(Error::NameCollision);
200 break; 201 break;
201 case IdMacCollision: 202 case IdIpCollision:
202 SetState(State::Idle); 203 SetState(State::Idle);
203 SetError(Error::MacCollision); 204 SetError(Error::IpCollision);
204 break;
205 case IdConsoleIdCollision:
206 SetState(State::Idle);
207 SetError(Error::ConsoleIdCollision);
208 break; 205 break;
209 case IdVersionMismatch: 206 case IdVersionMismatch:
210 SetState(State::Idle); 207 SetState(State::Idle);
@@ -275,15 +272,13 @@ void RoomMember::RoomMemberImpl::Send(Packet&& packet) {
275} 272}
276 273
277void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname_, 274void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname_,
278 const std::string& console_id_hash, 275 const IPv4Address& preferred_fake_ip,
279 const MacAddress& preferred_mac,
280 const std::string& password, 276 const std::string& password,
281 const std::string& token) { 277 const std::string& token) {
282 Packet packet; 278 Packet packet;
283 packet.Write(static_cast<u8>(IdJoinRequest)); 279 packet.Write(static_cast<u8>(IdJoinRequest));
284 packet.Write(nickname_); 280 packet.Write(nickname_);
285 packet.Write(console_id_hash); 281 packet.Write(preferred_fake_ip);
286 packet.Write(preferred_mac);
287 packet.Write(network_version); 282 packet.Write(network_version);
288 packet.Write(password); 283 packet.Write(password);
289 packet.Write(token); 284 packet.Write(token);
@@ -317,7 +312,7 @@ void RoomMember::RoomMemberImpl::HandleRoomInformationPacket(const ENetEvent* ev
317 312
318 for (auto& member : member_information) { 313 for (auto& member : member_information) {
319 packet.Read(member.nickname); 314 packet.Read(member.nickname);
320 packet.Read(member.mac_address); 315 packet.Read(member.fake_ip);
321 packet.Read(member.game_info.name); 316 packet.Read(member.game_info.name);
322 packet.Read(member.game_info.id); 317 packet.Read(member.game_info.id);
323 packet.Read(member.username); 318 packet.Read(member.username);
@@ -342,29 +337,38 @@ void RoomMember::RoomMemberImpl::HandleJoinPacket(const ENetEvent* event) {
342 packet.IgnoreBytes(sizeof(u8)); // Ignore the message type 337 packet.IgnoreBytes(sizeof(u8)); // Ignore the message type
343 338
344 // Parse the MAC Address from the packet 339 // Parse the MAC Address from the packet
345 packet.Read(mac_address); 340 packet.Read(fake_ip);
346} 341}
347 342
348void RoomMember::RoomMemberImpl::HandleWifiPackets(const ENetEvent* event) { 343void RoomMember::RoomMemberImpl::HandleProxyPackets(const ENetEvent* event) {
349 WifiPacket wifi_packet{}; 344 ProxyPacket proxy_packet{};
350 Packet packet; 345 Packet packet;
351 packet.Append(event->packet->data, event->packet->dataLength); 346 packet.Append(event->packet->data, event->packet->dataLength);
352 347
353 // Ignore the first byte, which is the message id. 348 // Ignore the first byte, which is the message id.
354 packet.IgnoreBytes(sizeof(u8)); // Ignore the message type 349 packet.IgnoreBytes(sizeof(u8)); // Ignore the message type
355 350
356 // Parse the WifiPacket from the packet 351 // Parse the ProxyPacket from the packet
357 u8 frame_type; 352 u8 local_family;
358 packet.Read(frame_type); 353 packet.Read(local_family);
359 WifiPacket::PacketType type = static_cast<WifiPacket::PacketType>(frame_type); 354 proxy_packet.local_endpoint.family = static_cast<Domain>(local_family);
355 packet.Read(proxy_packet.local_endpoint.ip);
356 packet.Read(proxy_packet.local_endpoint.portno);
357
358 u8 remote_family;
359 packet.Read(remote_family);
360 proxy_packet.remote_endpoint.family = static_cast<Domain>(remote_family);
361 packet.Read(proxy_packet.remote_endpoint.ip);
362 packet.Read(proxy_packet.remote_endpoint.portno);
363
364 u8 protocol_type;
365 packet.Read(protocol_type);
366 proxy_packet.protocol = static_cast<Protocol>(protocol_type);
360 367
361 wifi_packet.type = type; 368 packet.Read(proxy_packet.broadcast);
362 packet.Read(wifi_packet.channel); 369 packet.Read(proxy_packet.data);
363 packet.Read(wifi_packet.transmitter_address);
364 packet.Read(wifi_packet.destination_address);
365 packet.Read(wifi_packet.data);
366 370
367 Invoke<WifiPacket>(wifi_packet); 371 Invoke<ProxyPacket>(proxy_packet);
368} 372}
369 373
370void RoomMember::RoomMemberImpl::HandleChatPacket(const ENetEvent* event) { 374void RoomMember::RoomMemberImpl::HandleChatPacket(const ENetEvent* event) {
@@ -440,8 +444,8 @@ void RoomMember::RoomMemberImpl::Disconnect() {
440} 444}
441 445
442template <> 446template <>
443RoomMember::RoomMemberImpl::CallbackSet<WifiPacket>& RoomMember::RoomMemberImpl::Callbacks::Get() { 447RoomMember::RoomMemberImpl::CallbackSet<ProxyPacket>& RoomMember::RoomMemberImpl::Callbacks::Get() {
444 return callback_set_wifi_packet; 448 return callback_set_proxy_packet;
445} 449}
446 450
447template <> 451template <>
@@ -525,19 +529,18 @@ const std::string& RoomMember::GetUsername() const {
525 return room_member_impl->username; 529 return room_member_impl->username;
526} 530}
527 531
528const MacAddress& RoomMember::GetMacAddress() const { 532const IPv4Address& RoomMember::GetFakeIpAddress() const {
529 ASSERT_MSG(IsConnected(), "Tried to get MAC address while not connected"); 533 ASSERT_MSG(IsConnected(), "Tried to get fake ip address while not connected");
530 return room_member_impl->mac_address; 534 return room_member_impl->fake_ip;
531} 535}
532 536
533RoomInformation RoomMember::GetRoomInformation() const { 537RoomInformation RoomMember::GetRoomInformation() const {
534 return room_member_impl->room_information; 538 return room_member_impl->room_information;
535} 539}
536 540
537void RoomMember::Join(const std::string& nick, const std::string& console_id_hash, 541void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port,
538 const char* server_addr, u16 server_port, u16 client_port, 542 u16 client_port, const IPv4Address& preferred_fake_ip,
539 const MacAddress& preferred_mac, const std::string& password, 543 const std::string& password, const std::string& token) {
540 const std::string& token) {
541 // If the member is connected, kill the connection first 544 // If the member is connected, kill the connection first
542 if (room_member_impl->loop_thread && room_member_impl->loop_thread->joinable()) { 545 if (room_member_impl->loop_thread && room_member_impl->loop_thread->joinable()) {
543 Leave(); 546 Leave();
@@ -571,7 +574,7 @@ void RoomMember::Join(const std::string& nick, const std::string& console_id_has
571 if (net > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { 574 if (net > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
572 room_member_impl->nickname = nick; 575 room_member_impl->nickname = nick;
573 room_member_impl->StartLoop(); 576 room_member_impl->StartLoop();
574 room_member_impl->SendJoinRequest(nick, console_id_hash, preferred_mac, password, token); 577 room_member_impl->SendJoinRequest(nick, preferred_fake_ip, password, token);
575 SendGameInfo(room_member_impl->current_game_info); 578 SendGameInfo(room_member_impl->current_game_info);
576 } else { 579 } else {
577 enet_peer_disconnect(room_member_impl->server, 0); 580 enet_peer_disconnect(room_member_impl->server, 0);
@@ -584,14 +587,22 @@ bool RoomMember::IsConnected() const {
584 return room_member_impl->IsConnected(); 587 return room_member_impl->IsConnected();
585} 588}
586 589
587void RoomMember::SendWifiPacket(const WifiPacket& wifi_packet) { 590void RoomMember::SendProxyPacket(const ProxyPacket& proxy_packet) {
588 Packet packet; 591 Packet packet;
589 packet.Write(static_cast<u8>(IdWifiPacket)); 592 packet.Write(static_cast<u8>(IdProxyPacket));
590 packet.Write(static_cast<u8>(wifi_packet.type)); 593
591 packet.Write(wifi_packet.channel); 594 packet.Write(static_cast<u8>(proxy_packet.local_endpoint.family));
592 packet.Write(wifi_packet.transmitter_address); 595 packet.Write(proxy_packet.local_endpoint.ip);
593 packet.Write(wifi_packet.destination_address); 596 packet.Write(proxy_packet.local_endpoint.portno);
594 packet.Write(wifi_packet.data); 597
598 packet.Write(static_cast<u8>(proxy_packet.remote_endpoint.family));
599 packet.Write(proxy_packet.remote_endpoint.ip);
600 packet.Write(proxy_packet.remote_endpoint.portno);
601
602 packet.Write(static_cast<u8>(proxy_packet.protocol));
603 packet.Write(proxy_packet.broadcast);
604 packet.Write(proxy_packet.data);
605
595 room_member_impl->Send(std::move(packet)); 606 room_member_impl->Send(std::move(packet));
596} 607}
597 608
@@ -645,8 +656,8 @@ RoomMember::CallbackHandle<RoomMember::Error> RoomMember::BindOnError(
645 return room_member_impl->Bind(callback); 656 return room_member_impl->Bind(callback);
646} 657}
647 658
648RoomMember::CallbackHandle<WifiPacket> RoomMember::BindOnWifiPacketReceived( 659RoomMember::CallbackHandle<ProxyPacket> RoomMember::BindOnProxyPacketReceived(
649 std::function<void(const WifiPacket&)> callback) { 660 std::function<void(const ProxyPacket&)> callback) {
650 return room_member_impl->Bind(callback); 661 return room_member_impl->Bind(callback);
651} 662}
652 663
@@ -685,7 +696,7 @@ void RoomMember::Leave() {
685 room_member_impl->client = nullptr; 696 room_member_impl->client = nullptr;
686} 697}
687 698
688template void RoomMember::Unbind(CallbackHandle<WifiPacket>); 699template void RoomMember::Unbind(CallbackHandle<ProxyPacket>);
689template void RoomMember::Unbind(CallbackHandle<RoomMember::State>); 700template void RoomMember::Unbind(CallbackHandle<RoomMember::State>);
690template void RoomMember::Unbind(CallbackHandle<RoomMember::Error>); 701template void RoomMember::Unbind(CallbackHandle<RoomMember::Error>);
691template void RoomMember::Unbind(CallbackHandle<RoomInformation>); 702template void RoomMember::Unbind(CallbackHandle<RoomInformation>);
diff --git a/src/network/room_member.h b/src/network/room_member.h
index bbb7d13d4..4252b7146 100644
--- a/src/network/room_member.h
+++ b/src/network/room_member.h
@@ -9,6 +9,7 @@
9#include <vector> 9#include <vector>
10#include "common/announce_multiplayer_room.h" 10#include "common/announce_multiplayer_room.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/socket_types.h"
12#include "network/room.h" 13#include "network/room.h"
13 14
14namespace Network { 15namespace Network {
@@ -17,22 +18,12 @@ using AnnounceMultiplayerRoom::GameInfo;
17using AnnounceMultiplayerRoom::RoomInformation; 18using AnnounceMultiplayerRoom::RoomInformation;
18 19
19/// Information about the received WiFi packets. 20/// Information about the received WiFi packets.
20/// Acts as our own 802.11 header. 21struct ProxyPacket {
21struct WifiPacket { 22 SockAddrIn local_endpoint;
22 enum class PacketType : u8 { 23 SockAddrIn remote_endpoint;
23 Beacon, 24 Protocol protocol;
24 Data, 25 bool broadcast;
25 Authentication, 26 std::vector<u8> data;
26 AssociationResponse,
27 Deauthentication,
28 NodeMap
29 };
30 PacketType type; ///< The type of 802.11 frame.
31 std::vector<u8> data; ///< Raw 802.11 frame data, starting at the management frame header
32 /// for management frames.
33 MacAddress transmitter_address; ///< Mac address of the transmitter.
34 MacAddress destination_address; ///< Mac address of the receiver.
35 u8 channel; ///< WiFi channel where this frame was transmitted.
36}; 27};
37 28
38/// Represents a chat message. 29/// Represents a chat message.
@@ -72,15 +63,14 @@ public:
72 HostKicked, ///< Kicked by the host 63 HostKicked, ///< Kicked by the host
73 64
74 // Reasons why connection was rejected 65 // Reasons why connection was rejected
75 UnknownError, ///< Some error [permissions to network device missing or something] 66 UnknownError, ///< Some error [permissions to network device missing or something]
76 NameCollision, ///< Somebody is already using this name 67 NameCollision, ///< Somebody is already using this name
77 MacCollision, ///< Somebody is already using that mac-address 68 IpCollision, ///< Somebody is already using that fake-ip-address
78 ConsoleIdCollision, ///< Somebody in the room has the same Console ID 69 WrongVersion, ///< The room version is not the same as for this RoomMember
79 WrongVersion, ///< The room version is not the same as for this RoomMember 70 WrongPassword, ///< The password doesn't match the one from the Room
80 WrongPassword, ///< The password doesn't match the one from the Room 71 CouldNotConnect, ///< The room is not responding to a connection attempt
81 CouldNotConnect, ///< The room is not responding to a connection attempt 72 RoomIsFull, ///< Room is already at the maximum number of players
82 RoomIsFull, ///< Room is already at the maximum number of players 73 HostBanned, ///< The user is banned by the host
83 HostBanned, ///< The user is banned by the host
84 74
85 // Reasons why moderation request failed 75 // Reasons why moderation request failed
86 PermissionDenied, ///< The user does not have mod permissions 76 PermissionDenied, ///< The user does not have mod permissions
@@ -92,9 +82,9 @@ public:
92 std::string username; ///< The web services username of the member. Can be empty. 82 std::string username; ///< The web services username of the member. Can be empty.
93 std::string display_name; ///< The web services display name of the member. Can be empty. 83 std::string display_name; ///< The web services display name of the member. Can be empty.
94 std::string avatar_url; ///< Url to the member's avatar. Can be empty. 84 std::string avatar_url; ///< Url to the member's avatar. Can be empty.
95 GameInfo game_info; ///< Name of the game they're currently playing, or empty if they're 85 GameInfo game_info; ///< Name of the game they're currently playing, or empty if they're
96 /// not playing anything. 86 /// not playing anything.
97 MacAddress mac_address; ///< MAC address associated with this member. 87 IPv4Address fake_ip; ///< Fake Ip address associated with this member.
98 }; 88 };
99 using MemberList = std::vector<MemberInformation>; 89 using MemberList = std::vector<MemberInformation>;
100 90
@@ -135,7 +125,7 @@ public:
135 /** 125 /**
136 * Returns the MAC address of the RoomMember. 126 * Returns the MAC address of the RoomMember.
137 */ 127 */
138 const MacAddress& GetMacAddress() const; 128 const IPv4Address& GetFakeIpAddress() const;
139 129
140 /** 130 /**
141 * Returns information about the room we're currently connected to. 131 * Returns information about the room we're currently connected to.
@@ -149,19 +139,17 @@ public:
149 139
150 /** 140 /**
151 * Attempts to join a room at the specified address and port, using the specified nickname. 141 * Attempts to join a room at the specified address and port, using the specified nickname.
152 * A console ID hash is passed in to check console ID conflicts.
153 * This may fail if the username or console ID is already taken.
154 */ 142 */
155 void Join(const std::string& nickname, const std::string& console_id_hash, 143 void Join(const std::string& nickname, const char* server_addr = "127.0.0.1",
156 const char* server_addr = "127.0.0.1", u16 server_port = DefaultRoomPort, 144 u16 server_port = DefaultRoomPort, u16 client_port = 0,
157 u16 client_port = 0, const MacAddress& preferred_mac = NoPreferredMac, 145 const IPv4Address& preferred_fake_ip = NoPreferredIP,
158 const std::string& password = "", const std::string& token = ""); 146 const std::string& password = "", const std::string& token = "");
159 147
160 /** 148 /**
161 * Sends a WiFi packet to the room. 149 * Sends a WiFi packet to the room.
162 * @param packet The WiFi packet to send. 150 * @param packet The WiFi packet to send.
163 */ 151 */
164 void SendWifiPacket(const WifiPacket& packet); 152 void SendProxyPacket(const ProxyPacket& packet);
165 153
166 /** 154 /**
167 * Sends a chat message to the room. 155 * Sends a chat message to the room.
@@ -207,14 +195,14 @@ public:
207 CallbackHandle<Error> BindOnError(std::function<void(const Error&)> callback); 195 CallbackHandle<Error> BindOnError(std::function<void(const Error&)> callback);
208 196
209 /** 197 /**
210 * Binds a function to an event that will be triggered every time a WifiPacket is received. 198 * Binds a function to an event that will be triggered every time a ProxyPacket is received.
211 * The function wil be called everytime the event is triggered. 199 * The function wil be called everytime the event is triggered.
212 * The callback function must not bind or unbind a function. Doing so will cause a deadlock 200 * The callback function must not bind or unbind a function. Doing so will cause a deadlock
213 * @param callback The function to call 201 * @param callback The function to call
214 * @return A handle used for removing the function from the registered list 202 * @return A handle used for removing the function from the registered list
215 */ 203 */
216 CallbackHandle<WifiPacket> BindOnWifiPacketReceived( 204 CallbackHandle<ProxyPacket> BindOnProxyPacketReceived(
217 std::function<void(const WifiPacket&)> callback); 205 std::function<void(const ProxyPacket&)> callback);
218 206
219 /** 207 /**
220 * Binds a function to an event that will be triggered every time the RoomInformation changes. 208 * Binds a function to an event that will be triggered every time the RoomInformation changes.
@@ -292,10 +280,8 @@ inline const char* GetErrorStr(const RoomMember::Error& e) {
292 return "UnknownError"; 280 return "UnknownError";
293 case RoomMember::Error::NameCollision: 281 case RoomMember::Error::NameCollision:
294 return "NameCollision"; 282 return "NameCollision";
295 case RoomMember::Error::MacCollision: 283 case RoomMember::Error::IpCollision:
296 return "MaxCollision"; 284 return "IpCollision";
297 case RoomMember::Error::ConsoleIdCollision:
298 return "ConsoleIdCollision";
299 case RoomMember::Error::WrongVersion: 285 case RoomMember::Error::WrongVersion:
300 return "WrongVersion"; 286 return "WrongVersion";
301 case RoomMember::Error::WrongPassword: 287 case RoomMember::Error::WrongPassword: