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 #include "connection_slot.h"
13 
14 #include "conversion.h"
15 #include "game_util.h"
16 #include "config.h"
17 #include "server_interface.h"
18 #include "network_message.h"
19 #include "platform_util.h"
20 #include <stdexcept>
21 
22 #include "leak_dumper.h"
23 
24 using namespace std;
25 using namespace Shared::Util;
26 
27 namespace Glest{ namespace Game{
28 
29 // =====================================================
30 //	class ConnectionSlotThread
31 // =====================================================
32 
ConnectionSlotThread(int slotIndex)33 ConnectionSlotThread::ConnectionSlotThread(int slotIndex) : BaseThread() {
34 	this->masterController 	= NULL;
35 	this->triggerIdMutex 	= new Mutex(CODE_AT_LINE);
36 	this->slotIndex 		= slotIndex;
37 	this->slotInterface 	= NULL;
38 	uniqueID 				= "ConnectionSlotThread";
39 	eventList.clear();
40 	eventList.reserve(1000);
41 
42 	triggerGameStarted 		= new Mutex(CODE_AT_LINE);
43 	gameStarted 			= false;
44 }
45 
ConnectionSlotThread(ConnectionSlotCallbackInterface * slotInterface,int slotIndex)46 ConnectionSlotThread::ConnectionSlotThread(ConnectionSlotCallbackInterface *slotInterface,int slotIndex) : BaseThread() {
47 	this->masterController 	= NULL;
48 	this->triggerIdMutex 	= new Mutex(CODE_AT_LINE);
49 	this->slotIndex 		= slotIndex;
50 	this->slotInterface 	= slotInterface;
51 	uniqueID 				= "ConnectionSlotThread";
52 	eventList.clear();
53 
54 	triggerGameStarted 		= new Mutex(CODE_AT_LINE);
55 	gameStarted 			= false;
56 }
57 
~ConnectionSlotThread()58 ConnectionSlotThread::~ConnectionSlotThread() {
59 	delete triggerIdMutex;
60 	triggerIdMutex = NULL;
61 
62 	delete triggerGameStarted;
63 	triggerGameStarted = NULL;
64 }
65 
setQuitStatus(bool value)66 void ConnectionSlotThread::setQuitStatus(bool value) {
67 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d value = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
68 
69 	BaseThread::setQuitStatus(value);
70 	if(value == true) {
71 		signalUpdate(NULL);
72 	}
73 
74 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
75 }
76 
signalUpdate(ConnectionSlotEvent * event)77 void ConnectionSlotThread::signalUpdate(ConnectionSlotEvent *event) {
78 	if(event != NULL) {
79 		MutexSafeWrapper safeMutex(triggerIdMutex,CODE_AT_LINE);
80 		eventList.push_back(*event);
81 	}
82 	if(getGameStarted() == true && getQuitStatus() == true) {
83 		return;
84 	}
85 	semTaskSignalled.signal();
86 }
87 
setTaskCompleted(int eventId)88 void ConnectionSlotThread::setTaskCompleted(int eventId) {
89 	if(eventId > 0) {
90 		MutexSafeWrapper safeMutex(triggerIdMutex,CODE_AT_LINE);
91 		for(int index = 0; index < (int)eventList.size(); ++index) {
92 		    ConnectionSlotEvent &slotEvent = eventList[index];
93 		    if(slotEvent.eventId == eventId) {
94                 slotEvent.eventCompleted = true;
95                 break;
96 		    }
97 		}
98 	}
99 }
100 
purgeAllEvents()101 void ConnectionSlotThread::purgeAllEvents() {
102     MutexSafeWrapper safeMutex(triggerIdMutex,CODE_AT_LINE);
103     eventList.clear();
104 }
105 
setAllEventsCompleted()106 void ConnectionSlotThread::setAllEventsCompleted() {
107     MutexSafeWrapper safeMutex(triggerIdMutex,CODE_AT_LINE);
108     for(int index = 0; index < (int)eventList.size(); ++index) {
109         ConnectionSlotEvent &slotEvent = eventList[index];
110         if(slotEvent.eventCompleted == false) {
111             slotEvent.eventCompleted = true;
112         }
113     }
114 }
115 
purgeCompletedEvents()116 void ConnectionSlotThread::purgeCompletedEvents() {
117     MutexSafeWrapper safeMutex(triggerIdMutex,CODE_AT_LINE);
118     for(int index = (int)eventList.size() - 1; index >= 0; index--) {
119         ConnectionSlotEvent &slotEvent = eventList[index];
120         if(slotEvent.eventCompleted == true) {
121             eventList.erase(eventList.begin() + index);
122         }
123     }
124 }
125 
canShutdown(bool deleteSelfIfShutdownDelayed)126 bool ConnectionSlotThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
127 	bool ret = (getExecutingTask() == false);
128 	if(ret == false && deleteSelfIfShutdownDelayed == true) {
129 	    setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed);
130 	    deleteSelfIfRequired();
131 	    signalQuit();
132 	}
133 
134 	return ret;
135 }
136 
isSignalCompleted(ConnectionSlotEvent * event)137 bool ConnectionSlotThread::isSignalCompleted(ConnectionSlotEvent *event) {
138 	bool result = false;
139     if(event != NULL) {
140     	MutexSafeWrapper safeMutex(triggerIdMutex,CODE_AT_LINE);
141         for(int index = 0; index < (int)eventList.size(); ++index) {
142             ConnectionSlotEvent &slotEvent = eventList[index];
143             if(slotEvent.eventId == event->eventId) {
144                 result = slotEvent.eventCompleted;
145                 break;
146             }
147         }
148     }
149 	return result;
150 }
151 
slotUpdateTask(ConnectionSlotEvent * event)152 void ConnectionSlotThread::slotUpdateTask(ConnectionSlotEvent *event) {
153 	if(event != NULL && event->connectionSlot != NULL) {
154 		if(event->eventType == eSendSocketData) {
155 			event->connectionSlot->sendMessage(event->networkMessage);
156 		}
157 		else if(event->eventType == eReceiveSocketData) {
158 			event->connectionSlot->updateSlot(event);
159 		}
160 	}
161 }
162 
signalSlave(void * userdata)163 void ConnectionSlotThread::signalSlave(void *userdata) {
164 	std::map<int,ConnectionSlotEvent> *eventList = (std::map<int,ConnectionSlotEvent> *)userdata;
165 	ConnectionSlotEvent &event = (*eventList)[slotIndex];
166 	signalUpdate(&event);
167 }
168 
getGameStarted()169 bool ConnectionSlotThread::getGameStarted() {
170 	MutexSafeWrapper safeMutexGameStarted(triggerGameStarted,CODE_AT_LINE);
171 	return gameStarted;
172 }
setGameStarted(bool value)173 void ConnectionSlotThread::setGameStarted(bool value) {
174 	MutexSafeWrapper safeMutexGameStarted(triggerGameStarted,CODE_AT_LINE);
175 	if(gameStarted != value) {
176 		gameStarted = value;
177 
178 		if(gameStarted == true) {
179 			semTaskSignalled.signal();
180 		}
181 	}
182 }
183 
execute()184 void ConnectionSlotThread::execute() {
185     RunningStatusSafeWrapper runningStatus(this);
186 	try {
187 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
188 		//printf("Starting client SLOT thread: %d\n",slotIndex);
189 
190 		for(;this->slotInterface != NULL;) {
191 			if(getQuitStatus() == true) {
192 				SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
193 				break;
194 			}
195 
196 			// Does this game allow joining in progress play and is this slot
197 			// not already connected to a client?
198 			if( this->slotInterface->getAllowInGameConnections() == true &&
199 				this->slotInterface->isClientConnected(slotIndex) == false) {
200 				//printf("#1 Non connected slot: %d waiting for client connection..\n",slotIndex);
201 				sleep(100);
202 
203 				if(getQuitStatus() == true) {
204 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
205 					break;
206 				}
207 
208 				//printf("Slot thread slotIndex: %d eventCount: %d\n",slotIndex,eventCount);
209 
210 				ConnectionSlotEvent eventCopy;
211 				eventCopy.eventType 		= eReceiveSocketData;
212 				eventCopy.connectionSlot 	= this->slotInterface->getSlot(slotIndex,true);
213 
214 				if(getQuitStatus() == true) {
215 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
216 					break;
217 				}
218 
219 				ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
220 				this->slotUpdateTask(&eventCopy);
221 			}
222 			else {
223 				// If the game already started?
224 				if(getGameStarted() == true) {
225 					//printf("#A Checking action for slot: %d\n",slotIndex);
226 
227 					if(getQuitStatus() == true) {
228 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
229 						break;
230 					}
231 
232 					ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
233 
234 					// If the slot or socket are NULL the connection was lost
235 					// so exit the thread
236 					MutexSafeWrapper safeMutex(this->slotInterface->getSlotMutex(slotIndex),CODE_AT_LINE);
237 					ConnectionSlot *slot = this->slotInterface->getSlot(slotIndex,false);
238 					if(slot == NULL) {
239 						break;
240 					}
241 					Socket *socket = slot->getSocket(true);
242 					if(socket == NULL) {
243 						break;
244 					}
245 
246 					PLATFORM_SOCKET socketId = socket->getSocketId();
247 					safeMutex.ReleaseLock();
248 
249 					// Avoid mutex locking
250 					//bool socketHasReadData = Socket::hasDataToRead(socket->getSocketId());
251 					bool socketHasReadData = Socket::hasDataToReadWithWait(socketId,150000);
252 
253 					if(getQuitStatus() == true) {
254 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
255 						break;
256 					}
257 
258 					ConnectionSlotEvent eventCopy;
259 					eventCopy.eventType 		= eReceiveSocketData;
260 					eventCopy.connectionSlot 	= this->slotInterface->getSlot(slotIndex,true);
261 					eventCopy.eventId 			= slotIndex;
262 					eventCopy.socketTriggered 	= socketHasReadData;
263 
264 					if(getQuitStatus() == true) {
265 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
266 						break;
267 					}
268 
269 					this->slotUpdateTask(&eventCopy);
270 				}
271 				// Game has not yet started
272 				else {
273 					//printf("#1 Checking action for slot: %d\n",slotIndex);
274 
275 					if(getGameStarted() == true) {
276 						continue;
277 					}
278 					//printf("#2 Checking action for slot: %d\n",slotIndex);
279 
280 					semTaskSignalled.waitTillSignalled();
281 					//printf("#3 Checking action for slot: %d\n",slotIndex);
282 
283 					if(getGameStarted() == true) {
284 						continue;
285 					}
286 					//printf("#4 Checking action for slot: %d\n",slotIndex);
287 
288 					static string masterSlaveOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
289 					MasterSlaveThreadControllerSafeWrapper safeMasterController(masterController,20000,masterSlaveOwnerId);
290 					if(getQuitStatus() == true) {
291 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
292 						break;
293 					}
294 
295 					MutexSafeWrapper safeMutex(triggerIdMutex,CODE_AT_LINE);
296 					int eventCount = (int)eventList.size();
297 
298 					//printf("Slot thread slotIndex: %d eventCount: %d\n",slotIndex,eventCount);
299 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Slot thread slotIndex: %d eventCount: %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex,eventCount);
300 
301 					if(eventCount > 0) {
302 						ConnectionSlotEvent eventCopy;
303 						for(int i = 0; i < (int)eventList.size(); ++i) {
304 							ConnectionSlotEvent &slotEvent = eventList[i];
305 							if(slotEvent.eventCompleted == false) {
306 								eventCopy = slotEvent;
307 								break;
308 							}
309 						}
310 						safeMutex.ReleaseLock();
311 
312 						if(getQuitStatus() == true) {
313 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
314 							break;
315 						}
316 
317 						if(eventCopy.eventId > 0) {
318 							ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
319 
320 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Slot thread slotIndex: %d eventCount: %d eventCopy.eventId: %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex,eventCount,(int)eventCopy.eventId);
321 							//printf("#1 Slot thread slotIndex: %d eventCount: %d eventCopy.eventId: %d\n",slotIndex,eventCount,(int)eventCopy.eventId);
322 
323 							this->slotUpdateTask(&eventCopy);
324 							setTaskCompleted(eventCopy.eventId);
325 
326 							//printf("#2 Slot thread slotIndex: %d eventCount: %d eventCopy.eventId: %d\n",slotIndex,eventCount,(int)eventCopy.eventId);
327 						}
328 					}
329 				}
330 			}
331 
332 			if(getQuitStatus() == true) {
333 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
334 				break;
335 			}
336 		}
337 
338 		//printf("Ending client SLOT thread: %d\n",slotIndex);
339 
340 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
341 	}
342 	catch(const exception &ex) {
343 
344 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
345 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
346 
347 		throw megaglest_runtime_error(ex.what());
348 	}
349 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
350 }
351 
352 // =====================================================
353 //	class ConnectionSlot
354 // =====================================================
355 
ConnectionSlot(ServerInterface * serverInterface,int playerIndex)356 ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex) {
357 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
358 
359 	this->mutexSocket 						= new Mutex(CODE_AT_LINE);
360 	this->socket 							= NULL;
361 	this->mutexCloseConnection 				= new Mutex(CODE_AT_LINE);
362 	this->mutexPendingNetworkCommandList 	= new Mutex(CODE_AT_LINE);
363 	this->socketSynchAccessor 				= new Mutex(CODE_AT_LINE);
364     this->connectedRemoteIPAddress 			= 0;
365 	this->sessionKey 						= 0;
366 	this->serverInterface					= serverInterface;
367 	this->playerIndex						= playerIndex;
368 	this->playerStatus						= npst_None;
369 	this->playerLanguage					= "";
370 	this->playerUUID						= "";
371 	this->platform							= "";
372 	this->currentFrameCount 				= 0;
373 	this->currentLagCount					= 0;
374 	this->gotLagCountWarning 				= false;
375 	this->lastReceiveCommandListTime		= 0;
376 	this->receivedNetworkGameStatus 		= false;
377 
378 	this->autoPauseGameCountForLag			= 0;
379 	this->skipLagCheck 						= false;
380 	this->joinGameInProgress 				= false;
381 	this->canAcceptConnections 				= true;
382 	this->startInGameConnectionLaunch 		= false;
383 	this->pauseForInGameConnection 			= false;
384 	this->unPauseForInGameConnection 		= false;
385 	this->sentSavedGameInfo 				= false;
386 
387 	this->ready								= false;
388 	this->gotIntro 							= false;
389 	this->connectedTime 					= 0;
390 
391 	this->networkGameDataSynchCheckOkMap    = false;
392 	this->networkGameDataSynchCheckOkTile   = false;
393 	this->networkGameDataSynchCheckOkTech   = false;
394 	this->setNetworkGameDataSynchCheckTechMismatchReport("");
395 	this->setReceivedDataSynchCheck(false);
396 
397 	this->clearChatInfo();
398 
399 	this->setSocket(NULL);
400 	this->slotThreadWorker 					= NULL;
401 	static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
402 	this->slotThreadWorker 					= new ConnectionSlotThread(this->serverInterface,playerIndex);
403 	this->slotThreadWorker->setUniqueID(mutexOwnerId);
404 	this->slotThreadWorker->start();
405 }
406 
~ConnectionSlot()407 ConnectionSlot::~ConnectionSlot() {
408 	//printf("===> Destructor for ConnectionSlot = %d\n",playerIndex);
409 
410 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] START\n",__FILE__,__FUNCTION__,__LINE__);
411 
412 	//printf("Deleting connection slot\n");
413 	close();
414 
415 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
416 
417 	//printf("#1 Ending client SLOT: %d slotThreadWorker: %p\n",playerIndex,slotThreadWorker);
418 	if(slotThreadWorker != NULL) {
419 		slotThreadWorker->signalQuit();
420 	}
421 	if( slotThreadWorker != NULL &&
422 		slotThreadWorker->canShutdown(false) == true &&
423 		slotThreadWorker->getRunningStatus() == false) {
424 		//printf("#2 Ending client SLOT: %d\n",playerIndex);
425 
426 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
427 
428 		delete slotThreadWorker;
429 
430         if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
431 	}
432 	else if(slotThreadWorker != NULL &&
433 			slotThreadWorker->canShutdown(true) == true) {
434 
435 		if(slotThreadWorker->getRunningStatus() == false) {
436 			//printf("#3 Ending client SLOT: %d\n",playerIndex);
437 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
438 
439 			delete slotThreadWorker;
440 
441 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
442 		}
443 		else {
444 			slotThreadWorker->setDeleteSelfOnExecutionDone(true);
445 			slotThreadWorker->setDeleteAfterExecute(true);
446 		}
447 	}
448 	//printf("#4 Ending client SLOT: %d\n",playerIndex);
449 	slotThreadWorker = NULL;
450 
451 	delete socketSynchAccessor;
452 	socketSynchAccessor = NULL;
453 
454 	delete mutexPendingNetworkCommandList;
455 	mutexPendingNetworkCommandList = NULL;
456 
457 	delete mutexCloseConnection;
458 	mutexCloseConnection = NULL;
459 
460 	delete mutexSocket;
461 	mutexSocket = NULL;
462 
463 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
464 }
465 
getAutoPauseGameCountForLag()466 int ConnectionSlot::getAutoPauseGameCountForLag() {
467 	return autoPauseGameCountForLag;
468 }
469 
incrementAutoPauseGameCountForLag()470 void ConnectionSlot::incrementAutoPauseGameCountForLag() {
471 	autoPauseGameCountForLag++;
472 }
473 
getGameStarted()474 bool ConnectionSlot::getGameStarted() {
475 	bool result = false;
476 	if(this->slotThreadWorker != NULL) {
477 		result = this->slotThreadWorker->getGameStarted();
478 	}
479 	return result;
480 }
setGameStarted(bool value)481 void ConnectionSlot::setGameStarted(bool value) {
482 	if(this->slotThreadWorker != NULL) {
483 		this->slotThreadWorker->setGameStarted(value);
484 	}
485 }
486 
setPlayerIndex(int value)487 void ConnectionSlot::setPlayerIndex(int value) {
488 	playerIndex = value;
489 
490 	if(this->slotThreadWorker != NULL) {
491 		this->slotThreadWorker->setSlotIndex(playerIndex);
492 	}
493 }
494 
setReady()495 void ConnectionSlot::setReady()	{
496 	this->ready= true;
497 	this->skipLagCheck = false;
498 	this->joinGameInProgress = false;
499 	this->sentSavedGameInfo = false;
500 }
501 
updateSlot(ConnectionSlotEvent * event)502 void ConnectionSlot::updateSlot(ConnectionSlotEvent *event) {
503 	if(event != NULL) {
504 		bool &socketTriggered = event->socketTriggered;
505 		bool checkForNewClients =
506 				(serverInterface->getGameHasBeenInitiated() == false ||
507 					serverInterface->getAllowInGameConnections() == true);
508 
509 		//if((serverInterface->getGameHasBeenInitiated() == false ||
510 		//	(serverInterface->getAllowInGameConnections() == true && this->isConnected() == false) ||
511 		//	socketTriggered == true)) {
512 		if(socketTriggered == true ||
513 			((serverInterface->getGameHasBeenInitiated() == false ||
514 			  serverInterface->getAllowInGameConnections() == true) &&
515 				this->isConnected() == false)) {
516 
517 			this->update(checkForNewClients,event->triggerId);
518 		}
519 		//}
520 	}
521 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
522 }
523 
getIpAddress(bool mutexLock)524 string ConnectionSlot::getIpAddress(bool mutexLock) {
525 	string result = "";
526 	MutexSafeWrapper safeMutexSlot((mutexLock == true ? mutexSocket : NULL),CODE_AT_LINE);
527 	if(socket != NULL) {
528 		result = socket->getIpAddress();
529 	}
530 	return result;
531 }
532 
update(bool checkForNewClients,int lockedSlotIndex)533 void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
534 	try {
535 		clearThreadErrorList();
536 
537 	    if(slotThreadWorker != NULL) {
538 	        slotThreadWorker->purgeCompletedEvents();
539 	    }
540 
541 	    pair<bool,Socket*> socketInfo = this->getSocketInfo();
542 		if(socketInfo.second == NULL) {
543 			if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap  = false;
544 			if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false;
545 			if(networkGameDataSynchCheckOkTech) networkGameDataSynchCheckOkTech = false;
546 			this->setReceivedDataSynchCheck(false);
547 
548 			// Is the listener socket ready to be read?
549 			if(checkForNewClients == true && this->canAcceptConnections == true) {
550 
551 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] BEFORE accept new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getOpenSlotCount());
552 
553 				//printf("Checking for new connections...\n");
554 				bool hasData = (serverInterface->getServerSocket() != NULL &&
555 								serverInterface->getServerSocket()->hasDataToRead() == true);
556 				//printf("Server socket hasData: %d\n",hasData);
557 
558 				if(hasData == true) {
559 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] about to accept new client connection playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex);
560 
561 					Socket *newSocket = serverInterface->getServerSocket()->accept(false);
562 
563 					//printf("Server socket newSocket: %p\n",newSocket);
564 
565 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] called accept new client connection playerIndex = %d newSocket = %p\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,newSocket);
566 					if(newSocket != NULL) {
567 						// Set Socket as non-blocking
568 						newSocket->setBlock(false);
569 
570 						MutexSafeWrapper safeMutex(mutexCloseConnection,CODE_AT_LINE);
571 						this->setSocket(newSocket);
572 						safeMutex.ReleaseLock();
573 
574 						this->connectedTime = time(NULL);
575 						this->clearChatInfo();
576 						this->name = "";
577 						this->playerStatus = npst_PickSettings;
578 						this->playerLanguage = "";
579 						this->playerUUID     = "";
580 						this->platform		 = "";
581 						this->ready = false;
582 						this->vctFileList.clear();
583 						this->receivedNetworkGameStatus = false;
584 						this->gotIntro = false;
585 
586 						MutexSafeWrapper safeMutexSlot1(mutexPendingNetworkCommandList,CODE_AT_LINE);
587 						this->vctPendingNetworkCommandList.clear();
588 						safeMutexSlot1.ReleaseLock();
589 
590 						this->currentFrameCount = 0;
591 						this->currentLagCount = 0;
592 						this->lastReceiveCommandListTime = 0;
593 						this->gotLagCountWarning = false;
594 						this->versionString = "";
595 
596 						serverInterface->updateListen();
597 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex);
598 					}
599 					else {
600 						close();
601 						return;
602 					}
603 
604 					//send intro message when connected
605 					if(this->isConnected() == true) {
606 						//printf("Server socket newSocket is connected: %d\n",playerIndex);
607 
608 						Chrono seed(true);
609 						srand((unsigned int)seed.getCurTicks() / (this->playerIndex + 1));
610 
611 						sessionKey = rand() % 1000000;
612 
613 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] accepted new client connection, serverInterface->getOpenSlotCount() = %d, sessionKey = %d\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getOpenSlotCount(),sessionKey);
614 						if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] client will be assigned to the next open slot\n",__FILE__,__FUNCTION__,__LINE__);
615 
616 						NetworkMessageIntro networkMessageIntro(
617 								sessionKey,
618 								getNetworkVersionGITString(),
619 								getHostName(),
620 								playerIndex,
621 								nmgstOk,
622 								0,
623 								ServerSocket::getFTPServerPort(),
624 								"",
625 								serverInterface->getGameHasBeenInitiated(),
626 								Config::getInstance().getString("PlayerId",""),
627 								getPlatformNameString());
628 						sendMessage(&networkMessageIntro);
629 
630 						if(this->serverInterface->getGameHasBeenInitiated() == true) {
631 							setGameStarted(true);
632 						}
633 					}
634 				}
635 			}
636 		}
637 		else {
638 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
639 
640 			if(socketInfo.first == true) {
641 				this->clearChatInfo();
642 
643 				bool gotTextMsg = true;
644 				bool gotCellMarkerMsg = true;
645 				bool waitForLaggingClient = false;
646 				bool waitedForLaggingClient = false;
647 
648 				//printf("Update slot: %d this->hasDataToRead(): %d\n",this->playerIndex,this->hasDataToRead());
649 
650 				for(;waitForLaggingClient == true ||
651 						(this->hasDataToRead() == true &&
652 						 (gotTextMsg == true || gotCellMarkerMsg == true));) {
653 
654 					//printf("Server slot checking for waitForLaggingClient = %d this->hasDataToRead() = %d gotTextMsg = %d gotCellMarkerMsg = %d\n",waitForLaggingClient,this->hasDataToRead(),gotTextMsg,gotCellMarkerMsg);
655 
656 					waitForLaggingClient = false;
657 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] polling for networkMessageType...\n",__FILE__,__FUNCTION__,__LINE__);
658 
659 					NetworkMessageType networkMessageType= getNextMessageType();
660 
661 					if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] networkMessageType = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageType);
662 
663 					gotTextMsg = false;
664 					gotCellMarkerMsg = false;
665 					//process incoming commands
666 					switch(networkMessageType) {
667 
668 						case nmtInvalid:
669 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtInvalid\n",__FILE__,__FUNCTION__,__LINE__);
670 							break;
671 
672 						case nmtPing:
673 						{
674 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__);
675 
676 							// client REQUIRES a ping before completing intro
677 							// authentication
678 							NetworkMessagePing networkMessagePing;
679 							if(receiveMessage(&networkMessagePing)) {
680 								if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
681 								lastPingInfo = networkMessagePing;
682 							}
683 							else {
684 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
685 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
686 								close();
687 								return;
688 							}
689 						}
690 						break;
691 
692 						case nmtText:
693 						{
694 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtText gotIntro = %d\n",__FILE__,__FUNCTION__,__LINE__,gotIntro);
695 
696 							if(gotIntro == true) {
697 								NetworkMessageText networkMessageText;
698 								if(receiveMessage(&networkMessageText)) {
699 									ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getTeamIndex(),networkMessageText.getPlayerIndex(),networkMessageText.getTargetLanguage());
700 									this->addChatInfo(msg);
701 									gotTextMsg = true;
702 								}
703 								else {
704 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
705 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
706 									close();
707 									return;
708 								}
709 							}
710 							else {
711 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
712 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
713 								close();
714 								return;
715 							}
716 						}
717 						break;
718 
719 						case nmtMarkCell:
720 						{
721 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtMarkCell gotIntro = %d\n",__FILE__,__FUNCTION__,__LINE__,gotIntro);
722 
723 							if(gotIntro == true) {
724 								NetworkMessageMarkCell networkMessageMarkCell;
725 								if(receiveMessage(&networkMessageMarkCell)) {
726 					            	MarkedCell msg(networkMessageMarkCell.getTarget(),
727 					            			       networkMessageMarkCell.getFactionIndex(),
728 					            			       networkMessageMarkCell.getText().c_str(),
729 					            			       networkMessageMarkCell.getPlayerIndex());
730 
731 					            	this->addMarkedCell(msg);
732 					            	gotCellMarkerMsg = true;
733 								}
734 								else {
735 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
736 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
737 									close();
738 									return;
739 								}
740 							}
741 							else {
742 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
743 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
744 								close();
745 								return;
746 							}
747 						}
748 						break;
749 
750 						case nmtUnMarkCell:
751 						{
752 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtUnMarkCell gotIntro = %d\n",__FILE__,__FUNCTION__,__LINE__,gotIntro);
753 
754 							if(gotIntro == true) {
755 								NetworkMessageUnMarkCell networkMessageMarkCell;
756 								if(receiveMessage(&networkMessageMarkCell)) {
757 					            	UnMarkedCell msg(networkMessageMarkCell.getTarget(),
758 					            			       networkMessageMarkCell.getFactionIndex());
759 
760 					            	this->addUnMarkedCell(msg);
761 					            	gotCellMarkerMsg = true;
762 								}
763 								else {
764 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
765 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
766 									close();
767 									return;
768 								}
769 							}
770 							else {
771 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
772 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
773 								close();
774 								return;
775 							}
776 						}
777 						break;
778 
779 						case nmtHighlightCell:
780 						{
781 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtMarkCell gotIntro = %d\n",__FILE__,__FUNCTION__,__LINE__,gotIntro);
782 
783 							if(gotIntro == true) {
784 								NetworkMessageHighlightCell networkMessageHighlightCell;
785 								if(receiveMessage(&networkMessageHighlightCell)) {
786 					            	MarkedCell msg(networkMessageHighlightCell.getTarget(),
787 					            			networkMessageHighlightCell.getFactionIndex(),"none",-1);
788 
789 					            	this->setHighlightedCell(msg);
790 					            	gotCellMarkerMsg = true;
791 								}
792 								else {
793 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
794 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
795 									close();
796 									return;
797 								}
798 							}
799 							else {
800 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
801 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
802 								close();
803 								return;
804 							}
805 						}
806 						break;
807 
808 						//command list
809 						case nmtCommandList: {
810 
811 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtCommandList gotIntro = %d\n",__FILE__,__FUNCTION__,__LINE__,gotIntro);
812 
813 							if(gotIntro == true) {
814 								NetworkMessageCommandList networkMessageCommandList;
815 								if(receiveMessage(&networkMessageCommandList)) {
816 									currentFrameCount = networkMessageCommandList.getFrameCount();
817 									lastReceiveCommandListTime = time(NULL);
818 
819 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] currentFrameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,currentFrameCount);
820 
821 									MutexSafeWrapper safeMutexSlot(mutexPendingNetworkCommandList,CODE_AT_LINE);
822 									for(int i = 0; i < networkMessageCommandList.getCommandCount(); ++i) {
823 										vctPendingNetworkCommandList.push_back(*networkMessageCommandList.getCommand(i));
824 									}
825 									//printf("Got commands from client frame: %d count: %d\n",currentFrameCount,vctPendingNetworkCommandList.size());
826 
827 									//printf("#2 Server slot got currentFrameCount = %d\n",currentFrameCount);
828 								}
829 								else {
830 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
831 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
832 									close();
833 									return;
834 								}
835 							}
836 							else {
837 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
838 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
839 								close();
840 								return;
841 							}
842 						}
843 						break;
844 
845 						//process intro messages
846 						case nmtIntro:
847 						{
848 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtIntro\n",__FILE__,__FUNCTION__);
849 
850 							NetworkMessageIntro networkMessageIntro;
851 							if(receiveMessage(&networkMessageIntro)) {
852 								int32 msgSessionId = networkMessageIntro.getSessionId();
853 								this->name= networkMessageIntro.getName();
854 								this->versionString = networkMessageIntro.getVersionString();
855 								this->connectedRemoteIPAddress = networkMessageIntro.getExternalIp();
856 								this->playerLanguage = networkMessageIntro.getPlayerLanguage();
857 								this->playerUUID	  = networkMessageIntro.getPlayerUUID();
858 								this->platform		  = networkMessageIntro.getPlayerPlatform();
859 
860 								//printf("Got uuid from client [%s]\n",this->playerUUID.c_str());
861 								if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got name [%s] versionString [%s], msgSessionId = %d\n",__FILE__,__FUNCTION__,name.c_str(),versionString.c_str(),msgSessionId);
862 
863 								if(msgSessionId != sessionKey) {
864 									string playerNameStr = name;
865 									string sErr = "Client gave invalid sessionid for player [" + playerNameStr + "] actual [" + intToStr(msgSessionId) + "] expected [" + intToStr(sessionKey) + "]";
866 									printf("%s\n",sErr.c_str());
867 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
868 
869 									close();
870 									return;
871 								}
872 								else if(this->playerUUID == "") {
873 									string playerNameStr = name;
874 									string sErr = "Client gave an invalid UUID for player [" + playerNameStr + "]";
875 									printf("%s\n",sErr.c_str());
876 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
877 
878 									close();
879 									return;
880 								}
881 								else {
882 									//check consistency
883 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
884 
885 									bool compatible = checkVersionComptability(getNetworkVersionGITString(), networkMessageIntro.getVersionString());
886 
887 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
888 
889 									if(compatible == false) {
890 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
891 
892 										bool versionMatched = false;
893 										string platformFreeVersion = getNetworkPlatformFreeVersionString();
894 										string sErr = "";
895 
896 										if(strncmp(platformFreeVersion.c_str(),networkMessageIntro.getVersionString().c_str(),strlen(platformFreeVersion.c_str())) != 0) {
897 											string playerNameStr = name;
898 											sErr = "Server and client binary mismatch!\nYou have to use the exactly same binaries!\n\nServer: " +  getNetworkVersionGITString() +
899 													"\nClient: " + networkMessageIntro.getVersionString() + " player [" + playerNameStr + "]";
900 											printf("%s\n",sErr.c_str());
901 
902 											serverInterface->sendTextMessage("Server and client binary mismatch!!",-1, true,"",lockedSlotIndex);
903 											serverInterface->sendTextMessage(" Server:" + getNetworkVersionGITString(),-1, true,"",lockedSlotIndex);
904 											serverInterface->sendTextMessage(" Client: "+ networkMessageIntro.getVersionString(),-1, true,"",lockedSlotIndex);
905 											serverInterface->sendTextMessage(" Client player [" + playerNameStr + "]",-1, true,"",lockedSlotIndex);
906 										}
907 										else {
908 											versionMatched = true;
909 
910 											string playerNameStr = name;
911 											sErr = "Warning, Server and client are using the same version but different platforms.\n\nServer: " +  getNetworkVersionGITString() +
912 													"\nClient: " + networkMessageIntro.getVersionString() + " player [" + playerNameStr + "]";
913 											//printf("%s\n",sErr.c_str());
914 											if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
915 										}
916 
917 										if(Config::getInstance().getBool("PlatformConsistencyChecks","true") &&
918 										   versionMatched == false) { // error message and disconnect only if checked
919 											if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
920 											close();
921 											if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
922 											return;
923 										}
924 									}
925 
926 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
927 									gotIntro = true;
928 
929 									int factionIndex = this->serverInterface->gameSettings.getFactionIndexForStartLocation(playerIndex);
930 									this->serverInterface->addClientToServerIPAddress(this->getSocket()->getConnectedIPAddress(this->getSocket()->getIpAddress()),this->connectedRemoteIPAddress);
931 
932 									this->serverInterface->gameSettings.setNetworkPlayerUUID(factionIndex,this->playerUUID);
933 									this->serverInterface->gameSettings.setNetworkPlayerPlatform(factionIndex,this->platform);
934 
935 									if(serverInterface->getGameHasBeenInitiated() == true &&
936 									   serverInterface->getAllowInGameConnections() == true) {
937 										this->serverInterface->gameSettings.setNetworkPlayerStatuses(factionIndex,npst_None);
938 									}
939 
940 									if(getAllowGameDataSynchCheck() == true && serverInterface->getGameSettings() != NULL) {
941 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending NetworkMessageSynchNetworkGameData\n",__FILE__,__FUNCTION__,__LINE__);
942 
943 										NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(serverInterface->getGameSettings());
944 										sendMessage(&networkMessageSynchNetworkGameData);
945 									}
946 
947 									if(serverInterface->getGameHasBeenInitiated() == true &&
948 									   serverInterface->getAllowInGameConnections() == true) {
949 
950 										ConnectionSlot *slot = serverInterface->findSlotForUUID(this->playerUUID,true);
951 										if(slot != NULL) {
952 											slot->setJoinGameInProgressFlags();
953 											slot->setPauseForInGameConnection(true);
954 
955 											serverInterface->switchSlot(this->playerIndex,slot->getPlayerIndex());
956 										}
957 										else {
958 											setJoinGameInProgressFlags();
959 											this->setPauseForInGameConnection(true);
960 										}
961 									}
962 									else {
963 										ConnectionSlot *slot = serverInterface->findSlotForUUID(this->playerUUID,true);
964 										if(slot != NULL) {
965 											serverInterface->switchSlot(this->playerIndex,slot->getPlayerIndex());
966 										}
967 									}
968 								}
969 							}
970 							else {
971 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
972 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
973 								close();
974 								return;
975 							}
976 						}
977 						break;
978 
979 				        case nmtLaunch:
980 				        case nmtBroadCastSetup:
981 				        {
982 				        	if(gotIntro == true) {
983 								if(this->serverInterface->getGameSettings() == NULL ||
984 									(joinGameInProgress == false && sessionKey != this->serverInterface->getGameSettings()->getMasterserver_admin())) {
985 									string playerNameStr = name;
986 									string sErr = "Client has invalid admin sessionid for player [" + playerNameStr + "]";
987 									printf("%s\n",sErr.c_str());
988 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
989 
990 									close();
991 									return;
992 								}
993 
994 								NetworkMessageLaunch networkMessageLaunch;
995 								if(receiveMessage(&networkMessageLaunch,networkMessageType)) {
996 									if(networkMessageLaunch.getMessageType() == nmtLaunch) {
997 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtLaunch\n",__FILE__,__FUNCTION__,__LINE__);
998 										//printf("Got launch request from client joinGameInProgress = %d joinGameInProgress = %d!\n",joinGameInProgress,joinGameInProgress);
999 									}
1000 									else if(networkMessageLaunch.getMessageType() == nmtBroadCastSetup) {
1001 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtBroadCastSetup\n",__FILE__,__FUNCTION__,__LINE__);
1002 									}
1003 									else {
1004 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType());
1005 
1006 										char szBuf[1024]="";
1007 										snprintf(szBuf,1023,"In [%s::%s Line: %d] Invalid networkMessageLaunch.getMessageType() = %d",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType());
1008 										throw megaglest_runtime_error(szBuf);
1009 									}
1010 
1011 									int minHeadLessPlayersRequired = Config::getInstance().getInt("MinHeadlessPlayersRequired","2");
1012 									if(this->joinGameInProgress == false &&
1013 										networkMessageLaunch.getMessageType() == nmtLaunch &&
1014 										this->ready == false &&
1015 										this->serverInterface->getConnectedSlotCount(true) < minHeadLessPlayersRequired) {
1016 
1017 								    	Lang &lang= Lang::getInstance();
1018 								    	const vector<string> languageList = this->serverInterface->getGameSettings()->getUniqueNetworkPlayerLanguages();
1019 								    	for(unsigned int index = 0; index < languageList.size(); ++index) {
1020 								    		char szBuf[4096]="";
1021 											string msgTemplate = "You must have have at least %d player(s) connected to start this game!";
1022 											if(lang.hasString("HeadlessAdminRequiresMorePlayers",languageList[index]) == true) {
1023 												msgTemplate = lang.getString("HeadlessAdminRequiresMorePlayers",languageList[index]);
1024 											}
1025 					#ifdef WIN32
1026 											_snprintf(szBuf,4095,msgTemplate.c_str(),minHeadLessPlayersRequired);
1027 					#else
1028 											snprintf(szBuf,4095,msgTemplate.c_str(),minHeadLessPlayersRequired);
1029 					#endif
1030 											if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
1031 
1032 											string sMsg = szBuf;
1033 											bool echoLocal = lang.isLanguageLocal(languageList[index]);
1034 											this->serverInterface->sendTextMessage(sMsg,-1, echoLocal, languageList[index], this->getPlayerIndex());
1035 								    	}
1036 									}
1037 									else {
1038 										if(this->joinGameInProgress == false) {
1039 											GameSettings gameSettingsBuffer;
1040 											networkMessageLaunch.buildGameSettings(&gameSettingsBuffer);
1041 
1042 											//printf("Connection slot got networkMessageLaunch.getMessageType() = %d, got map [%s]\n",networkMessageLaunch.getMessageType(),gameSettings.getMap().c_str());
1043 											//printf("\n\n\n\n=====Connection slot got settings:\n%s\n",gameSettings.toString().c_str());
1044 
1045 											this->serverInterface->broadcastGameSetup(&gameSettingsBuffer, true);
1046 										}
1047 
1048 										if(this->joinGameInProgress == false &&
1049 											networkMessageLaunch.getMessageType() == nmtLaunch) {
1050 
1051 											this->serverInterface->setMasterserverAdminRequestLaunch(true);
1052 										}
1053 										else if(this->joinGameInProgress == true &&
1054 												networkMessageLaunch.getMessageType() == nmtLaunch) {
1055 											//printf("!!! setStartInGameConnectionLaunch for client joinGameInProgress = %d!\n",joinGameInProgress);
1056 
1057 											int factionIndex = this->serverInterface->gameSettings.getFactionIndexForStartLocation(playerIndex);
1058 											this->serverInterface->gameSettings.setFactionControl(factionIndex,ctNetwork);
1059 											this->serverInterface->gameSettings.setNetworkPlayerName(factionIndex,this->name);
1060 											this->serverInterface->gameSettings.setNetworkPlayerUUID(factionIndex,this->playerUUID);
1061 											this->serverInterface->gameSettings.setNetworkPlayerPlatform(factionIndex,this->platform);
1062 
1063 											if(this->serverInterface->gameSettings.getNetworkPlayerStatuses(factionIndex) == npst_Disconnected) {
1064 												this->serverInterface->gameSettings.setNetworkPlayerStatuses(factionIndex,npst_None);
1065 											}
1066 
1067 											this->serverInterface->broadcastGameSetup(&this->serverInterface->gameSettings, true);
1068 
1069 											this->setStartInGameConnectionLaunch(true);
1070 										}
1071 									}
1072 								}
1073 								else {
1074 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1075 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1076 									close();
1077 									return;
1078 								}
1079 				        	}
1080 							else {
1081 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1082 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1083 								close();
1084 								return;
1085 							}
1086 				        }
1087 				        break;
1088 
1089 						//process datasynch messages
1090 						case nmtSynchNetworkGameDataStatus:
1091 						{
1092 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtSynchNetworkGameDataStatus, gotIntro = %d\n",__FILE__,__FUNCTION__,__LINE__,gotIntro);
1093 
1094 							if(gotIntro == true) {
1095 								if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1096 
1097 								NetworkMessageSynchNetworkGameDataStatus networkMessageSynchNetworkGameDataStatus;
1098 								if(receiveMessage(&networkMessageSynchNetworkGameDataStatus)) {
1099 									this->setNetworkGameDataSynchCheckTechMismatchReport("");
1100 									this->setReceivedDataSynchCheck(false);
1101 
1102 									Config &config = Config::getInstance();
1103 									string scenarioDir = "";
1104 									if(serverInterface->getGameSettings()->getScenarioDir() != "") {
1105 										scenarioDir = serverInterface->getGameSettings()->getScenarioDir();
1106 										if(EndsWith(scenarioDir, ".xml") == true) {
1107 											scenarioDir = scenarioDir.erase(scenarioDir.size() - 4, 4);
1108 											scenarioDir = scenarioDir.erase(scenarioDir.size() - serverInterface->getGameSettings()->getScenario().size(), serverInterface->getGameSettings()->getScenario().size() + 1);
1109 										}
1110 
1111 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getGameSettings()->getScenarioDir().c_str(),serverInterface->getGameSettings()->getScenario().c_str(),scenarioDir.c_str());
1112 									}
1113 
1114 									//tileset
1115 									uint32 tilesetCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + serverInterface->getGameSettings()->getTileset() + string("/*"), ".xml", NULL);
1116 									uint32 techCRC    = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,scenarioDir), "/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL);
1117 									Checksum checksum;
1118 									string file = Config::getMapPath(serverInterface->getGameSettings()->getMap(),scenarioDir,false);
1119 									checksum.addFile(file);
1120 									uint32 mapCRC = checksum.getSum();
1121 
1122 									networkGameDataSynchCheckOkMap      = (networkMessageSynchNetworkGameDataStatus.getMapCRC() == mapCRC);
1123 									networkGameDataSynchCheckOkTile     = (networkMessageSynchNetworkGameDataStatus.getTilesetCRC() == tilesetCRC);
1124 									networkGameDataSynchCheckOkTech     = (networkMessageSynchNetworkGameDataStatus.getTechCRC()    == techCRC);
1125 
1126 									// For testing
1127 									//techCRC++;
1128 
1129 									if( networkGameDataSynchCheckOkMap      == true &&
1130 										networkGameDataSynchCheckOkTile     == true &&
1131 										networkGameDataSynchCheckOkTech     == true) {
1132 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] client data synch ok\n",__FILE__,__FUNCTION__);
1133 									}
1134 									else {
1135 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] mapCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameDataStatus.getMapCRC());
1136 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] tilesetCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameDataStatus.getTilesetCRC());
1137 										if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] techCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameDataStatus.getTechCRC());
1138 
1139 										if(allowDownloadDataSynch == true) {
1140 											// Now get all filenames with their CRC values and send to the client
1141 											vctFileList.clear();
1142 
1143 											Config &config = Config::getInstance();
1144 											string scenarioDir = "";
1145 											if(serverInterface->getGameSettings()->getScenarioDir() != "") {
1146 												scenarioDir = serverInterface->getGameSettings()->getScenarioDir();
1147 												if(EndsWith(scenarioDir, ".xml") == true) {
1148 													scenarioDir = scenarioDir.erase(scenarioDir.size() - 4, 4);
1149 													scenarioDir = scenarioDir.erase(scenarioDir.size() - serverInterface->getGameSettings()->getScenario().size(), serverInterface->getGameSettings()->getScenario().size() + 1);
1150 												}
1151 
1152 												if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getGameSettings()->getScenarioDir().c_str(),serverInterface->getGameSettings()->getScenario().c_str(),scenarioDir.c_str());
1153 											}
1154 
1155 											if(networkGameDataSynchCheckOkTile == false) {
1156 												if(tilesetCRC == 0) {
1157 													vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + serverInterface->getGameSettings()->getTileset() + string("/*"), "", &vctFileList);
1158 												}
1159 												else {
1160 													vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTilesets,scenarioDir), "/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList);
1161 												}
1162 											}
1163 											if(networkGameDataSynchCheckOkTech == false) {
1164 												if(techCRC == 0) {
1165 													vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList);
1166 												}
1167 												else {
1168 													vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList);
1169 												}
1170 
1171 												string report = networkMessageSynchNetworkGameDataStatus.getTechCRCFileMismatchReport(serverInterface->getGameSettings()->getTech(),vctFileList);
1172 												this->setNetworkGameDataSynchCheckTechMismatchReport(report);
1173 											}
1174 											if(networkGameDataSynchCheckOkMap == false) {
1175 												vctFileList.push_back(std::pair<string,uint32>(Config::getMapPath(serverInterface->getGameSettings()->getMap(),scenarioDir,false),mapCRC));
1176 											}
1177 
1178 											NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck((int)vctFileList.size(), 1, vctFileList[0].second, vctFileList[0].first);
1179 											sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck);
1180 										}
1181 										else {
1182 											if(networkGameDataSynchCheckOkTech == false) {
1183 												vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL);
1184 
1185 												string report = networkMessageSynchNetworkGameDataStatus.getTechCRCFileMismatchReport(serverInterface->getGameSettings()->getTech(),vctFileList);
1186 												this->setNetworkGameDataSynchCheckTechMismatchReport(report);
1187 											}
1188 										}
1189 									}
1190 
1191 									this->setReceivedDataSynchCheck(true);
1192 									receivedNetworkGameStatus = true;
1193 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1194 								}
1195 								else {
1196 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1197 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1198 									close();
1199 									return;
1200 								}
1201 							}
1202 							else {
1203 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1204 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1205 								close();
1206 								return;
1207 							}
1208 						}
1209 						break;
1210 
1211 						case nmtSynchNetworkGameDataFileCRCCheck:
1212 						{
1213 
1214 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck\n",__FILE__,__FUNCTION__);
1215 
1216 							if(gotIntro == true) {
1217 								NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck;
1218 								if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck))
1219 								{
1220 									int fileIndex = networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex();
1221 									NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck((int)vctFileList.size(), fileIndex, vctFileList[fileIndex-1].second, vctFileList[fileIndex-1].first);
1222 									sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck);
1223 								}
1224 								else {
1225 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1226 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1227 									close();
1228 									return;
1229 								}
1230 							}
1231 							else {
1232 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1233 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1234 								close();
1235 								return;
1236 							}
1237 						}
1238 						break;
1239 
1240 						case nmtSynchNetworkGameDataFileGet:
1241 						{
1242 
1243 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataFileGet\n",__FILE__,__FUNCTION__);
1244 
1245 							if(gotIntro == true) {
1246 								NetworkMessageSynchNetworkGameDataFileGet networkMessageSynchNetworkGameDataFileGet;
1247 								if(receiveMessage(&networkMessageSynchNetworkGameDataFileGet)) {
1248 									FileTransferInfo fileInfo;
1249 									fileInfo.hostType   = eServer;
1250 									//fileInfo.serverIP   = this->ip.getString();
1251 									fileInfo.serverPort = Config::getInstance().getInt("PortServer",intToStr(GameConstants::serverPort).c_str());
1252 									fileInfo.fileName   = networkMessageSynchNetworkGameDataFileGet.getFileName();
1253 
1254 									FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo);
1255 									fileXferThread->start();
1256 								}
1257 								else {
1258 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1259 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1260 									close();
1261 									return;
1262 								}
1263 							}
1264 							else {
1265 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1266 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1267 								close();
1268 								return;
1269 							}
1270 						}
1271 						break;
1272 
1273 						case nmtSwitchSetupRequest:
1274 						{
1275 							//printf("Got nmtSwitchSetupRequest A gotIntro = %d\n",gotIntro);
1276 							if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtSwitchSetupRequest gotIntro = %d\n",__FILE__,__FUNCTION__,__LINE__,gotIntro);
1277 
1278 							if(gotIntro == true) {
1279 								//printf("Got nmtSwitchSetupRequest B\n");
1280 
1281 								SwitchSetupRequest switchSetupRequest;
1282 								if(receiveMessage(&switchSetupRequest)) {
1283 									MutexSafeWrapper safeMutex(getServerSynchAccessor(),CODE_AT_LINE);
1284 
1285 									int slotIdx = switchSetupRequest.getCurrentSlotIndex();
1286 									//int newSlotIdx = switchSetupRequest.getToSlotIndex();
1287 									//printf("slotIdx = %d newSlotIdx = %d\n",slotIdx,newSlotIdx);
1288 
1289 									if(serverInterface->getSwitchSetupRequests(slotIdx) == NULL) {
1290 										serverInterface->setSwitchSetupRequests(slotIdx,new SwitchSetupRequest());
1291 									}
1292 									*(serverInterface->getSwitchSetupRequests(slotIdx)) = switchSetupRequest;
1293 
1294 									//printf("slotIdx = %d newSlotIdx = %d\n",serverInterface->getSwitchSetupRequests(slotIdx)->getCurrentSlotIndex(),serverInterface->getSwitchSetupRequests(slotIdx)->getToSlotIndex());
1295 
1296 									this->playerStatus = switchSetupRequest.getNetworkPlayerStatus();
1297 									this->name = switchSetupRequest.getNetworkPlayerName();
1298 									this->playerLanguage = switchSetupRequest.getNetworkPlayerLanguage();
1299 
1300 									//printf("Got nmtSwitchSetupRequest C\n");
1301 									//printf("In [%s::%s Line %d] networkPlayerName [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getSwitchSetupRequests()[factionIdx]->getNetworkPlayerName().c_str());
1302 
1303 									if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] networkPlayerName [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getSwitchSetupRequests()[slotIdx]->getNetworkPlayerName().c_str());
1304 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] factionIdx = %d, switchSetupRequest.getNetworkPlayerName() [%s] switchSetupRequest.getNetworkPlayerStatus() = %d, switchSetupRequest.getSwitchFlags() = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIdx,switchSetupRequest.getNetworkPlayerName().c_str(),switchSetupRequest.getNetworkPlayerStatus(),switchSetupRequest.getSwitchFlags());
1305 								}
1306 								else {
1307 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1308 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1309 									close();
1310 									return;
1311 								}
1312 							}
1313 							else {
1314 								if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1315 								this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1316 								close();
1317 								return;
1318 							}
1319 
1320 							break;
1321 						}
1322 
1323 						case nmtReady:
1324 						{
1325 							NetworkMessageReady networkMessageReady;
1326 						    this->receiveMessage(&networkMessageReady);
1327 
1328 							// its simply ignored here. Probably we are starting a game
1329 							//printf("Got ready message from client slot joinGameInProgress = %d\n",joinGameInProgress);
1330 							if(joinGameInProgress == true) {
1331 								NetworkMessageReady networkMessageReady(0);
1332 								this->sendMessage(&networkMessageReady);
1333 								this->setGameStarted(true);
1334 
1335 								this->currentFrameCount = serverInterface->getCurrentFrameCount();
1336 								//printf("#2 Server slot got currentFrameCount = %d\n",currentFrameCount);
1337 
1338 								this->currentLagCount = 0;
1339 								this->lastReceiveCommandListTime = time(NULL);
1340 
1341 								this->setReady();
1342 							}
1343 							// unpause the game
1344 							else {
1345 								this->setUnPauseForInGameConnection(true);
1346 							}
1347 							break;
1348 						}
1349 			            case nmtLoadingStatusMessage:
1350 			                break;
1351 
1352 						default:
1353 							{
1354 								if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] networkMessageType = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageType);
1355 
1356 								if(gotIntro == true) {
1357 									//throw megaglest_runtime_error("Unexpected message in connection slot: " + intToStr(networkMessageType));
1358 									string sErr = "Unexpected message in connection slot: " + intToStr(networkMessageType);
1359 									//sendTextMessage(sErr,-1);
1360 									//DisplayErrorMessage(sErr);
1361 									threadErrorList.push_back(sErr);
1362 									return;
1363 								}
1364 								else {
1365 									if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got invalid message type before intro, disconnecting socket.\n",__FILE__,__FUNCTION__,__LINE__);
1366 
1367 									if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
1368 									this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress());
1369 									close();
1370 									return;
1371 								}
1372 							}
1373 					}
1374 
1375 					//printf("#3 Server slot got currentFrameCount = %d\n",currentFrameCount);
1376 
1377 					// This may end up continuously lagging and not disconnecting players who have
1378 					// just the 'wrong' amount of lag (but not enough to be horrible for a disconnect)
1379 					if(Config::getInstance().getBool("AutoClientLagCorrection","true") == true) {
1380 						double LAG_CHECK_GRACE_PERIOD 		= 15;
1381 
1382 						//printf("#4 Server slot got currentFrameCount = %d\n",currentFrameCount);
1383 
1384 						if(this->serverInterface->getGameStartTime() > 0 &&
1385 								difftime((long int)time(NULL),this->serverInterface->getGameStartTime()) >= LAG_CHECK_GRACE_PERIOD &&
1386 								difftime((long int)time(NULL),this->getConnectedTime()) >= LAG_CHECK_GRACE_PERIOD) {
1387 							if(this->isConnected() == true && this->gotIntro == true && this->skipLagCheck == false) {
1388 								double clientLag = this->serverInterface->getCurrentFrameCount() - this->getCurrentFrameCount();
1389 								double clientLagCount = (gameSettings.getNetworkFramePeriod() > 0 ? (clientLag / gameSettings.getNetworkFramePeriod()) : 0);
1390 								double clientLagTime = difftime((long int)time(NULL),this->getLastReceiveCommandListTime());
1391 
1392 								double maxFrameCountLagAllowed 		= 10;
1393 								double maxClientLagTimeAllowed 		= 8;
1394 
1395 								// New lag check
1396 								if((maxFrameCountLagAllowed > 0 && clientLagCount > maxFrameCountLagAllowed) ||
1397 									(maxClientLagTimeAllowed > 0 && clientLagTime > maxClientLagTimeAllowed)) {
1398 
1399 									waitForLaggingClient = true;
1400 									if(waitedForLaggingClient == false) {
1401 										waitedForLaggingClient = true;
1402 										printf("*TESTING*: START Waiting for lagging client playerIndex = %d [%s] clientLagCount = %f [%f]\n",playerIndex,name.c_str(),clientLagCount,clientLagTime);
1403 									}
1404 								}
1405 							}
1406 						}
1407 
1408 						//printf("#5 Server slot got currentFrameCount = %d\n",currentFrameCount);
1409 					}
1410 					//printf("#5a Server slot got currentFrameCount = %d\n",currentFrameCount);
1411 				}
1412 
1413 				//printf("#6 Server slot got currentFrameCount = %d\n",currentFrameCount);
1414 
1415 				if(waitedForLaggingClient == true) {
1416 					printf("*TESTING*: FINISHED Waiting for lagging client playerIndex = %d [%s]\n",playerIndex,name.c_str());
1417 				}
1418 
1419 				//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1420 
1421 				validateConnection();
1422 
1423 				//printf("#7 Server slot got currentFrameCount = %d\n",currentFrameCount);
1424 
1425 				//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1426 			}
1427 			else {
1428 				if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] calling close...\n",__FILE__,__FUNCTION__,__LINE__);
1429 
1430 				//printf("Closing connection slot socketInfo.first = %d\n",socketInfo.first);
1431 
1432 				close();
1433 
1434 				//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1435 			}
1436 
1437 			if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1438 		}
1439 	}
1440 	catch(const exception &ex) {
1441 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
1442 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error detected [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
1443 
1444 		threadErrorList.push_back(ex.what());
1445 
1446 		//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1447 	}
1448 
1449 	//printf("#8 Server slot got currentFrameCount = %d\n",currentFrameCount);
1450 	//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
1451 }
1452 
validateConnection()1453 void ConnectionSlot::validateConnection() {
1454 	if(this->isConnected() == true &&
1455 		gotIntro == false && connectedTime > 0 &&
1456 		difftime((long int)time(NULL),connectedTime) > GameConstants::maxClientConnectHandshakeSecs) {
1457 
1458 		//printf("Closing connection slot timed out!\n");
1459 		close();
1460 	}
1461 }
1462 
resetJoinGameInProgressFlags()1463 void ConnectionSlot::resetJoinGameInProgressFlags() {
1464 	this->gotIntro 				= false;
1465 	this->skipLagCheck 			= false;
1466 	this->joinGameInProgress 	= false;
1467 	this->ready					= false;
1468 }
1469 
setJoinGameInProgressFlags()1470 void ConnectionSlot::setJoinGameInProgressFlags() {
1471 	this->gotIntro 				= true;
1472 	this->skipLagCheck 			= true;
1473 	this->joinGameInProgress 	= true;
1474 	this->ready					= false;
1475 	this->sentSavedGameInfo 	= false;
1476 }
1477 
close()1478 void ConnectionSlot::close() {
1479 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s LINE: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1480 
1481 	//printf("Closing slot for playerIndex = %d\n",playerIndex);
1482 	//if(serverInterface->getAllowInGameConnections() == true) {
1483 		//printf("Closing connection slot!\n");
1484 	//}
1485 	//printf("ConnectionSlot::close() #1 this->getSocket() = %p\n",this->getSocket());
1486 
1487 	this->gotIntro 						= false;
1488 	this->skipLagCheck 					= false;
1489 	this->joinGameInProgress 			= false;
1490 	this->sentSavedGameInfo 			= false;
1491 	this->pauseForInGameConnection 		= false;
1492 	this->unPauseForInGameConnection 	= false;
1493 	this->ready							= false;
1494 	this->connectedTime 				= 0;
1495 
1496 	if(this->slotThreadWorker != NULL) {
1497 		if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1498         this->slotThreadWorker->setAllEventsCompleted();
1499         if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1500 	}
1501 
1502 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1503 
1504 	//printf("ConnectionSlot::close() #2 this->getSocket() = %p\n",this->getSocket());
1505 
1506 	MutexSafeWrapper safeMutex(mutexCloseConnection,CODE_AT_LINE);
1507 	bool updateServerListener = (this->getSocket() != NULL);
1508 
1509 	//printf("ConnectionSlot::close() #3 this->getSocket() = %p updateServerListener = %d\n",this->getSocket(),updateServerListener);
1510 
1511 	this->deleteSocket();
1512 	safeMutex.ReleaseLock();
1513 
1514 	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s LINE: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1515 	//printf("Closing slot for playerIndex = %d updateServerListener = %d ready = %d\n",playerIndex,updateServerListener,ready);
1516 
1517     if(updateServerListener == true) {
1518     	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s LINE: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1519     	serverInterface->updateListen();
1520     }
1521 
1522     if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
1523 }
1524 
getServerSynchAccessor()1525 Mutex * ConnectionSlot::getServerSynchAccessor() {
1526 	return (serverInterface != NULL ? serverInterface->getServerSynchAccessor() : NULL);
1527 }
1528 
signalUpdate(ConnectionSlotEvent * event)1529 void ConnectionSlot::signalUpdate(ConnectionSlotEvent *event) {
1530     if(slotThreadWorker != NULL) {
1531         slotThreadWorker->signalUpdate(event);
1532     }
1533 }
1534 
updateCompleted(ConnectionSlotEvent * event)1535 bool ConnectionSlot::updateCompleted(ConnectionSlotEvent *event) {
1536 	bool waitingForThread = (slotThreadWorker != NULL &&
1537 							 slotThreadWorker->isSignalCompleted(event) == false &&
1538 							 slotThreadWorker->getQuitStatus() 		    == false &&
1539 							 slotThreadWorker->getRunningStatus() 	    == true);
1540 
1541 	return (waitingForThread == false);
1542 }
1543 
sendMessage(NetworkMessage * networkMessage)1544 void ConnectionSlot::sendMessage(NetworkMessage* networkMessage) {
1545 	MutexSafeWrapper safeMutex(socketSynchAccessor,CODE_AT_LINE);
1546 
1547 	// Skip text messages not intended for the players preferred language
1548 	NetworkMessageText *textMsg = dynamic_cast<NetworkMessageText *>(networkMessage);
1549 	if(textMsg != NULL) {
1550 		//printf("\n\n\n~~~ SERVER HAS NetworkMessageText target [%s] player [%s] msg[%s]\n\n\n",textMsg->getTargetLanguage().c_str(),this->getNetworkPlayerLanguage().c_str(), textMsg->getText().c_str());
1551 		if(textMsg->getTargetLanguage() != "" &&
1552 			textMsg->getTargetLanguage() != this->getNetworkPlayerLanguage()) {
1553 			return;
1554 		}
1555 	}
1556 
1557 	NetworkInterface::sendMessage(networkMessage);
1558 }
1559 
getHumanPlayerName(int index)1560 string ConnectionSlot::getHumanPlayerName(int index) {
1561 	return serverInterface->getHumanPlayerName(index);
1562 }
1563 
getPendingNetworkCommandList(bool clearList)1564 vector<NetworkCommand> ConnectionSlot::getPendingNetworkCommandList(bool clearList) {
1565 	vector<NetworkCommand> ret;
1566 	MutexSafeWrapper safeMutexSlot(mutexPendingNetworkCommandList,CODE_AT_LINE);
1567     if(vctPendingNetworkCommandList.empty() == false) {
1568     	ret = vctPendingNetworkCommandList;
1569 		if(clearList == true) {
1570 			vctPendingNetworkCommandList.clear();
1571 		}
1572     }
1573 
1574     return ret;
1575 }
1576 
clearPendingNetworkCommandList()1577 void ConnectionSlot::clearPendingNetworkCommandList() {
1578 	MutexSafeWrapper safeMutexSlot(mutexPendingNetworkCommandList,CODE_AT_LINE);
1579 	if(vctPendingNetworkCommandList.empty() == false) {
1580 		vctPendingNetworkCommandList.clear();
1581 	}
1582 }
1583 
hasValidSocketId()1584 bool ConnectionSlot::hasValidSocketId() {
1585     bool result = false;
1586     MutexSafeWrapper safeMutexSlot(mutexSocket,CODE_AT_LINE);
1587     if(socket != NULL && socket->getSocketId() > 0) {
1588     	result = true;
1589     }
1590 	return result;
1591 
1592 }
1593 
isConnected()1594 bool ConnectionSlot::isConnected() {
1595     bool result = false;
1596     MutexSafeWrapper safeMutexSlot(mutexSocket,CODE_AT_LINE);
1597     if(socket != NULL && socket->isConnected() == true) {
1598     	result = true;
1599     }
1600 	return result;
1601 }
1602 
getSocketId()1603 PLATFORM_SOCKET ConnectionSlot::getSocketId() {
1604 	PLATFORM_SOCKET result = 0;
1605 	MutexSafeWrapper safeMutexSlot(mutexSocket,CODE_AT_LINE);
1606 	if(socket != NULL) {
1607 		result = socket->getSocketId();
1608 	}
1609 	return result;
1610 }
1611 
getSocketInfo()1612 pair<bool,Socket*> ConnectionSlot::getSocketInfo()	{
1613 	pair<bool,Socket*> result;
1614 	MutexSafeWrapper safeMutexSlot(mutexSocket,CODE_AT_LINE);
1615 	result.first = (socket != NULL && socket->isConnected());
1616 	result.second = socket;
1617 
1618 	return result;
1619 
1620 }
1621 
getSocket(bool mutexLock)1622 Socket* ConnectionSlot::getSocket(bool mutexLock)	{
1623 	MutexSafeWrapper safeMutexSlot(NULL,CODE_AT_LINE);
1624 	if(mutexLock == true) {
1625 		safeMutexSlot.setMutex(mutexSocket,CODE_AT_LINE);
1626 	}
1627 	return socket;
1628 }
1629 
setSocket(Socket * newSocket)1630 void ConnectionSlot::setSocket(Socket *newSocket) {
1631 	MutexSafeWrapper safeMutexSlot(mutexSocket,CODE_AT_LINE);
1632 	socket = newSocket;
1633 }
1634 
deleteSocket()1635 void ConnectionSlot::deleteSocket() {
1636 	MutexSafeWrapper safeMutexSlot(mutexSocket,CODE_AT_LINE);
1637 	delete socket;
1638 	socket = NULL;
1639 }
1640 
hasDataToRead()1641 bool ConnectionSlot::hasDataToRead() {
1642     bool result = false;
1643 
1644     MutexSafeWrapper safeMutexSlot(mutexSocket,CODE_AT_LINE);
1645 	if(socket != NULL && socket->hasDataToRead() == true) {
1646 		result = true;
1647 	}
1648 
1649 	return result;
1650 }
1651 
1652 }}//end namespace
1653