1 // ==============================================================
2 //	This file is part of Glest (www.glest.org)
3 //
4 //	Copyright (C) 2001-2008 Martiño Figueroa
5 //
6 //	You can redistribute this code and/or modify it under
7 //	the terms of the GNU General Public License as published
8 //	by the Free Software Foundation; either version 2 of the
9 //	License, or (at your option) any later version
10 // ==============================================================
11 
12 #ifndef _GLEST_GAME_SERVERINTERFACE_H_
13 #define _GLEST_GAME_SERVERINTERFACE_H_
14 
15 #ifdef WIN32
16     #include <winsock2.h>
17     #include <winsock.h>
18 #endif
19 
20 #include <vector>
21 #include "game_constants.h"
22 #include "network_interface.h"
23 #include "connection_slot.h"
24 #include "socket.h"
25 #include "leak_dumper.h"
26 
27 using std::vector;
28 using Shared::Platform::ServerSocket;
29 
30 namespace Shared {  namespace PlatformCommon {  class FTPServerThread;  }}
31 
32 namespace Glest{ namespace Game{
33 
34 class Stats;
35 // =====================================================
36 //	class ServerInterface
37 // =====================================================
38 
39 class ServerInterface: public GameNetworkInterface,
40                        public ConnectionSlotCallbackInterface,
41                        // This is for publishing game status to the masterserver
42                        public SimpleTaskCallbackInterface,
43                        public FTPClientValidationInterface {
44 
45 class TextMessageQueue {
46 public:
47     string text;
48     int teamIndex;
49     bool echoLocal;
50     string targetLanguage;
51 };
52 
53 private:
54 	ConnectionSlot* slots[GameConstants::maxPlayers];
55 	Mutex *slotAccessorMutexes[GameConstants::maxPlayers];
56 
57 	ServerSocket serverSocket;
58 
59 	Mutex *switchSetupRequestsSynchAccessor;
60 	SwitchSetupRequest* switchSetupRequests[GameConstants::maxPlayers];
61 
62 	Mutex *serverSynchAccessor;
63 	int currentFrameCount;
64 
65 	time_t gameStartTime;
66 
67 	time_t lastGlobalLagCheckTime;
68 
69 	SimpleTaskThread *publishToMasterserverThread;
70 	Mutex *masterServerThreadAccessor;
71 	time_t lastMasterserverHeartbeatTime;
72 	bool needToRepublishToMasterserver;
73 
74     ::Shared::PlatformCommon::FTPServerThread *ftpServer;
75     bool exitServer;
76     int64 nextEventId;
77 
78     Mutex *textMessageQueueThreadAccessor;
79     vector<TextMessageQueue> textMessageQueue;
80 
81     Mutex *broadcastMessageQueueThreadAccessor;
82     vector<pair<NetworkMessage *,int> > broadcastMessageQueue;
83 
84     Mutex *inBroadcastMessageThreadAccessor;
85     bool inBroadcastMessage;
86 
87     bool masterserverAdminRequestLaunch;
88 
89 	vector<string> mapFiles;
90 	vector<string> playerSortedMaps[GameConstants::maxPlayers+1];
91 	vector<string> techTreeFiles;
92 	vector<string> tilesetFiles;
93 
94 	map<string,pair<uint64,time_t> > badClientConnectIPList;
95 
96 	ServerSocket *serverSocketAdmin;
97 	MasterSlaveThreadController masterController;
98 
99 	bool gameHasBeenInitiated;
100 	int gameSettingsUpdateCount;
101 
102 	bool allowInGameConnections;
103 	bool gameLaunched;
104 	time_t lastListenerSlotCheckTime;
105 
106 	time_t resumeGameStartTime;
107 
108 	Mutex *gameStatsThreadAccessor;
109 	Stats *gameStats;
110 
111 	bool clientsAutoPausedDueToLag;
112 	Chrono clientsAutoPausedDueToLagTimer;
113 	Chrono lastBroadcastCommandsTimer;
114 	ClientLagCallbackInterface *clientLagCallbackInterface;
115 
116 public:
117 	ServerInterface(bool publishEnabled, ClientLagCallbackInterface *clientLagCallbackInterface);
118 	virtual ~ServerInterface();
119 
120 	bool getClientsAutoPausedDueToLag();
121 	void setClientLagCallbackInterface(ClientLagCallbackInterface *intf);
122 	void setGameStats(Stats *gameStats);
123 
124 	virtual Socket* getSocket(bool mutexLock=true)				{return &serverSocket;}
125 	virtual std::string getIpAddress(bool mutexLock=true);
126 
getGameStartTime()127 	time_t getGameStartTime() const { return gameStartTime; }
128 
getAllowInGameConnections()129 	virtual bool getAllowInGameConnections() const { return allowInGameConnections; }
setAllowInGameConnections(bool value)130 	void setAllowInGameConnections(bool value) { allowInGameConnections = value; }
131 
132 	bool getStartInGameConnectionLaunch();
133 	bool getPauseForInGameConnection();
134 	bool getUnPauseForInGameConnection();
135 
136 	void shutdownFTPServer();
137 
138     virtual void close();
139     virtual void update();
updateLobby()140     virtual void updateLobby()  { };
141     virtual void updateKeyframe(int frameCount);
setKeyframe(int frameCount)142     virtual void setKeyframe(int frameCount) { currentFrameCount = frameCount; }
143 
144     virtual void waitUntilReady(Checksum *checksum);
145     virtual void sendTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage);
146     void sendTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage, int lockedSlotIndex);
147 
148     void queueTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage);
149 
150     virtual void sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note,int playerIndex);
151     void sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note, int playerIndex, int lockedSlotIndex);
152 
153 	virtual void sendHighlightCellMessage(Vec2i targetPos, int factionIndex);
154     void sendHighlightCellMessage(Vec2i targetPos, int factionIndex, int lockedSlotIndex);
155 
156     virtual void sendUnMarkCellMessage(Vec2i targetPos, int factionIndex);
157     void sendUnMarkCellMessage(Vec2i targetPos, int factionIndex, int lockedSlotIndex);
158 
159     virtual void quitGame(bool userManuallyQuit);
160     virtual string getNetworkStatus();
getServerSocket()161     ServerSocket *getServerSocket() {
162         return &serverSocket;
163     }
164 
165     SwitchSetupRequest **getSwitchSetupRequests();
166     SwitchSetupRequest *getSwitchSetupRequests(int index);
167     void setSwitchSetupRequests(int index,SwitchSetupRequest *ptr);
getSwitchSetupRequestsMutex()168     Mutex * getSwitchSetupRequestsMutex() { return switchSetupRequestsSynchAccessor; }
169 
170     void addSlot(int playerIndex);
171     bool switchSlot(int fromPlayerIndex, int toPlayerIndex);
172     void removeSlot(int playerIndex, int lockedSlotIndex = -1);
173     virtual ConnectionSlot *getSlot(int playerIndex, bool lockMutex);
174     virtual Mutex *getSlotMutex(int playerIndex);
175     int getSlotCount();
176     int getConnectedSlotCount(bool authenticated);
177 
178     int getOpenSlotCount();
179     bool launchGame(const GameSettings *gameSettings);
180 	void validateGameSettings(GameSettings *serverGameSettings);
181     void setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck);
182     void broadcastGameSetup(GameSettings *gameSettingsBuffer, bool setGameSettingsBuffer=false);
183 
184     int getGameSettingsUpdateCount();
185 
getMasterserverAdminRequestLaunch()186     bool getMasterserverAdminRequestLaunch() const { return masterserverAdminRequestLaunch; }
setMasterserverAdminRequestLaunch(bool value)187     void setMasterserverAdminRequestLaunch(bool value) { masterserverAdminRequestLaunch = value; }
188 
189     void updateListen();
getConnectHasHandshaked()190     virtual bool getConnectHasHandshaked() const {
191         return false;
192     }
193 
slotUpdateTask(ConnectionSlotEvent * event)194     virtual void slotUpdateTask(ConnectionSlotEvent *event) { };
195     bool hasClientConnection();
196     virtual bool isClientConnected(int index);
197 
getCurrentFrameCount()198     int getCurrentFrameCount() const {
199         return currentFrameCount;
200     }
201 
202     std::pair<bool,bool> clientLagCheck(ConnectionSlot *connectionSlot, bool skipNetworkBroadCast = false);
203     bool signalClientReceiveCommands(ConnectionSlot *connectionSlot, int slotIndex, bool socketTriggered, ConnectionSlotEvent & event);
204     void updateSocketTriggeredList(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList);
isPortBound()205     bool isPortBound() const {
206         return serverSocket.isPortBound();
207     }
208 
getBindPort()209     int getBindPort() const {
210         return serverSocket.getBindPort();
211     }
212 
213     void broadcastPing(NetworkMessagePing *networkMessage, int excludeSlot = -1) {
214         this->broadcastMessage(networkMessage, excludeSlot);
215     }
216 
217     void queueBroadcastMessage(NetworkMessage *networkMessage, int excludeSlot = -1);
218     virtual string getHumanPlayerName(int index = -1);
219     virtual int getHumanPlayerIndex() const;
getNeedToRepublishToMasterserver()220     bool getNeedToRepublishToMasterserver() const {
221         return needToRepublishToMasterserver;
222     }
223 
setNeedToRepublishToMasterserver(bool value)224     void setNeedToRepublishToMasterserver(bool value) {
225         needToRepublishToMasterserver = value;
226     }
227 
228     void setPublishEnabled(bool value);
229 
getGameHasBeenInitiated()230     bool getGameHasBeenInitiated() const {
231     	return gameHasBeenInitiated;
232     }
233 
234 public:
getServerSynchAccessor()235     Mutex *getServerSynchAccessor() {
236         return serverSynchAccessor;
237     }
238 
239     virtual void simpleTask(BaseThread *callingThread,void *userdata);
240     void addClientToServerIPAddress(uint32 clientIp, uint32 ServerIp);
241     virtual int isValidClientType(uint32 clientIp);
242     virtual int isClientAllowedToGetFile(uint32 clientIp, const char *username, const char *filename);
243 
244     void notifyBadClientConnectAttempt(string ipAddress);
245     std::string DumpStatsToLog(bool dumpToStringOnly) const;
246 
247     virtual void saveGame(XmlNode *rootNode);
248 
249     void broadcastMessage(NetworkMessage *networkMessage, int excludeSlot = -1, int lockedSlotIndex = -1);
250 
251     ConnectionSlot * findSlotForUUID(string uuid, bool unConnectedOnly=true);
252 
253 private:
254 
255     void broadcastMessageToConnectedClients(NetworkMessage *networkMessage, int excludeSlot = -1);
256     bool shouldDiscardNetworkMessage(NetworkMessageType networkMessageType, ConnectionSlot *connectionSlot);
257     void updateSlot(ConnectionSlotEvent *event);
258     void validateConnectedClients();
259 
260     std::map<string,string> publishToMasterserver();
261     std::map<string,string> publishToMasterserverStats();
262 
263     int64 getNextEventId();
264     void processTextMessageQueue();
265     void processBroadCastMessageQueue();
266     void checkListenerSlots();
267 	void checkForCompletedClientsUsingThreadManager(
268 			std::map<int, bool>& mapSlotSignalledList,
269 			std::vector<string>& errorMsgList);
270 	void checkForCompletedClientsUsingLoop(
271 			std::map<int, bool>& mapSlotSignalledList,
272 			std::vector<string>& errorMsgList,
273 			std::map<int, ConnectionSlotEvent>& eventList);
274 	void checkForAutoPauseForLaggingClient(int index,
275 			ConnectionSlot* connectionSlot);
276 	void checkForAutoResumeForLaggingClients();
277 
278 protected:
279     void signalClientsToRecieveData(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList, std::map<int,ConnectionSlotEvent> & eventList, std::map<int,bool> & mapSlotSignalledList);
280     void checkForCompletedClients(std::map<int,bool> & mapSlotSignalledList,std::vector <string> &errorMsgList,std::map<int,ConnectionSlotEvent> &eventList);
281     void checkForLaggingClients(std::map<int,bool> &mapSlotSignalledList, std::map<int,ConnectionSlotEvent> &eventList, std::map<PLATFORM_SOCKET,bool> &socketTriggeredList,std::vector <string> &errorMsgList);
282     void executeNetworkCommandsFromClients();
283     void dispatchPendingChatMessages(std::vector <string> &errorMsgList);
284     void dispatchPendingMarkCellMessages(std::vector <string> &errorMsgList);
285     void dispatchPendingUnMarkCellMessages(std::vector <string> &errorMsgList);
286     void dispatchPendingHighlightCellMessages(std::vector <string> &errorMsgList);
287 
288     void shutdownMasterserverPublishThread();
289 
290 
291 };
292 
293 }}//end namespace
294 
295 #endif
296