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_CONNECTIONSLOT_H_
13 #define _GLEST_GAME_CONNECTIONSLOT_H_
14 
15 #include "socket.h"
16 #include "network_interface.h"
17 #include "base_thread.h"
18 #include <time.h>
19 #include <vector>
20 
21 #include "leak_dumper.h"
22 
23 using Shared::Platform::ServerSocket;
24 using Shared::Platform::Socket;
25 using std::vector;
26 
27 namespace Glest{ namespace Game{
28 
29 class ServerInterface;
30 class ConnectionSlot;
31 
32 // =====================================================
33 //	class ConnectionSlotThread
34 // =====================================================
35 
36 enum ConnectionSlotEventType
37 {
38 	eNone,
39     eReceiveSocketData,
40     eSendSocketData
41 };
42 
43 class ConnectionSlotEvent {
44 public:
45 
ConnectionSlotEvent()46 	ConnectionSlotEvent() {
47 		eventType = eNone;
48 		triggerId = -1;
49 		connectionSlot = NULL;
50 		networkMessage = NULL;
51 		socketTriggered = false;
52 		eventCompleted = false;
53 		eventId = -1;
54 	}
55 
56 	int64 triggerId;
57 	ConnectionSlot* connectionSlot;
58 	ConnectionSlotEventType eventType;
59 	NetworkMessage *networkMessage;
60 	bool socketTriggered;
61 	bool eventCompleted;
62 	int64 eventId;
63 };
64 
65 //
66 // This interface describes the methods a callback object must implement
67 //
68 class ConnectionSlotCallbackInterface {
69 public:
70 	virtual bool isClientConnected(int index) = 0;
71 	virtual bool getAllowInGameConnections() const = 0;
72 	virtual ConnectionSlot *getSlot(int index, bool lockMutex) = 0;
73 	virtual Mutex *getSlotMutex(int index) = 0;
74 
75 	virtual void slotUpdateTask(ConnectionSlotEvent *event) = 0;
~ConnectionSlotCallbackInterface()76 	virtual ~ConnectionSlotCallbackInterface() {}
77 };
78 
79 class ConnectionSlotThread : public BaseThread, public SlaveThreadControllerInterface
80 {
81 protected:
82 
83 	ConnectionSlotCallbackInterface *slotInterface;
84 	Semaphore semTaskSignalled;
85 	Mutex *triggerIdMutex;
86 	vector<ConnectionSlotEvent> eventList;
87 	int slotIndex;
88 	MasterSlaveThreadController *masterController;
89 
90 	Mutex *triggerGameStarted;
91 	bool gameStarted;
92 
93 	virtual void setQuitStatus(bool value);
94 	virtual void setTaskCompleted(int eventId);
95 
96 	void slotUpdateTask(ConnectionSlotEvent *event);
97 
98 public:
99 	ConnectionSlotThread(int slotIndex);
100 	ConnectionSlotThread(ConnectionSlotCallbackInterface *slotInterface,int slotIndex);
101 	virtual ~ConnectionSlotThread();
102 
103 	bool getGameStarted();
104 	void setGameStarted(bool value);
105 
setMasterController(MasterSlaveThreadController * master)106 	virtual void setMasterController(MasterSlaveThreadController *master) { masterController = master; }
107 	virtual void signalSlave(void *userdata);
108 
109     virtual void execute();
110     void signalUpdate(ConnectionSlotEvent *event);
111     bool isSignalCompleted(ConnectionSlotEvent *event);
112 
getSlotIndex()113     int getSlotIndex() const {return slotIndex; }
setSlotIndex(int index)114     void setSlotIndex(int index) { this->slotIndex = index; }
115 
116     void purgeCompletedEvents();
117     void purgeAllEvents();
118     void setAllEventsCompleted();
119 
120     virtual bool canShutdown(bool deleteSelfIfShutdownDelayed=false);
121 };
122 
123 // =====================================================
124 //	class ConnectionSlot
125 // =====================================================
126 
127 class ConnectionSlot: public NetworkInterface {
128 private:
129 	ServerInterface* serverInterface;
130 
131 	Mutex *mutexSocket;
132 	Socket* socket;
133 	int playerIndex;
134 	string name;
135 	bool ready;
136 	vector<std::pair<string,uint32> > vctFileList;
137 	bool receivedNetworkGameStatus;
138 	time_t connectedTime;
139 	bool gotIntro;
140 
141 	Mutex *mutexCloseConnection;
142 
143 	Mutex *mutexPendingNetworkCommandList;
144 	vector<NetworkCommand> vctPendingNetworkCommandList;
145 	ConnectionSlotThread* slotThreadWorker;
146 	int currentFrameCount;
147 	int currentLagCount;
148 	time_t lastReceiveCommandListTime;
149 	bool gotLagCountWarning;
150 	string versionString;
151 	int sessionKey;
152 	uint32 connectedRemoteIPAddress;
153 	int playerStatus;
154 	string playerLanguage;
155 	string playerUUID;
156 	string platform;
157 
158 	bool skipLagCheck;
159 	bool joinGameInProgress;
160 	bool canAcceptConnections;
161 	bool startInGameConnectionLaunch;
162 	bool pauseForInGameConnection;
163 	bool unPauseForInGameConnection;
164 	bool sentSavedGameInfo;
165 
166 	int autoPauseGameCountForLag;
167 
168 public:
169 	ConnectionSlot(ServerInterface* serverInterface, int playerIndex);
170 	~ConnectionSlot();
171 
172 	int getAutoPauseGameCountForLag();
173 	void incrementAutoPauseGameCountForLag();
174 
175 	bool getGameStarted();
176 	void setGameStarted(bool value);
177 
getStartInGameConnectionLaunch()178 	bool getStartInGameConnectionLaunch() const { return startInGameConnectionLaunch; }
setStartInGameConnectionLaunch(bool value)179 	void setStartInGameConnectionLaunch(bool value) { startInGameConnectionLaunch = value; }
180 
getPauseForInGameConnection()181 	bool getPauseForInGameConnection() const { return pauseForInGameConnection; }
setPauseForInGameConnection(bool value)182 	void setPauseForInGameConnection(bool value) { pauseForInGameConnection = value; }
183 
getUnPauseForInGameConnection()184 	bool getUnPauseForInGameConnection() const { return unPauseForInGameConnection; }
setUnPauseForInGameConnection(bool value)185 	void setUnPauseForInGameConnection(bool value) { unPauseForInGameConnection = value; }
186 
getSkipLagCheck()187 	bool getSkipLagCheck() const { return skipLagCheck; }
getJoinGameInProgress()188 	bool getJoinGameInProgress() const { return joinGameInProgress; }
189 
getSentSavedGameInfo()190 	bool getSentSavedGameInfo() const { return sentSavedGameInfo; }
setSentSavedGameInfo(bool value)191 	void setSentSavedGameInfo(bool value) { sentSavedGameInfo = value; }
192 
getWorkerThread()193 	ConnectionSlotThread *getWorkerThread() { return slotThreadWorker; }
194 
195     void update(bool checkForNewClients,int lockedSlotIndex);
196 	void setPlayerIndex(int value);
getPlayerIndex()197 	int getPlayerIndex() const {return playerIndex;}
198 
getConnectedRemoteIPAddress()199 	uint32 getConnectedRemoteIPAddress() const { return connectedRemoteIPAddress; }
200 
201 	void setReady();
getName()202 	const string &getName() const	{return name;}
getUUID()203 	const string &getUUID() const	{return playerUUID;}
getPlatform()204 	const string &getPlatform() const { return platform; }
setName(string value)205 	void setName(string value)      {name = value;}
isReady()206 	bool isReady() const			{return ready;}
207 
208 	virtual std::string getIpAddress(bool mutexLock=true);
209 
210 	virtual Socket* getSocket(bool mutexLock=true);
211 	pair<bool,Socket*> getSocketInfo();
212 
213 	virtual void close();
214 	//virtual bool getFogOfWar();
215 
getReceivedNetworkGameStatus()216 	bool getReceivedNetworkGameStatus() const { return receivedNetworkGameStatus; }
setReceivedNetworkGameStatus(bool value)217 	void setReceivedNetworkGameStatus(bool value) { receivedNetworkGameStatus = value; }
218 
219 	bool hasValidSocketId();
getConnectHasHandshaked()220 	virtual bool getConnectHasHandshaked() const { return gotIntro; }
getThreadErrorList()221 	std::vector<std::string> getThreadErrorList() const { return threadErrorList; }
clearThreadErrorList()222 	void clearThreadErrorList() { threadErrorList.clear(); }
223 
224 	vector<NetworkCommand> getPendingNetworkCommandList(bool clearList=false);
225 	void clearPendingNetworkCommandList();
226 
227 	void signalUpdate(ConnectionSlotEvent *event);
228 	bool updateCompleted(ConnectionSlotEvent *event);
229 
230 	virtual void sendMessage(NetworkMessage* networkMessage);
getCurrentFrameCount()231 	int getCurrentFrameCount() const { return currentFrameCount; }
232 
getCurrentLagCount()233 	int getCurrentLagCount() const { return currentLagCount; }
setCurrentLagCount(int value)234 	void setCurrentLagCount(int value) { currentLagCount = value; }
235 
getLastReceiveCommandListTime()236 	time_t getLastReceiveCommandListTime() const { return lastReceiveCommandListTime; }
237 
getLagCountWarning()238 	bool getLagCountWarning() const { return gotLagCountWarning; }
setLagCountWarning(bool value)239 	void setLagCountWarning(bool value) { gotLagCountWarning = value; }
240 
getVersionString()241 	const string &getVersionString() const	{return versionString;}
242 
243 	void validateConnection();
244 	virtual string getHumanPlayerName(int index=-1);
getHumanPlayerIndex()245 	virtual int getHumanPlayerIndex() const {return playerIndex;}
246 
getNetworkPlayerStatus()247 	int getNetworkPlayerStatus() const { return playerStatus;}
248 
getNetworkPlayerLanguage()249 	string getNetworkPlayerLanguage() const { return playerLanguage; }
250 
getConnectedTime()251 	time_t getConnectedTime() const { return connectedTime; }
getSessionKey()252 	int getSessionKey() const { return sessionKey; }
253 
254 	void updateSlot(ConnectionSlotEvent *event);
255 	virtual bool isConnected();
256 
257 	PLATFORM_SOCKET getSocketId();
258 
setCanAcceptConnections(bool value)259 	void setCanAcceptConnections(bool value) { canAcceptConnections = value; }
getCanAcceptConnections()260 	bool getCanAcceptConnections() const { return canAcceptConnections; }
261 
saveGame(XmlNode * rootNode)262 	virtual void saveGame(XmlNode *rootNode) {};
263 
264 	void resetJoinGameInProgressFlags();
265 	void setJoinGameInProgressFlags();
266 
267 protected:
268 
269 	Mutex * getServerSynchAccessor();
270 	std::vector<std::string> threadErrorList;
271 	Mutex *socketSynchAccessor;
272 
273 	void setSocket(Socket *newSocket);
274 	void deleteSocket();
update()275 	virtual void update() {}
276 
277 	bool hasDataToRead();
278 };
279 
280 }}//end namespace
281 
282 #endif
283