// ============================================================== // This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 MartiƱo Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #ifndef _GLEST_GAME_SERVERINTERFACE_H_ #define _GLEST_GAME_SERVERINTERFACE_H_ #ifdef WIN32 #include #include #endif #include #include "game_constants.h" #include "network_interface.h" #include "connection_slot.h" #include "socket.h" #include "leak_dumper.h" using std::vector; using Shared::Platform::ServerSocket; namespace Shared { namespace PlatformCommon { class FTPServerThread; }} namespace Glest{ namespace Game{ class Stats; // ===================================================== // class ServerInterface // ===================================================== class ServerInterface: public GameNetworkInterface, public ConnectionSlotCallbackInterface, // This is for publishing game status to the masterserver public SimpleTaskCallbackInterface, public FTPClientValidationInterface { class TextMessageQueue { public: string text; int teamIndex; bool echoLocal; string targetLanguage; }; private: ConnectionSlot* slots[GameConstants::maxPlayers]; Mutex *slotAccessorMutexes[GameConstants::maxPlayers]; ServerSocket serverSocket; Mutex *switchSetupRequestsSynchAccessor; SwitchSetupRequest* switchSetupRequests[GameConstants::maxPlayers]; Mutex *serverSynchAccessor; int currentFrameCount; time_t gameStartTime; time_t lastGlobalLagCheckTime; SimpleTaskThread *publishToMasterserverThread; Mutex *masterServerThreadAccessor; time_t lastMasterserverHeartbeatTime; bool needToRepublishToMasterserver; ::Shared::PlatformCommon::FTPServerThread *ftpServer; bool exitServer; int64 nextEventId; Mutex *textMessageQueueThreadAccessor; vector textMessageQueue; Mutex *broadcastMessageQueueThreadAccessor; vector > broadcastMessageQueue; Mutex *inBroadcastMessageThreadAccessor; bool inBroadcastMessage; bool masterserverAdminRequestLaunch; vector mapFiles; vector techTreeFiles; vector tilesetFiles; map > badClientConnectIPList; ServerSocket *serverSocketAdmin; MasterSlaveThreadController masterController; bool gameHasBeenInitiated; int gameSettingsUpdateCount; bool allowInGameConnections; bool gameLaunched; time_t lastListenerSlotCheckTime; time_t resumeGameStartTime; Mutex *gameStatsThreadAccessor; Stats *gameStats; bool clientsAutoPausedDueToLag; Chrono clientsAutoPausedDueToLagTimer; Chrono lastBroadcastCommandsTimer; ClientLagCallbackInterface *clientLagCallbackInterface; public: ServerInterface(bool publishEnabled, ClientLagCallbackInterface *clientLagCallbackInterface); virtual ~ServerInterface(); bool getClientsAutoPausedDueToLag(); void setClientLagCallbackInterface(ClientLagCallbackInterface *intf); void setGameStats(Stats *gameStats); virtual Socket* getSocket(bool mutexLock=true) {return &serverSocket;} virtual std::string getIpAddress(bool mutexLock=true); time_t getGameStartTime() const { return gameStartTime; } virtual bool getAllowInGameConnections() const { return allowInGameConnections; } void setAllowInGameConnections(bool value) { allowInGameConnections = value; } bool getStartInGameConnectionLaunch(); bool getPauseForInGameConnection(); bool getUnPauseForInGameConnection(); void shutdownFTPServer(); virtual void close(); virtual void update(); virtual void updateLobby() { }; virtual void updateKeyframe(int frameCount); virtual void setKeyframe(int frameCount) { currentFrameCount = frameCount; } virtual void waitUntilReady(Checksum *checksum); virtual void sendTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage); void sendTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage, int lockedSlotIndex); void queueTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage); virtual void sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note,int playerIndex); void sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note, int playerIndex, int lockedSlotIndex); virtual void sendHighlightCellMessage(Vec2i targetPos, int factionIndex); void sendHighlightCellMessage(Vec2i targetPos, int factionIndex, int lockedSlotIndex); virtual void sendUnMarkCellMessage(Vec2i targetPos, int factionIndex); void sendUnMarkCellMessage(Vec2i targetPos, int factionIndex, int lockedSlotIndex); virtual void quitGame(bool userManuallyQuit); virtual string getNetworkStatus(); ServerSocket *getServerSocket() { return &serverSocket; } SwitchSetupRequest **getSwitchSetupRequests(); SwitchSetupRequest *getSwitchSetupRequests(int index); void setSwitchSetupRequests(int index,SwitchSetupRequest *ptr); Mutex * getSwitchSetupRequestsMutex() { return switchSetupRequestsSynchAccessor; } void addSlot(int playerIndex); bool switchSlot(int fromPlayerIndex, int toPlayerIndex); void removeSlot(int playerIndex, int lockedSlotIndex = -1); virtual ConnectionSlot *getSlot(int playerIndex, bool lockMutex); virtual Mutex *getSlotMutex(int playerIndex); int getSlotCount(); int getConnectedSlotCount(bool authenticated); int getOpenSlotCount(); bool launchGame(const GameSettings *gameSettings); void validateGameSettings(GameSettings *serverGameSettings); void setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck); void broadcastGameSetup(GameSettings *gameSettingsBuffer, bool setGameSettingsBuffer=false); int getGameSettingsUpdateCount(); bool getMasterserverAdminRequestLaunch() const { return masterserverAdminRequestLaunch; } void setMasterserverAdminRequestLaunch(bool value) { masterserverAdminRequestLaunch = value; } void updateListen(); virtual bool getConnectHasHandshaked() const { return false; } virtual void slotUpdateTask(ConnectionSlotEvent *event) { }; bool hasClientConnection(); virtual bool isClientConnected(int index); int getCurrentFrameCount() const { return currentFrameCount; } std::pair clientLagCheck(ConnectionSlot *connectionSlot, bool skipNetworkBroadCast = false); bool signalClientReceiveCommands(ConnectionSlot *connectionSlot, int slotIndex, bool socketTriggered, ConnectionSlotEvent & event); void updateSocketTriggeredList(std::map & socketTriggeredList); bool isPortBound() const { return serverSocket.isPortBound(); } int getBindPort() const { return serverSocket.getBindPort(); } void broadcastPing(NetworkMessagePing *networkMessage, int excludeSlot = -1) { this->broadcastMessage(networkMessage, excludeSlot); } void queueBroadcastMessage(NetworkMessage *networkMessage, int excludeSlot = -1); virtual string getHumanPlayerName(int index = -1); virtual int getHumanPlayerIndex() const; bool getNeedToRepublishToMasterserver() const { return needToRepublishToMasterserver; } void setNeedToRepublishToMasterserver(bool value) { needToRepublishToMasterserver = value; } void setPublishEnabled(bool value); bool getGameHasBeenInitiated() const { return gameHasBeenInitiated; } public: Mutex *getServerSynchAccessor() { return serverSynchAccessor; } virtual void simpleTask(BaseThread *callingThread,void *userdata); void addClientToServerIPAddress(uint32 clientIp, uint32 ServerIp); virtual int isValidClientType(uint32 clientIp); virtual int isClientAllowedToGetFile(uint32 clientIp, const char *username, const char *filename); void notifyBadClientConnectAttempt(string ipAddress); std::string DumpStatsToLog(bool dumpToStringOnly) const; virtual void saveGame(XmlNode *rootNode); void broadcastMessage(NetworkMessage *networkMessage, int excludeSlot = -1, int lockedSlotIndex = -1); ConnectionSlot * findSlotForUUID(string uuid, bool unConnectedOnly=true); private: void broadcastMessageToConnectedClients(NetworkMessage *networkMessage, int excludeSlot = -1); bool shouldDiscardNetworkMessage(NetworkMessageType networkMessageType, ConnectionSlot *connectionSlot); void updateSlot(ConnectionSlotEvent *event); void validateConnectedClients(); std::map publishToMasterserver(); std::map publishToMasterserverStats(); int64 getNextEventId(); void processTextMessageQueue(); void processBroadCastMessageQueue(); void checkListenerSlots(); void checkForCompletedClientsUsingThreadManager( std::map& mapSlotSignalledList, std::vector& errorMsgList); void checkForCompletedClientsUsingLoop( std::map& mapSlotSignalledList, std::vector& errorMsgList, std::map& eventList); void checkForAutoPauseForLaggingClient(int index, ConnectionSlot* connectionSlot); void checkForAutoResumeForLaggingClients(); protected: void signalClientsToRecieveData(std::map & socketTriggeredList, std::map & eventList, std::map & mapSlotSignalledList); void checkForCompletedClients(std::map & mapSlotSignalledList,std::vector &errorMsgList,std::map &eventList); void checkForLaggingClients(std::map &mapSlotSignalledList, std::map &eventList, std::map &socketTriggeredList,std::vector &errorMsgList); void executeNetworkCommandsFromClients(); void dispatchPendingChatMessages(std::vector &errorMsgList); void dispatchPendingMarkCellMessages(std::vector &errorMsgList); void dispatchPendingUnMarkCellMessages(std::vector &errorMsgList); void dispatchPendingHighlightCellMessages(std::vector &errorMsgList); void shutdownMasterserverPublishThread(); }; }}//end namespace #endif