room_member.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // Copyright 2017 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <functional>
  6. #include <memory>
  7. #include <string>
  8. #include <vector>
  9. #include <boost/serialization/vector.hpp>
  10. #include "common/common_types.h"
  11. #include "network/room.h"
  12. namespace Network {
  13. /// Information about the received WiFi packets.
  14. /// Acts as our own 802.11 header.
  15. struct WifiPacket {
  16. enum class PacketType : u8 {
  17. Beacon,
  18. Data,
  19. Authentication,
  20. AssociationResponse,
  21. Deauthentication,
  22. NodeMap
  23. };
  24. PacketType type; ///< The type of 802.11 frame.
  25. std::vector<u8> data; ///< Raw 802.11 frame data, starting at the management frame header
  26. /// for management frames.
  27. MacAddress transmitter_address; ///< Mac address of the transmitter.
  28. MacAddress destination_address; ///< Mac address of the receiver.
  29. u8 channel; ///< WiFi channel where this frame was transmitted.
  30. private:
  31. template <class Archive>
  32. void serialize(Archive& ar, const unsigned int) {
  33. ar& type;
  34. ar& data;
  35. ar& transmitter_address;
  36. ar& destination_address;
  37. ar& channel;
  38. }
  39. friend class boost::serialization::access;
  40. };
  41. /// Represents a chat message.
  42. struct ChatEntry {
  43. std::string nickname; ///< Nickname of the client who sent this message.
  44. /// Web services username of the client who sent this message, can be empty.
  45. std::string username;
  46. std::string message; ///< Body of the message.
  47. };
  48. /// Represents a system status message.
  49. struct StatusMessageEntry {
  50. StatusMessageTypes type; ///< Type of the message
  51. /// Subject of the message. i.e. the user who is joining/leaving/being banned, etc.
  52. std::string nickname;
  53. std::string username;
  54. };
  55. /**
  56. * This is what a client [person joining a server] would use.
  57. * It also has to be used if you host a game yourself (You'd create both, a Room and a
  58. * RoomMembership for yourself)
  59. */
  60. class RoomMember final {
  61. public:
  62. enum class State : u8 {
  63. Uninitialized, ///< Not initialized
  64. Idle, ///< Default state (i.e. not connected)
  65. Joining, ///< The client is attempting to join a room.
  66. Joined, ///< The client is connected to the room and is ready to send/receive packets.
  67. Moderator, ///< The client is connnected to the room and is granted mod permissions.
  68. };
  69. enum class Error : u8 {
  70. // Reasons why connection was closed
  71. LostConnection, ///< Connection closed
  72. HostKicked, ///< Kicked by the host
  73. // Reasons why connection was rejected
  74. UnknownError, ///< Some error [permissions to network device missing or something]
  75. NameCollision, ///< Somebody is already using this name
  76. MacCollision, ///< Somebody is already using that mac-address
  77. ConsoleIdCollision, ///< Somebody in the room has the same Console ID
  78. WrongVersion, ///< The room version is not the same as for this RoomMember
  79. WrongPassword, ///< The password doesn't match the one from the Room
  80. CouldNotConnect, ///< The room is not responding to a connection attempt
  81. RoomIsFull, ///< Room is already at the maximum number of players
  82. HostBanned, ///< The user is banned by the host
  83. // Reasons why moderation request failed
  84. PermissionDenied, ///< The user does not have mod permissions
  85. NoSuchUser, ///< The nickname the user attempts to kick/ban does not exist
  86. };
  87. struct MemberInformation {
  88. std::string nickname; ///< Nickname of the member.
  89. std::string username; ///< The web services username of the member. Can be empty.
  90. std::string display_name; ///< The web services display name of the member. Can be empty.
  91. std::string avatar_url; ///< Url to the member's avatar. Can be empty.
  92. GameInfo game_info; ///< Name of the game they're currently playing, or empty if they're
  93. /// not playing anything.
  94. MacAddress mac_address; ///< MAC address associated with this member.
  95. };
  96. using MemberList = std::vector<MemberInformation>;
  97. // The handle for the callback functions
  98. template <typename T>
  99. using CallbackHandle = std::shared_ptr<std::function<void(const T&)>>;
  100. /**
  101. * Unbinds a callback function from the events.
  102. * @param handle The connection handle to disconnect
  103. */
  104. template <typename T>
  105. void Unbind(CallbackHandle<T> handle);
  106. RoomMember();
  107. ~RoomMember();
  108. /**
  109. * Returns the status of our connection to the room.
  110. */
  111. State GetState() const;
  112. /**
  113. * Returns information about the members in the room we're currently connected to.
  114. */
  115. const MemberList& GetMemberInformation() const;
  116. /**
  117. * Returns the nickname of the RoomMember.
  118. */
  119. const std::string& GetNickname() const;
  120. /**
  121. * Returns the username of the RoomMember.
  122. */
  123. const std::string& GetUsername() const;
  124. /**
  125. * Returns the MAC address of the RoomMember.
  126. */
  127. const MacAddress& GetMacAddress() const;
  128. /**
  129. * Returns information about the room we're currently connected to.
  130. */
  131. RoomInformation GetRoomInformation() const;
  132. /**
  133. * Returns whether we're connected to a server or not.
  134. */
  135. bool IsConnected() const;
  136. /**
  137. * Attempts to join a room at the specified address and port, using the specified nickname.
  138. * A console ID hash is passed in to check console ID conflicts.
  139. * This may fail if the username or console ID is already taken.
  140. */
  141. void Join(const std::string& nickname, const std::string& console_id_hash,
  142. const char* server_addr = "127.0.0.1", u16 server_port = DefaultRoomPort,
  143. u16 client_port = 0, const MacAddress& preferred_mac = NoPreferredMac,
  144. const std::string& password = "", const std::string& token = "");
  145. /**
  146. * Sends a WiFi packet to the room.
  147. * @param packet The WiFi packet to send.
  148. */
  149. void SendWifiPacket(const WifiPacket& packet);
  150. /**
  151. * Sends a chat message to the room.
  152. * @param message The contents of the message.
  153. */
  154. void SendChatMessage(const std::string& message);
  155. /**
  156. * Sends the current game info to the room.
  157. * @param game_info The game information.
  158. */
  159. void SendGameInfo(const GameInfo& game_info);
  160. /**
  161. * Sends a moderation request to the room.
  162. * @param type Moderation request type.
  163. * @param nickname The subject of the request. (i.e. the user you want to kick/ban)
  164. */
  165. void SendModerationRequest(RoomMessageTypes type, const std::string& nickname);
  166. /**
  167. * Attempts to retrieve ban list from the room.
  168. * If success, the ban list callback would be called. Otherwise an error would be emitted.
  169. */
  170. void RequestBanList();
  171. /**
  172. * Binds a function to an event that will be triggered every time the State of the member
  173. * changed. The function wil be called every time the event is triggered. The callback function
  174. * must not bind or unbind a function. Doing so will cause a deadlock
  175. * @param callback The function to call
  176. * @return A handle used for removing the function from the registered list
  177. */
  178. CallbackHandle<State> BindOnStateChanged(std::function<void(const State&)> callback);
  179. /**
  180. * Binds a function to an event that will be triggered every time an error happened. The
  181. * function wil be called every time the event is triggered. The callback function must not bind
  182. * or unbind a function. Doing so will cause a deadlock
  183. * @param callback The function to call
  184. * @return A handle used for removing the function from the registered list
  185. */
  186. CallbackHandle<Error> BindOnError(std::function<void(const Error&)> callback);
  187. /**
  188. * Binds a function to an event that will be triggered every time a WifiPacket is received.
  189. * The function wil be called everytime the event is triggered.
  190. * The callback function must not bind or unbind a function. Doing so will cause a deadlock
  191. * @param callback The function to call
  192. * @return A handle used for removing the function from the registered list
  193. */
  194. CallbackHandle<WifiPacket> BindOnWifiPacketReceived(
  195. std::function<void(const WifiPacket&)> callback);
  196. /**
  197. * Binds a function to an event that will be triggered every time the RoomInformation changes.
  198. * The function wil be called every time the event is triggered.
  199. * The callback function must not bind or unbind a function. Doing so will cause a deadlock
  200. * @param callback The function to call
  201. * @return A handle used for removing the function from the registered list
  202. */
  203. CallbackHandle<RoomInformation> BindOnRoomInformationChanged(
  204. std::function<void(const RoomInformation&)> callback);
  205. /**
  206. * Binds a function to an event that will be triggered every time a ChatMessage is received.
  207. * The function wil be called every time the event is triggered.
  208. * The callback function must not bind or unbind a function. Doing so will cause a deadlock
  209. * @param callback The function to call
  210. * @return A handle used for removing the function from the registered list
  211. */
  212. CallbackHandle<ChatEntry> BindOnChatMessageRecieved(
  213. std::function<void(const ChatEntry&)> callback);
  214. /**
  215. * Binds a function to an event that will be triggered every time a StatusMessage is
  216. * received. The function will be called every time the event is triggered. The callback
  217. * function must not bind or unbind a function. Doing so will cause a deadlock
  218. * @param callback The function to call
  219. * @return A handle used for removing the function from the registered list
  220. */
  221. CallbackHandle<StatusMessageEntry> BindOnStatusMessageReceived(
  222. std::function<void(const StatusMessageEntry&)> callback);
  223. /**
  224. * Binds a function to an event that will be triggered every time a requested ban list
  225. * received. The function will be called every time the event is triggered. The callback
  226. * function must not bind or unbind a function. Doing so will cause a deadlock
  227. * @param callback The function to call
  228. * @return A handle used for removing the function from the registered list
  229. */
  230. CallbackHandle<Room::BanList> BindOnBanListReceived(
  231. std::function<void(const Room::BanList&)> callback);
  232. /**
  233. * Leaves the current room.
  234. */
  235. void Leave();
  236. private:
  237. class RoomMemberImpl;
  238. std::unique_ptr<RoomMemberImpl> room_member_impl;
  239. };
  240. inline const char* GetStateStr(const RoomMember::State& s) {
  241. switch (s) {
  242. case RoomMember::State::Uninitialized:
  243. return "Uninitialized";
  244. case RoomMember::State::Idle:
  245. return "Idle";
  246. case RoomMember::State::Joining:
  247. return "Joining";
  248. case RoomMember::State::Joined:
  249. return "Joined";
  250. case RoomMember::State::Moderator:
  251. return "Moderator";
  252. }
  253. return "Unknown";
  254. }
  255. inline const char* GetErrorStr(const RoomMember::Error& e) {
  256. switch (e) {
  257. case RoomMember::Error::LostConnection:
  258. return "LostConnection";
  259. case RoomMember::Error::HostKicked:
  260. return "HostKicked";
  261. case RoomMember::Error::UnknownError:
  262. return "UnknownError";
  263. case RoomMember::Error::NameCollision:
  264. return "NameCollision";
  265. case RoomMember::Error::MacCollision:
  266. return "MaxCollision";
  267. case RoomMember::Error::ConsoleIdCollision:
  268. return "ConsoleIdCollision";
  269. case RoomMember::Error::WrongVersion:
  270. return "WrongVersion";
  271. case RoomMember::Error::WrongPassword:
  272. return "WrongPassword";
  273. case RoomMember::Error::CouldNotConnect:
  274. return "CouldNotConnect";
  275. case RoomMember::Error::RoomIsFull:
  276. return "RoomIsFull";
  277. case RoomMember::Error::HostBanned:
  278. return "HostBanned";
  279. case RoomMember::Error::PermissionDenied:
  280. return "PermissionDenied";
  281. case RoomMember::Error::NoSuchUser:
  282. return "NoSuchUser";
  283. default:
  284. return "Unknown";
  285. }
  286. }
  287. } // namespace Network