Lobby2Server.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #ifndef __LOBBY_2_SERVER_H
  11. #define __LOBBY_2_SERVER_H
  12. #include "Export.h"
  13. #include "RakNetTypes.h"
  14. #include "Lobby2Plugin.h"
  15. #include "DS_OrderedList.h"
  16. #include "ThreadPool.h"
  17. #include "Lobby2Presence.h"
  18. //class PostgreSQLInterface;
  19. namespace RakNet
  20. {
  21. struct Lobby2Message;
  22. class RoomsPlugin;
  23. /// Commands are either messages from remote systems, or can be run by the local system
  24. /// \internal
  25. struct Lobby2ServerCommand
  26. {
  27. Lobby2Message *lobby2Message;
  28. bool deallocMsgWhenDone;
  29. bool returnToSender;
  30. unsigned int callerUserId;
  31. RakNet::RakString callingUserName;
  32. DataStructures::List<SystemAddress> callerSystemAddresses;
  33. DataStructures::List<RakNetGUID> callerGuids;
  34. //SystemAddress requiredConnectionAddress;
  35. Lobby2Server *server;
  36. };
  37. /// \brief The base class for the lobby server, without database specific functionality
  38. /// \details This is a plugin which will take incoming messages via Lobby2Client_PC::SendMsg(), process them, and send back the same messages with output and a result code
  39. /// Unlike the first implementation of the lobby server, this is a thin plugin that mostly just sends messages to threads and sends back the results.
  40. /// \ingroup LOBBY_2_SERVER
  41. class RAK_DLL_EXPORT Lobby2Server : public RakNet::Lobby2Plugin, public ThreadDataInterface
  42. {
  43. public:
  44. Lobby2Server();
  45. virtual ~Lobby2Server();
  46. /// \brief Connect to the database \a numWorkerThreads times using the connection string
  47. /// \param[in] conninfo See the postgre docs
  48. /// \return True on success, false on failure.
  49. virtual bool ConnectToDB(const char *conninfo, int numWorkerThreads)=0;
  50. /// \internal
  51. virtual void AddInputFromThread(Lobby2Message *msg, unsigned int targetUserId, RakNet::RakString targetUserHandle)=0;
  52. /// \internal
  53. virtual void AddOutputFromThread(Lobby2Message *msg, unsigned int targetUserId, RakNet::RakString targetUserHandle)=0;
  54. /// \brief Lobby2Message encapsulates a user command, containing both input and output data
  55. /// \details This will serialize and transmit that command
  56. void SendMsg(Lobby2Message *msg, const DataStructures::List<SystemAddress> &recipients);
  57. /// \brief Add a command, which contains a message and other data such as who send the message.
  58. /// \details The command will be processed according to its implemented virtual functions. Most likely it will be processed in a thread to run database commands
  59. void ExecuteCommand(Lobby2ServerCommand *command);
  60. /// \brief If Lobby2Message::RequiresAdmin() returns true, the message can only be processed from a remote system if the sender's system address is first added()
  61. /// \details This is useful if you want to administrate the server remotely
  62. void AddAdminAddress(SystemAddress addr);
  63. /// \brief If AddAdminAddress() was previously called with \a addr then this returns true.
  64. bool HasAdminAddress(const DataStructures::List<SystemAddress> &addresses);
  65. /// \brief Removes a system address previously added with AddAdminAddress()
  66. void RemoveAdminAddress(SystemAddress addr);
  67. /// \brief Removes all system addresses previously added with AddAdminAddress()
  68. void ClearAdminAddresses(void);
  69. /// \brief If Lobby2Message::RequiresRankingPermission() returns true, then the system that sent the command must be registered with AddRankingAddress()
  70. /// \param[in] addr Address to allow
  71. void AddRankingAddress(SystemAddress addr);
  72. /// Returns if an address was previously added with AddRankingAddress()
  73. /// \param[in] addr Address to check
  74. bool HasRankingAddress(const DataStructures::List<SystemAddress> &addresses);
  75. /// Removes an addressed added with AddRankingAddress()
  76. /// \param[in] addr Address to check
  77. void RemoveRankingAddress(SystemAddress addr);
  78. /// \brief Clears all addresses added with AddRankingAddress()
  79. void ClearRankingAddresses(void);
  80. /// \brief To use RoomsPlugin and Lobby2Server together, register RoomsPlugin with this funcrtion
  81. /// \details The rooms plugin does not automatically handle users logging in and logging off, or renaming users.
  82. /// You can have Lobby2Server manage this for you by calling SetRoomsPlugin() with a pointer to the rooms plugin, if it is on the local system.
  83. /// This will call RoomsPlugin::LoginRoomsParticipant() and RoomsPlugin::LogoffRoomsParticipant() as the messages L2MID_Client_Login and L2MID_Client_Logoff arrive
  84. /// This will use the pointer to RoomsPlugin directly. Setting this will disable SetRoomsPluginAddress()
  85. /// \note This is an empty function. You must #define __INTEGRATE_LOBBY2_WITH_ROOMS_PLUGIN and link with RoomsPlugin.h to use it()
  86. void SetRoomsPlugin(RoomsPlugin *rp);
  87. /// \brief This is similar to SetRoomsPlugin(), except the plugin is on another system.
  88. /// \details This will set the system address of that system to send the login and logoff commands to.
  89. /// For this function to work, you must first call RoomsPlugin::AddLoginServerAddress() so that RoomsPlugin will accept the incoming login and logoff messages.
  90. /// \note This is an empty function. You must #define __INTEGRATE_LOBBY2_WITH_ROOMS_PLUGIN and link with RoomsPlugin.h to use it()
  91. void SetRoomsPluginAddress(SystemAddress address);
  92. /// \brief Server configuration properties, to customize how the server runs specific commands
  93. struct ConfigurationProperties
  94. {
  95. ConfigurationProperties() {requiresEmailAddressValidationToLogin=false; requiresTitleToLogin=false; accountRegistrationRequiredAgeYears=0;}
  96. /// \brief If true, Client_Login will fail with Client_Login_EMAIL_ADDRESS_NOT_VALIDATED unless the email address registered with Client_RegisterAccount is verified with the command System_SetEmailAddressValidated
  97. bool requiresEmailAddressValidationToLogin;
  98. /// \brief If true Client_Login::titleName and Client_Login::titleSecretKey must be previously registered with System_CreateTitle or Client_Login will fail with L2RC_Client_Login_BAD_TITLE_OR_TITLE_SECRET_KEY
  99. bool requiresTitleToLogin;
  100. /// \brief If true, Client_RegisterAccount::cdKey must be previously registered with CDKey_Add or Client_RegisterAccount will fail with L2RC_Client_RegisterAccount_REQUIRES_CD_KEY or a related error message
  101. bool accountRegistrationRequiresCDKey;
  102. /// \brief The minimum age needed to register accounts. If Client_RegisterAccount::createAccountParameters::ageInDays is less than this, then the account registration will fail with L2RC_Client_RegisterAccount_REQUIRED_AGE_NOT_MET
  103. /// \details Per-title age requirements can be handled client-side with System_CreateTitle::requiredAge and System_GetTitleRequiredAge
  104. unsigned int accountRegistrationRequiredAgeYears;
  105. };
  106. /// \brief Set the desired configuration properties. This is read during runtime from threads.
  107. void SetConfigurationProperties(ConfigurationProperties c);
  108. /// \brief Get the previously set configuration properties.
  109. const ConfigurationProperties *GetConfigurationProperties(void) const;
  110. /// Set the presence of a logged in user
  111. /// \param[in] presence Presence info of this user
  112. void SetPresence(const RakNet::Lobby2Presence &presence, RakNet::RakString userHandle);
  113. /// Get the presence of a logged in user, by handle
  114. /// \param[out] presence Presence info of requested user
  115. /// \param[in] userHandle Handle of the user
  116. void GetPresence(RakNet::Lobby2Presence &presence, RakNet::RakString userHandle);
  117. /// \internal Lets the plugin know that a user has logged on, so this user can be tracked and the message forwarded to RoomsPlugin
  118. void OnLogin(Lobby2ServerCommand *command, bool calledFromThread);
  119. /// \internal Lets the plugin know that a user has logged off, so this user can be tracked and the message forwarded to RoomsPlugin
  120. void OnLogoff(Lobby2ServerCommand *command, bool calledFromThread);
  121. /// \internal Lets the plugin know that a user has been renamed, so this user can be tracked and the message forwarded to RoomsPlugin
  122. void OnChangeHandle(Lobby2ServerCommand *command, bool calledFromThread);
  123. /// \internal
  124. struct User
  125. {
  126. DataStructures::List<SystemAddress> systemAddresses;
  127. DataStructures::List<RakNetGUID> guids;
  128. unsigned int callerUserId;
  129. RakNet::RakString userName;
  130. Lobby2Presence presence;
  131. bool allowMultipleLogins;
  132. };
  133. /// \internal
  134. static int UserCompByUsername( const RakString &key, Lobby2Server::User * const &data );
  135. /// \internal
  136. struct ThreadAction
  137. {
  138. Lobby2MessageID action;
  139. Lobby2ServerCommand command;
  140. };
  141. const DataStructures::OrderedList<RakString, User*, Lobby2Server::UserCompByUsername>& GetUsers(void) const {return users;}
  142. void GetUserOnlineStatus(UsernameAndOnlineStatus &userInfo) const;
  143. protected:
  144. void Update(void);
  145. PluginReceiveResult OnReceive(Packet *packet);
  146. void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
  147. void OnShutdown(void);
  148. void OnMessage(Packet *packet);
  149. void Clear(void);
  150. void ClearUsers(void);
  151. unsigned int GetUserIndexBySystemAddress(SystemAddress systemAddress) const;
  152. unsigned int GetUserIndexByGUID(RakNetGUID guid) const;
  153. unsigned int GetUserIndexByUsername(RakNet::RakString userName) const;
  154. void StopThreads(void);
  155. void SendRemoteLoginNotification(RakNet::RakString handle, const DataStructures::List<SystemAddress>& recipients);
  156. /// \internal
  157. void RemoveUser(RakString userName);
  158. /// \internal
  159. void RemoveUser(unsigned int index);
  160. void LogoffFromRooms(User *user);
  161. virtual void* PerThreadFactory(void *context)=0;
  162. virtual void PerThreadDestructor(void* factoryResult, void *context)=0;
  163. virtual void AddInputCommand(Lobby2ServerCommand command)=0;
  164. virtual void ClearConnections(void) {};
  165. DataStructures::OrderedList<SystemAddress, SystemAddress> adminAddresses;
  166. DataStructures::OrderedList<SystemAddress, SystemAddress> rankingAddresses;
  167. DataStructures::OrderedList<RakString, User*, Lobby2Server::UserCompByUsername> users;
  168. RoomsPlugin *roomsPlugin;
  169. SystemAddress roomsPluginAddress;
  170. ThreadPool<Lobby2ServerCommand,Lobby2ServerCommand> threadPool;
  171. SimpleMutex connectionPoolMutex;
  172. ConfigurationProperties configurationProperties;
  173. DataStructures::Queue<ThreadAction> threadActionQueue;
  174. SimpleMutex threadActionQueueMutex;
  175. //DataStructures::List<PostgreSQLInterface *> connectionPool;
  176. void SendUnifiedToMultiple( const RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const DataStructures::List<SystemAddress> systemAddresses );
  177. };
  178. }
  179. #endif
粤ICP备19079148号