// CentralServer.h // copyright 2000 Verant Interactive // Author: Justin Randall #ifndef _CentralServer_H #define _CentralServer_H //----------------------------------------------------------------------- #pragma warning(disable : 4100) #include #include #include #include #include #include "Singleton/Singleton.h" #include "serverKeyShare/KeyServer.h" #include "sharedFoundation/StationId.h" #include "sharedFoundation/NetworkId.h" #include "sharedMessageDispatch/Receiver.h" class CentralServerMetricsData; class ChatServerConnection; class Connection; class ConnectionServerConnection; class ConnectionCreateCharacter; class CustomerServiceConnection; class ExcommunicateGameServerMessage; class GameNetworkMessage; class GameServerConnection; class GameServerConnectionHandler; class GameServerForLoginMessage; class LoginServerConnection; class PlanetServerConnection; class RequestGameServerForLoginMessage; class RequestSceneTransfer; class Service; class TaskConnection; class TransferServerConnection; class StationPlayersCollectorConnection; class AuctionTransferClient; class ExchangeListCreditsMessage; //----------------------------------------------------------------------- class CentralServer : public Singleton, public MessageDispatch::Receiver { public: typedef std::string SceneId; typedef std::vector ProcessList; typedef unsigned int SpawnDelaySeconds; struct CentralObject { CentralObject(); CentralObject(const SceneId & sceneId, uint32 authProcess); SceneId m_sceneId; uint32 m_authoritativeProcess; ProcessList m_proxyProcessList; }; ~CentralServer(); private: typedef std::vector ConnectionServerConnectionList; typedef std::map CentralObjectMap; typedef std::unordered_multimap SceneGameMap; typedef std::pair ServersList; typedef std::unordered_map ConnectionServerSUIDMap; typedef std::map > PlayerSceneMapType; public: void addConnectionServerConnection(ConnectionServerConnection* conn); void addGameServer(GameServerConnection * newGameServer); void broadcastToChatServers(const GameNetworkMessage & message) const; void broadcastToCustomerServiceServers(const GameNetworkMessage & message) const; void broadcastToGameServers(const GameNetworkMessage & message) const; bool getIsClusterPublic() const; bool getIsClusterLocked() const; bool getIsClusterSecret() const; bool isPreloadFinished() const; bool isInClusterInitialStartup() const; uint8 getClusterId() const; int getClusterStartupTime() const; int getSecondsClusterHasBeenInLoadingState() const; int getPlanetsWaitingForPreloadCount() const; int getPlanetServersCount() const; bool isDatabaseBacklogged() const; bool hasDBConnection() const; const Service * getGameService() const; const Service * getChatService() const; const Service * getCustomerService() const; static const Service * getCommoditiesService(); const Service * getPlanetService() const; const std::string& getHostForScene(const std::string& scene) const; int getNumChatServers() const; int getNumConnectionServers() const; int getNumDatabaseServers() const; int getNumGameServers() const; int getNumPlanetServers() const; int getPlayerCount() const; int getFreeTrialCount() const; int getEmptySceneCount() const; int getTutorialSceneCount() const; int getFalconSceneCount() const; bool hasPlanetServer(const std::string & sceneName) const; void launchStartingProcesses() const; void launchStartingConnectionServers() const; void launchStartingPlanetServers(); void launchCommoditiesServer(); void receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); void removeConnectionServerConnection(const ConnectionServerConnection* conn); void removeGameServer(const GameServerConnection *gameServer); void removePlanetServer(const PlanetServerConnection *planetServer); void pushAllKeys(ConnectionServerConnection * targetConnServer) const; void sendTaskMessage(const GameNetworkMessage & source); void sendToGameServer(const uint32 gameServerProcessId, const GameNetworkMessage & message, const bool reliable) const; void sendToAllGameServers(const GameNetworkMessage & message, const bool reliable); void sendToAllGameServersExceptDBProcess(const GameNetworkMessage & message, const bool reliable); void sendToAllPlanetServers(const GameNetworkMessage & message, const bool reliable); void sendToPlanetServer(const std::string &sceneId, const GameNetworkMessage & message, const bool reliable); void sendToAllConnectionServers(const GameNetworkMessage & message, const bool reliable, Connection const * exclude = nullptr); void sendToConnectionServerForAccount(StationId account, const GameNetworkMessage & message, const bool reliable); void sendToDBProcess(const GameNetworkMessage & message, const bool reliable) const; void sendToLoginServer(uint32 loginServerId, const GameNetworkMessage &message); void sendToAllLoginServers(const GameNetworkMessage &message); uint32 sendToArbitraryLoginServer(const GameNetworkMessage &message, bool roundRobin = true); uint32 sendToRandomGameServer(const GameNetworkMessage &message); void sendToTransferServer(const GameNetworkMessage & message) const; void sendToStationPlayersCollector(const GameNetworkMessage & msg) const; void setTaskManager(TaskConnection * newTaskmanager); void setDbProcessServerProcessId(const uint32 newDbServerProcessid); void startConnectionServer(int connectionServerNumber, const std::string& listenAddress, const std::string * publicPort, const std::string * internalPort, SpawnDelaySeconds spawnDelay) const; void startConnectionServer(int connectionServerNumber, const std::string& listenAddress, uint16 publicPort, uint16 internalPort, bool, SpawnDelaySeconds spawnDelay) const; void startPlanetServer(const std::string& host, const std::string& sceneId, SpawnDelaySeconds spawnDelay); void startShutdownProcess(const uint32 timeToShutdown, const uint32 maxTime, const Unicode::String &systemMessage); void checkShutdownProcess(); void abortShutdownProcess(); GameServerConnection * getRandomGameServer(void); void getReadyGameServers(std::vector &theList); const uint32 getDbProcessServerProcessId(void) const; const std::string & getCommandLine() const; void setCommandLine(const std::string & cmdLine); static void run(void); static void done(); static void remove(); ConnectionServerConnection * getAnyConnectionServer(); GameServerConnection * getGameServer (const uint32 processId) const; GameServerConnection * getGameServer (const SceneId &scene) const; const ServersList getGameServers (const SceneId &scene) const; std::vector getGameServers() const; time_t getLastTimeSystemTimeMismatchNotification() const; const std::string & getLastTimeSystemTimeMismatchNotificationDescription() const; const std::string & getDisconnectedTaskManagerList() const; const std::map & getPopulationStatistics(time_t & refreshTime); const std::map > > & getGcwScoreStatistics(time_t & refreshTime); std::pair > const *, std::map > const *> getLastLoginTimeStatistics(time_t & refreshTime); void getCharacterMatchStatistics(int & numberOfCharacterMatchRequests, int & numberOfCharacterMatchResultsPerRequest, int & timeSpentPerCharacterMatchRequestMs); void removeFromAccountConnectionMap(StationId suid); private: void handleRequestGameServerForLoginMessage (const RequestGameServerForLoginMessage & msg); void handleRequestSceneTransfer (const RequestSceneTransfer & msg); void handleGameServerForLoginMessage (const GameServerForLoginMessage & msg); void handleExchangeListCreditsMessage (const ExchangeListCreditsMessage& msg); size_t getGameServerCount (void) const; void update(); void sendPopulationUpdateToLoginServer(); void sendMetricsToWebAPI(); ConnectionServerConnection * getConnectionServerForAccount(StationId suid); void addToAccountConnectionMap(StationId suid, ConnectionServerConnection * cconn, uint32 subscriptionBits); void removeFromAccountConnectionMap(int connectionServerConnectionId); void doServerPings(); void excommunicateServer(const ExcommunicateGameServerMessage &); protected: friend class Singleton; CentralServer(); private: void connectToLoginServer() const; CentralServer(const CentralServer & source); CentralServer& operator= (const CentralServer & rhs); ConnectionServerConnectionList m_connectionServerConnections; std::set m_chatServerConnections; std::set m_csServerConnections; SceneGameMap m_gameServers; ConnectionServerSUIDMap m_accountConnectionMap; // Network::Address clientService; /** The dbProcessServerProcessId is set by the DBProcess. The central server refers to this process if there are no matching objects in any of its maps. */ uint32 m_dbProcessServerProcessId; bool m_done; Service * m_gameService; Service * m_chatService; Service * m_connService; Service * m_csService; Service * m_planetService; Service * m_consoleService; TransferServerConnection * m_transferServerConnection; StationPlayersCollectorConnection * m_stationPlayersCollectorConnection; // these two lists must be kept in sync, ***EXCEPT*** that // m_gameServerConnectionsList doesn't contain the DB server std::map m_gameServerConnections; std::vector m_gameServerConnectionsList; PlayerSceneMapType m_playerSceneMap; typedef std::map LoginServerConnectionMapType; LoginServerConnectionMapType m_loginServerConnectionMap; KeyServer * m_loginServerKeys; Service * m_loginService; AuctionTransferClient * m_pAuctionTransferClient; std::vector m_messagesWaitingForPlanetServer; std::map m_pendingLoadingObjects; std::map m_pendingNewObjects; uint32 m_nextFreeProcessId; TaskConnection * m_taskManager; Service * m_taskService; std::string m_commandLine; std::map m_pendingTransfers; int m_totalPlayerCount; int m_totalFreeTrialCount; int m_totalEmptySceneCount; int m_totalTutorialSceneCount; int m_totalFalconSceneCount; CentralServerMetricsData* m_metricsData; std::map, time_t> > m_pendingPlanetServers; std::set m_planetsWaitingForPreload; std::map m_planetServers; uint16 m_nextPlanetWatcherPort; bool m_databaseBacklogged; time_t m_lastLoadingStateTime; time_t m_timeClusterStarted; int m_clusterStartupTime; time_t m_timeClusterWentIntoLoadingState; uint8 m_clusterId; std::set m_serverPings; uint32 m_shutdownTotalTime; uint32 m_shutdownMaxTime; Unicode::String m_shutdownSystemMessage; // This tracks various phases of the shutdown sequence. // 0 = not in the process of shutting down // 1 = first broadcast message immediately after receiving a shutdown command // 2 = beginning process of shutting down. Sending system message broadcasts each minute warning players. // 3 = give players 30sec to get to a safe place before being disconnected. // 4 = done broadcasting messages; set the cluster to private, kick the players and wait for the next DatabaseSaveStart message // 5 = received DatabaseStartSave, now we are waiting for either another DatabaseSaveStart or DatabaseSaveComplete // (it's possible to receive another DatabaseSaveStart without a matching DatabaseSaveComplete in cases where // there happens to be nothing to save for that cycle) // 6 = received a DatabaseSaveComplete (or another DatabaseSaveStart) and am in the process of shutting down. uint32 m_shutdownPhase; bool m_shutdownHaveDatabaseSaveStart; bool m_shutdownHaveDatabaseComplete; uint32 m_curTime; time_t m_lastTimeSystemTimeMismatchNotification; std::string m_lastTimeSystemTimeMismatchNotificationDescription; std::string m_disconnectedTaskManagerList; std::map m_populationStatistics; time_t m_timePopulationStatisticsRefresh; time_t m_timePopulationStatisticsNextRefresh; std::map > > m_gcwScoreStatistics; time_t m_timeGcwScoreStatisticsRefresh; time_t m_timeGcwScoreStatisticsNextRefresh; std::map > m_lastLoginTimeStatistics; std::map > m_createTimeStatistics; time_t m_timeLastLoginTimeStatisticsRefresh; time_t m_timeLastLoginTimeStatisticsNextRefresh; int m_numberOfCharacterMatchRequests; uint64 m_numberOfCharacterMatchResults; uint64 m_timeSpentOnCharacterMatchRequestsMs; time_t m_timeCharacterMatchStatisticsNextRefresh; }; //----------------------------------------------------------------------- inline void CentralServer::addConnectionServerConnection(ConnectionServerConnection* conn) { m_connectionServerConnections.push_back(conn); } //----------------------------------------------------------------------- inline int CentralServer::getNumChatServers() const { return m_chatServerConnections.size(); //lint !e713 } //----------------------------------------------------------------------- inline int CentralServer::getNumConnectionServers() const { return m_connectionServerConnections.size(); //lint !e713 } //----------------------------------------------------------------------- inline int CentralServer::getNumDatabaseServers() const { GameServerConnection * g = getGameServer(getDbProcessServerProcessId()); if(g) { return 1; } return 0; } //----------------------------------------------------------------------- inline int CentralServer::getNumGameServers() const { return m_gameServers.size() - 1; //lint !e713 } //----------------------------------------------------------------------- inline int CentralServer::getNumPlanetServers() const { return m_planetServers.size(); //lint !e713 } //----------------------------------------------------------------------- inline const uint32 CentralServer::getDbProcessServerProcessId(void) const { return m_dbProcessServerProcessId; } //----------------------------------------------------------------------- inline size_t CentralServer::getGameServerCount(void) const { return m_gameServers.size(); } //----------------------------------------------------------------------- inline int CentralServer::getPlayerCount() const { return m_totalPlayerCount; } //----------------------------------------------------------- inline int CentralServer::getFreeTrialCount() const { return m_totalFreeTrialCount; } //----------------------------------------------------------- inline int CentralServer::getEmptySceneCount() const { return m_totalEmptySceneCount; } //----------------------------------------------------------- inline int CentralServer::getTutorialSceneCount() const { return m_totalTutorialSceneCount; } //----------------------------------------------------------- inline int CentralServer::getFalconSceneCount() const { return m_totalFalconSceneCount; } //----------------------------------------------------------------------- inline void CentralServer::setDbProcessServerProcessId(const uint32 newDbServerProcessId) { m_dbProcessServerProcessId = newDbServerProcessId; } //----------------------------------------------------------------------- inline bool CentralServer::isPreloadFinished() const { return (!m_databaseBacklogged && m_planetsWaitingForPreload.empty() && !m_planetServers.empty()); } //----------------------------------------------------------------------- inline bool CentralServer::isInClusterInitialStartup() const { return (m_clusterStartupTime == -1); } // ---------------------------------------------------------------------- inline int CentralServer::getPlanetsWaitingForPreloadCount() const { return static_cast(m_planetsWaitingForPreload.size()); } // ---------------------------------------------------------------------- inline bool CentralServer::isDatabaseBacklogged() const { return m_databaseBacklogged; } // ---------------------------------------------------------------------- inline time_t CentralServer::getLastTimeSystemTimeMismatchNotification() const { return m_lastTimeSystemTimeMismatchNotification; } // ---------------------------------------------------------------------- inline const std::string & CentralServer::getLastTimeSystemTimeMismatchNotificationDescription() const { return m_lastTimeSystemTimeMismatchNotificationDescription; } // ---------------------------------------------------------------------- inline const std::string & CentralServer::getDisconnectedTaskManagerList() const { return m_disconnectedTaskManagerList; } // ---------------------------------------------------------------------- inline uint8 CentralServer::getClusterId() const { return m_clusterId; } // ====================================================================== #endif //_CentralServer_H