2010-03-17 07:25:19 +01:00
// ==============================================================
// This file is part of Glest (www.glest.org)
//
2011-12-14 08:40:48 +01:00
// Copyright (C) 2001-2008 Martiño Figueroa
2010-03-17 07:25:19 +01:00
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
# include "server_interface.h"
# include <cassert>
# include <stdexcept>
# include "platform_util.h"
# include "conversion.h"
# include "config.h"
# include "lang.h"
# include "logger.h"
# include <time.h>
2010-03-20 00:26:00 +01:00
# include "util.h"
2010-10-23 11:06:47 +02:00
# include "game_util.h"
2010-12-29 02:10:53 +01:00
# include "miniftpserver.h"
2011-01-20 09:19:14 +01:00
# include "window.h"
2011-10-12 08:54:36 +02:00
# include <set>
2011-12-05 06:26:48 +01:00
# include "map_preview.h"
2011-10-12 08:54:36 +02:00
2010-03-20 00:26:00 +01:00
# include "leak_dumper.h"
2010-03-17 07:25:19 +01:00
using namespace std ;
using namespace Shared : : Platform ;
using namespace Shared : : Util ;
2011-12-05 06:26:48 +01:00
using namespace Shared : : Map ;
2010-03-17 07:25:19 +01:00
2011-01-13 09:17:18 +01:00
namespace Glest { namespace Game {
2011-01-20 09:25:09 +01:00
double maxFrameCountLagAllowed = 25 ;
double maxClientLagTimeAllowed = 30 ;
2011-04-18 08:42:25 +02:00
double maxFrameCountLagAllowedEver = 35 ;
2011-05-16 08:32:06 +02:00
double maxClientLagTimeAllowedEver = 45 ;
2011-01-13 09:17:18 +01:00
double warnFrameCountLagPercent = 0.65 ;
double LAG_CHECK_GRACE_PERIOD = 15 ;
2011-02-16 05:43:27 +01:00
double MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE = 2 ;
2011-01-13 09:17:18 +01:00
const int MAX_SLOT_THREAD_WAIT_TIME = 3 ;
const int MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS = 30 ;
2011-03-11 13:14:24 +01:00
ServerInterface : : ServerInterface ( bool publishEnabled ) : GameNetworkInterface ( ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
2011-12-02 17:07:59 +01:00
serverSynchAccessor = new Mutex ( ) ;
for ( int i = 0 ; i < GameConstants : : maxPlayers ; + + i ) {
slotAccessorMutexes [ i ] = new Mutex ( ) ;
}
masterServerThreadAccessor = new Mutex ( ) ;
textMessageQueueThreadAccessor = new Mutex ( ) ;
broadcastMessageQueueThreadAccessor = new Mutex ( ) ;
inBroadcastMessageThreadAccessor = new Mutex ( ) ;
2011-01-13 09:17:18 +01:00
nextEventId = 1 ;
gameHasBeenInitiated = false ;
exitServer = false ;
gameSettingsUpdateCount = 0 ;
currentFrameCount = 0 ;
gameStartTime = 0 ;
publishToMasterserverThread = NULL ;
lastMasterserverHeartbeatTime = 0 ;
needToRepublishToMasterserver = false ;
ftpServer = NULL ;
inBroadcastMessage = false ;
2011-05-18 23:14:14 +02:00
lastGlobalLagCheckTime = 0 ;
2011-09-24 09:46:56 +02:00
masterserverAdminRequestLaunch = false ;
2011-01-13 09:17:18 +01:00
maxFrameCountLagAllowed = Config : : getInstance ( ) . getInt ( " MaxFrameCountLagAllowed " , intToStr ( maxFrameCountLagAllowed ) . c_str ( ) ) ;
maxFrameCountLagAllowedEver = Config : : getInstance ( ) . getInt ( " MaxFrameCountLagAllowedEver " , intToStr ( maxFrameCountLagAllowedEver ) . c_str ( ) ) ;
2011-05-16 08:32:06 +02:00
maxClientLagTimeAllowedEver = Config : : getInstance ( ) . getInt ( " MaxClientLagTimeAllowedEver " , intToStr ( maxClientLagTimeAllowedEver ) . c_str ( ) ) ;
2011-01-13 09:17:18 +01:00
maxClientLagTimeAllowed = Config : : getInstance ( ) . getInt ( " MaxClientLagTimeAllowed " , intToStr ( maxClientLagTimeAllowed ) . c_str ( ) ) ;
warnFrameCountLagPercent = Config : : getInstance ( ) . getFloat ( " WarnFrameCountLagPercent " , doubleToStr ( warnFrameCountLagPercent ) . c_str ( ) ) ;
2011-05-16 08:32:06 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] maxFrameCountLagAllowed = %f, maxFrameCountLagAllowedEver = %f, maxClientLagTimeAllowed = %f, maxClientLagTimeAllowedEver = %f \n " , __FILE__ , __FUNCTION__ , __LINE__ , maxFrameCountLagAllowed , maxFrameCountLagAllowedEver , maxClientLagTimeAllowed , maxClientLagTimeAllowedEver ) ;
2011-01-13 09:17:18 +01:00
for ( int i = 0 ; i < GameConstants : : maxPlayers ; + + i ) {
slots [ i ] = NULL ;
switchSetupRequests [ i ] = NULL ;
2010-03-17 07:25:19 +01:00
}
2011-01-13 09:17:18 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
serverSocket . setBlock ( false ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
serverSocket . setBindPort ( Config : : getInstance ( ) . getInt ( " ServerPort " , intToStr ( GameConstants : : serverPort ) . c_str ( ) ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
2011-12-05 06:26:48 +01:00
/*
2011-10-12 08:54:36 +02:00
Config & config = Config : : getInstance ( ) ;
vector < string > results ;
set < string > allMaps ;
findAll ( config . getPathListForType ( ptMaps ) , " *.gbm " , results , true , false ) ;
copy ( results . begin ( ) , results . end ( ) , std : : inserter ( allMaps , allMaps . begin ( ) ) ) ;
results . clear ( ) ;
findAll ( config . getPathListForType ( ptMaps ) , " *.mgm " , results , true , false ) ;
copy ( results . begin ( ) , results . end ( ) , std : : inserter ( allMaps , allMaps . begin ( ) ) ) ;
results . clear ( ) ;
if ( allMaps . empty ( ) ) {
throw runtime_error ( " No maps were found! " ) ;
}
copy ( allMaps . begin ( ) , allMaps . end ( ) , std : : back_inserter ( results ) ) ;
mapFiles = results ;
2011-12-05 06:26:48 +01:00
*/
Config & config = Config : : getInstance ( ) ;
vector < string > results ;
string scenarioDir = " " ;
vector < string > pathList = config . getPathListForType ( ptMaps , scenarioDir ) ;
vector < string > invalidMapList ;
vector < string > allMaps = MapPreview : : findAllValidMaps ( pathList , scenarioDir , false , true , & invalidMapList ) ;
if ( allMaps . empty ( ) ) {
throw runtime_error ( " No maps were found! " ) ;
}
results . clear ( ) ;
copy ( allMaps . begin ( ) , allMaps . end ( ) , std : : back_inserter ( results ) ) ;
mapFiles = results ;
2011-10-12 08:54:36 +02:00
//tileset listBox
results . clear ( ) ;
findDirs ( config . getPathListForType ( ptTilesets ) , results ) ;
if ( results . empty ( ) ) {
throw runtime_error ( " No tile-sets were found! " ) ;
}
tilesetFiles = results ;
//tech Tree listBox
results . clear ( ) ;
findDirs ( config . getPathListForType ( ptTechs ) , results ) ;
if ( results . empty ( ) ) {
throw runtime_error ( " No tech-trees were found! " ) ;
}
techTreeFiles = results ;
2011-01-13 09:17:18 +01:00
if ( Config : : getInstance ( ) . getBool ( " EnableFTPServer " , " true " ) = = true ) {
std : : pair < string , string > mapsPath ;
vector < string > pathList = Config : : getInstance ( ) . getPathListForType ( ptMaps ) ;
2011-09-01 03:11:23 +02:00
if ( pathList . empty ( ) = = false ) {
2011-01-13 09:17:18 +01:00
mapsPath . first = pathList [ 0 ] ;
if ( pathList . size ( ) > 1 ) {
mapsPath . second = pathList [ 1 ] ;
}
}
std : : pair < string , string > tilesetsPath ;
vector < string > tilesetsList = Config : : getInstance ( ) . getPathListForType ( ptTilesets ) ;
2011-09-01 03:11:23 +02:00
if ( tilesetsList . empty ( ) = = false ) {
2011-01-13 09:17:18 +01:00
tilesetsPath . first = tilesetsList [ 0 ] ;
if ( tilesetsList . size ( ) > 1 ) {
tilesetsPath . second = tilesetsList [ 1 ] ;
}
}
2011-03-10 00:09:32 +01:00
std : : pair < string , string > techtreesPath ;
vector < string > techtreesList = Config : : getInstance ( ) . getPathListForType ( ptTechs ) ;
2011-09-01 03:11:23 +02:00
if ( techtreesList . empty ( ) = = false ) {
2011-03-10 00:09:32 +01:00
techtreesPath . first = techtreesList [ 0 ] ;
if ( techtreesList . size ( ) > 1 ) {
techtreesPath . second = techtreesList [ 1 ] ;
}
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
int portNumber = Config : : getInstance ( ) . getInt ( " FTPServerPort " , intToStr ( ServerSocket : : getFTPServerPort ( ) ) . c_str ( ) ) ;
ServerSocket : : setFTPServerPort ( portNumber ) ;
2011-10-25 20:39:11 +02:00
//printf("In [%s::%s] portNumber = %d ServerSocket::getFTPServerPort() = %d\n",__FILE__,__FUNCTION__,__LINE__,portNumber,ServerSocket::getFTPServerPort());
2011-03-11 13:14:24 +01:00
bool allowInternetTilesetFileTransfers = Config : : getInstance ( ) . getBool ( " EnableFTPServerInternetTilesetXfer " , " true " ) ;
bool allowInternetTechtreeFileTransfers = Config : : getInstance ( ) . getBool ( " EnableFTPServerInternetTechtreeXfer " , " true " ) ;
2011-03-10 00:09:32 +01:00
ftpServer = new FTPServerThread ( mapsPath , tilesetsPath , techtreesPath ,
2011-03-11 13:14:24 +01:00
publishEnabled ,
allowInternetTilesetFileTransfers , allowInternetTechtreeFileTransfers ,
portNumber , GameConstants : : maxPlayers , this ) ;
2011-01-13 09:17:18 +01:00
ftpServer - > start ( ) ;
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
}
2011-03-11 13:14:24 +01:00
void ServerInterface : : setPublishEnabled ( bool value ) {
if ( ftpServer ! = NULL ) {
ftpServer - > setInternetEnabled ( value ) ;
}
}
2011-01-13 09:17:18 +01:00
ServerInterface : : ~ ServerInterface ( ) {
2011-11-23 09:00:09 +01:00
//printf("===> Destructor for ServerInterface\n");
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
exitServer = true ;
for ( int i = 0 ; i < GameConstants : : maxPlayers ; + + i ) {
2010-12-18 20:52:47 +01:00
if ( slots [ i ] ! = NULL ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
delete slots [ i ] ;
slots [ i ] = NULL ;
}
if ( switchSetupRequests [ i ] ! = NULL ) {
delete switchSetupRequests [ i ] ;
switchSetupRequests [ i ] = NULL ;
}
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
close ( ) ;
if ( ftpServer ! = NULL ) {
ftpServer - > shutdownAndWait ( ) ;
delete ftpServer ;
ftpServer = NULL ;
2010-03-17 07:25:19 +01:00
}
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( masterServerThreadAccessor , CODE_AT_LINE ) ;
2011-01-13 09:17:18 +01:00
delete publishToMasterserverThread ;
publishToMasterserverThread = NULL ;
safeMutex . ReleaseLock ( ) ;
2011-11-23 09:00:09 +01:00
2011-01-13 09:17:18 +01:00
lastMasterserverHeartbeatTime = 0 ;
if ( needToRepublishToMasterserver = = true ) {
2011-01-02 07:46:48 +01:00
simpleTask ( NULL ) ;
2010-10-24 07:52:21 +02:00
}
2011-12-02 17:07:59 +01:00
for ( int i = 0 ; i < GameConstants : : maxPlayers ; + + i ) {
delete slotAccessorMutexes [ i ] ;
slotAccessorMutexes [ i ] = NULL ;
}
delete textMessageQueueThreadAccessor ;
textMessageQueueThreadAccessor = NULL ;
delete broadcastMessageQueueThreadAccessor ;
broadcastMessageQueueThreadAccessor = NULL ;
delete inBroadcastMessageThreadAccessor ;
inBroadcastMessageThreadAccessor = NULL ;
delete serverSynchAccessor ;
serverSynchAccessor = NULL ;
delete masterServerThreadAccessor ;
masterServerThreadAccessor = NULL ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
}
2010-10-23 11:06:47 +02:00
2011-01-13 09:17:18 +01:00
int ServerInterface : : isValidClientType ( uint32 clientIp ) {
int result = 0 ;
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-01-07 07:21:23 +01:00
if ( slots [ i ] ! = NULL ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
Socket * socket = slots [ i ] - > getSocket ( ) ;
if ( socket ! = NULL ) {
uint32 slotIp = socket - > getConnectedIPAddress ( socket - > getIpAddress ( ) ) ;
if ( slotIp = = clientIp ) {
result = 1 ;
break ;
}
}
2011-01-07 07:21:23 +01:00
}
}
2011-01-13 09:17:18 +01:00
return result ;
}
2011-11-29 06:07:18 +01:00
int ServerInterface : : isClientAllowedToGetFile ( uint32 clientIp , const char * username , const char * filename ) {
int result = 1 ;
if ( username ! = NULL & & strlen ( username ) > 0 & & filename ! = NULL & & strlen ( filename ) > 0 ) {
string user = username ;
string file = filename ;
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d username [%s] file [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , username , filename ) ;
if ( StartsWith ( user , " tilesets " ) = = true & & EndsWith ( file , " 7z " ) = = false ) {
if ( Config : : getInstance ( ) . getBool ( " DisableFTPServerXferUncompressedTilesets " , " false " ) = = true ) {
result = 0 ;
}
else {
char szIP [ 100 ] = " " ;
Ip : : Inet_NtoA ( clientIp , szIP ) ;
string clientIP = szIP ;
//string serverIP = serverSocket.getIp();
std : : vector < std : : string > serverList = Socket : : getLocalIPAddressList ( ) ;
result = 0 ;
for ( unsigned int i = 0 ; i < serverList . size ( ) ; + + i ) {
string serverIP = serverList [ i ] ;
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d clientIP [%s] serverIP [%s] %d / %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , clientIP . c_str ( ) , serverIP . c_str ( ) , i , serverList . size ( ) ) ;
vector < string > clientTokens ;
Tokenize ( clientIP , clientTokens , " . " ) ;
vector < string > serverTokens ;
Tokenize ( serverIP , serverTokens , " . " ) ;
if ( clientTokens . size ( ) = = 4 & & serverTokens . size ( ) = = 4 ) {
if ( clientTokens [ 0 ] = = serverTokens [ 0 ] | |
clientTokens [ 1 ] = = serverTokens [ 1 ] | |
clientTokens [ 2 ] = = serverTokens [ 2 ] ) {
result = 1 ;
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d clientIP [%s] IS NOT BLOCKED \n " , __FILE__ , __FUNCTION__ , __LINE__ , clientIP . c_str ( ) ) ;
break ;
}
}
}
}
}
}
return result ;
}
2011-01-13 09:17:18 +01:00
void ServerInterface : : addClientToServerIPAddress ( uint32 clientIp , uint32 ServerIp ) {
FTPServerThread : : addClientToServerIPAddress ( clientIp , ServerIp ) ;
}
void ServerInterface : : addSlot ( int playerIndex ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
assert ( playerIndex > = 0 & & playerIndex < GameConstants : : maxPlayers ) ;
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( serverSynchAccessor , CODE_AT_LINE ) ;
2011-01-13 09:17:18 +01:00
if ( serverSocket . isPortBound ( ) = = false ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-06-24 03:23:18 +02:00
serverSocket . bind ( serverSocket . getBindPort ( ) ) ;
}
2011-01-13 09:17:18 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ playerIndex ] , CODE_AT_LINE_X ( playerIndex ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * slot = slots [ playerIndex ] ;
if ( slot ! = NULL ) {
slots [ playerIndex ] = NULL ;
}
slots [ playerIndex ] = new ConnectionSlot ( this , playerIndex ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-11-27 06:27:50 +01:00
safeMutexSlot . ReleaseLock ( ) ;
2011-01-13 09:17:18 +01:00
delete slot ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
safeMutex . ReleaseLock ( ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
updateListen ( ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
}
bool ServerInterface : : switchSlot ( int fromPlayerIndex , int toPlayerIndex ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
bool result = false ;
assert ( fromPlayerIndex > = 0 & & fromPlayerIndex < GameConstants : : maxPlayers ) ;
assert ( toPlayerIndex > = 0 & & toPlayerIndex < GameConstants : : maxPlayers ) ;
if ( fromPlayerIndex = = toPlayerIndex ) {
return false ;
}
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( serverSynchAccessor , CODE_AT_LINE ) ;
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ fromPlayerIndex ] , CODE_AT_LINE_X ( fromPlayerIndex ) ) ;
MutexSafeWrapper safeMutexSlot2 ( slotAccessorMutexes [ toPlayerIndex ] , CODE_AT_LINE_X ( toPlayerIndex ) ) ;
2011-01-25 23:43:39 +01:00
if ( slots [ toPlayerIndex ] ! = NULL & & slots [ toPlayerIndex ] ! = NULL & &
slots [ toPlayerIndex ] - > isConnected ( ) = = false ) {
2011-01-13 09:17:18 +01:00
slots [ fromPlayerIndex ] - > setPlayerIndex ( toPlayerIndex ) ;
slots [ toPlayerIndex ] - > setPlayerIndex ( fromPlayerIndex ) ;
ConnectionSlot * tmp = slots [ toPlayerIndex ] ;
slots [ toPlayerIndex ] = slots [ fromPlayerIndex ] ;
slots [ fromPlayerIndex ] = tmp ;
safeMutex . ReleaseLock ( ) ;
PlayerIndexMessage playerIndexMessage ( toPlayerIndex ) ;
slots [ toPlayerIndex ] - > sendMessage ( & playerIndexMessage ) ;
2011-11-27 06:27:50 +01:00
safeMutexSlot . ReleaseLock ( ) ;
safeMutexSlot2 . ReleaseLock ( ) ;
2011-01-13 09:17:18 +01:00
result = true ;
updateListen ( ) ;
}
else {
2011-11-27 06:27:50 +01:00
safeMutexSlot . ReleaseLock ( ) ;
safeMutexSlot2 . ReleaseLock ( ) ;
2011-01-13 09:17:18 +01:00
safeMutex . ReleaseLock ( ) ;
2011-01-10 22:00:55 +01:00
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
return result ;
}
void ServerInterface : : removeSlot ( int playerIndex , int lockedSlotIndex ) {
2011-04-05 20:39:47 +02:00
Lang & lang = Lang : : getInstance ( ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( serverSynchAccessor , CODE_AT_LINE ) ;
2011-11-27 06:27:50 +01:00
MutexSafeWrapper safeMutexSlot ( NULL , CODE_AT_LINE_X ( playerIndex ) ) ;
2011-01-13 09:17:18 +01:00
if ( playerIndex ! = lockedSlotIndex ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-12-02 17:07:59 +01:00
safeMutexSlot . setMutex ( slotAccessorMutexes [ playerIndex ] , CODE_AT_LINE_X ( playerIndex ) ) ;
2011-01-13 09:17:18 +01:00
}
ConnectionSlot * slot = slots [ playerIndex ] ;
bool notifyDisconnect = false ;
2011-04-05 20:39:47 +02:00
vector < string > msgList ;
const vector < string > languageList = this - > gameSettings . getUniqueNetworkPlayerLanguages ( ) ;
2011-01-13 09:17:18 +01:00
if ( slot ! = NULL ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-01-13 09:17:18 +01:00
if ( slot - > getLastReceiveCommandListTime ( ) > 0 ) {
2011-04-05 20:39:47 +02:00
char szBuf [ 4096 ] = " " ;
for ( unsigned int i = 0 ; i < languageList . size ( ) ; + + i ) {
string msgTemplate = " Player %s, disconnected from the game. " ;
if ( lang . hasString ( " PlayerDisconnected " , languageList [ i ] ) = = true ) {
msgTemplate = lang . get ( " PlayerDisconnected " , languageList [ i ] ) ;
}
2010-07-01 08:11:14 +02:00
# ifdef WIN32
2011-04-05 20:39:47 +02:00
_snprintf ( szBuf , 4095 , msgTemplate . c_str ( ) , slot - > getName ( ) . c_str ( ) ) ;
2010-07-01 08:11:14 +02:00
# else
2011-04-05 20:39:47 +02:00
snprintf ( szBuf , 4095 , msgTemplate . c_str ( ) , slot - > getName ( ) . c_str ( ) ) ;
2010-07-01 08:11:14 +02:00
# endif
2011-04-05 20:39:47 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] %s \n " , __FILE__ , __FUNCTION__ , __LINE__ , szBuf ) ;
msgList . push_back ( szBuf ) ;
}
2011-01-13 09:17:18 +01:00
notifyDisconnect = true ;
}
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-01-13 09:17:18 +01:00
slots [ playerIndex ] = NULL ;
2011-11-27 06:27:50 +01:00
safeMutexSlot . ReleaseLock ( ) ;
2011-01-13 09:17:18 +01:00
safeMutex . ReleaseLock ( ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-01-13 09:17:18 +01:00
delete slot ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-01-13 09:17:18 +01:00
updateListen ( ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-01-13 09:17:18 +01:00
if ( notifyDisconnect = = true ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-04-05 20:39:47 +02:00
//string sMsg = szBuf;
2011-01-11 23:09:46 +01:00
//sendTextMessage(sMsg,-1, true, lockedSlotIndex);
2011-04-05 20:39:47 +02:00
//const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
for ( unsigned int j = 0 ; j < languageList . size ( ) ; + + j ) {
bool localEcho = lang . isLanguageLocal ( languageList [ j ] ) ;
queueTextMessage ( msgList [ j ] , - 1 , localEcho , languageList [ j ] ) ;
2011-11-29 06:07:18 +01:00
//printf("j = %d [%s] localEcho = %d [%s]\n",j,msgList[j].c_str(),localEcho,languageList[j].c_str());
2011-04-05 20:39:47 +02:00
}
2010-07-01 08:11:14 +02:00
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , playerIndex , lockedSlotIndex ) ;
2011-01-13 09:17:18 +01:00
}
ConnectionSlot * ServerInterface : : getSlot ( int playerIndex ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ playerIndex ] , CODE_AT_LINE_X ( i ) ) ;
2011-11-25 10:12:53 +01:00
ConnectionSlot * result = slots [ playerIndex ] ;
return result ;
}
bool ServerInterface : : isClientConnected ( int index ) {
bool result = false ;
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ index ] , CODE_AT_LINE_X ( i ) ) ;
2011-11-25 10:12:53 +01:00
if ( slots [ index ] ! = NULL & & slots [ index ] - > isConnected ( ) = = true ) {
result = true ;
}
return result ;
2011-01-13 09:17:18 +01:00
}
bool ServerInterface : : hasClientConnection ( ) {
bool result = false ;
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-11-25 10:12:53 +01:00
if ( isClientConnected ( i ) = = true ) {
2010-05-17 08:41:05 +02:00
result = true ;
break ;
}
}
2011-01-13 09:17:18 +01:00
return result ;
}
int ServerInterface : : getConnectedSlotCount ( ) {
int connectedSlotCount = 0 ;
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2010-12-18 20:52:47 +01:00
if ( slots [ i ] ! = NULL ) {
2010-03-17 07:25:19 +01:00
+ + connectedSlotCount ;
}
}
2011-01-13 09:17:18 +01:00
return connectedSlotCount ;
}
int64 ServerInterface : : getNextEventId ( ) {
nextEventId + + ;
if ( nextEventId > INT_MAX ) {
nextEventId = 1 ;
}
return nextEventId ;
}
void ServerInterface : : slotUpdateTask ( ConnectionSlotEvent * event ) {
2011-11-23 09:00:09 +01:00
// if(event != NULL) {
// if(event->eventType == eSendSocketData) {
// if(event->connectionSlot != NULL) {
// event->connectionSlot->sendMessage(event->networkMessage);
// }
// }
// else if(event->eventType == eReceiveSocketData) {
// //updateSlot(event);
// if(event->connectionSlot != NULL) {
// event->connectionSlot->updateSlot(event);
// }
// }
// else {
// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// }
// }
2011-01-13 09:17:18 +01:00
}
2010-05-15 20:59:17 +02:00
2011-11-23 09:00:09 +01:00
//void ServerInterface::updateSlot(ConnectionSlotEvent *event) {
// Chrono chrono;
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
//
// if(event != NULL) {
// bool &socketTriggered = event->socketTriggered;
// bool checkForNewClients = true;
//
// // Safety check since we can experience a disconnect and the slot is NULL
// ConnectionSlot *connectionSlot = NULL;
// MutexSafeWrapper safeMutexSlot(NULL);
// if(event->triggerId >= 0 && event->triggerId < GameConstants::maxPlayers) {
//
// //printf("===> START slot %d [%d][%p] - About to updateSlot\n",event->triggerId,event->eventId,slots[event->triggerId]);
//
2011-12-02 17:07:59 +01:00
// safeMutexSlot.setMutex(slotAccessorMutexes[event->triggerId],CODE_AT_LINE_X(event->triggerId));
2011-11-23 09:00:09 +01:00
// connectionSlot = slots[event->triggerId];
// }
// else {
// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR CONDITION, event->triggerId = %d\n",__FILE__,__FUNCTION__,__LINE__,event->triggerId);
// SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] ERROR CONDITION, event->triggerId = %d\n",__FILE__,__FUNCTION__,__LINE__,event->triggerId);
// }
//
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//
// //if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] MUTEX LOCK held for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
//
// if(connectionSlot != NULL &&
// (gameHasBeenInitiated == false ||
// (connectionSlot->getSocket() != NULL && socketTriggered == true))) {
// if(connectionSlot->isConnected() == false || socketTriggered == true) {
// //if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] MUTEX LOCK held for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
//
// //safeMutexSlot.ReleaseLock(true);
// connectionSlot->update(checkForNewClients,event->triggerId);
//
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//
// //chrono.start();
// //safeMutexSlot.Lock();
// //connectionSlot = slots[event->triggerId];
//
// //if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] MUTEX LOCK held for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
//
// // This means no clients are trying to connect at the moment
// if(connectionSlot != NULL && connectionSlot->getSocket() == NULL) {
// checkForNewClients = false;
// }
// }
// //if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] MUTEX LOCK held for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
// }
// safeMutexSlot.ReleaseLock();
//
// if(event->triggerId >= 0 && event->triggerId < GameConstants::maxPlayers) {
// //printf("===> END slot %d - About to updateSlot\n",event->triggerId);
// }
// }
// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//}
2011-01-13 09:17:18 +01:00
std : : pair < bool , bool > ServerInterface : : clientLagCheck ( ConnectionSlot * connectionSlot , bool skipNetworkBroadCast ) {
2011-02-21 02:34:31 +01:00
Chrono chrono ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled ) chrono . start ( ) ;
2011-02-21 02:34:31 +01:00
2011-01-13 09:17:18 +01:00
std : : pair < bool , bool > clientLagExceededOrWarned = std : : make_pair ( false , false ) ;
static bool alreadyInLagCheck = false ;
2011-05-18 23:14:14 +02:00
// {
// if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
// double clientLag = this->getCurrentFrameCount() - connectionSlot->getCurrentFrameCount();
// double clientLagCount = (gameSettings.getNetworkFramePeriod() > 0 ? (clientLag / gameSettings.getNetworkFramePeriod()) : 0);
// double clientLagTime = difftime(time(NULL),connectionSlot->getLastReceiveCommandListTime());
//
// printf("\n\nmaxClientLagTimeAllowedEver [%f] - [%f] alreadyInLagCheck = %d\n\n",maxClientLagTimeAllowedEver,clientLagTime,alreadyInLagCheck);
// }
// }
2011-01-13 09:17:18 +01:00
if ( alreadyInLagCheck = = true ) {
return clientLagExceededOrWarned ;
2010-05-15 20:59:17 +02:00
}
2011-01-13 09:17:18 +01:00
try {
2010-07-01 08:11:14 +02:00
alreadyInLagCheck = true ;
if ( difftime ( time ( NULL ) , gameStartTime ) > = LAG_CHECK_GRACE_PERIOD ) {
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) = = true ) {
double clientLag = this - > getCurrentFrameCount ( ) - connectionSlot - > getCurrentFrameCount ( ) ;
double clientLagCount = ( gameSettings . getNetworkFramePeriod ( ) > 0 ? ( clientLag / gameSettings . getNetworkFramePeriod ( ) ) : 0 ) ;
connectionSlot - > setCurrentLagCount ( clientLagCount ) ;
double clientLagTime = difftime ( time ( NULL ) , connectionSlot - > getLastReceiveCommandListTime ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-21 02:34:31 +01:00
2010-07-01 08:11:14 +02:00
if ( this - > getCurrentFrameCount ( ) > 0 ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] playerIndex = %d, clientLag = %f, clientLagCount = %f, this->getCurrentFrameCount() = %d, connectionSlot->getCurrentFrameCount() = %d, clientLagTime = %f \n " ,
2011-01-13 09:17:18 +01:00
__FILE__ , __FUNCTION__ , __LINE__ ,
connectionSlot - > getPlayerIndex ( ) ,
clientLag , clientLagCount ,
this - > getCurrentFrameCount ( ) ,
connectionSlot - > getCurrentFrameCount ( ) ,
clientLagTime ) ;
2010-06-28 02:21:12 +02:00
}
2010-07-01 08:11:14 +02:00
// TEST LAG Error and warnings!!!
//clientLagCount = maxFrameCountLagAllowed + 1;
//clientLagTime = maxClientLagTimeAllowed + 1;
/*
if ( difftime ( time ( NULL ) , gameStartTime ) > = LAG_CHECK_GRACE_PERIOD + 5 ) {
clientLagTime = maxClientLagTimeAllowed + 1 ;
2010-06-28 02:21:12 +02:00
}
2010-07-01 08:11:14 +02:00
else if ( difftime ( time ( NULL ) , gameStartTime ) > = LAG_CHECK_GRACE_PERIOD ) {
clientLagTime = ( maxClientLagTimeAllowed * warnFrameCountLagPercent ) + 1 ;
}
*/
// END test
2010-06-28 02:21:12 +02:00
2011-05-18 23:14:14 +02:00
2010-07-01 08:11:14 +02:00
// New lag check
if ( ( maxFrameCountLagAllowed > 0 & & clientLagCount > maxFrameCountLagAllowed ) | |
2010-08-27 20:53:59 +02:00
( maxClientLagTimeAllowed > 0 & & clientLagTime > maxClientLagTimeAllowed ) | |
2011-05-18 23:14:14 +02:00
( maxFrameCountLagAllowedEver > 0 & & clientLagCount > maxFrameCountLagAllowedEver ) | |
( maxClientLagTimeAllowedEver > 0 & & clientLagTime > maxClientLagTimeAllowedEver ) ) {
2010-07-29 07:51:50 +02:00
clientLagExceededOrWarned . first = true ;
2010-06-30 09:03:04 +02:00
2011-04-05 20:39:47 +02:00
Lang & lang = Lang : : getInstance ( ) ;
const vector < string > languageList = this - > gameSettings . getUniqueNetworkPlayerLanguages ( ) ;
for ( unsigned int i = 0 ; i < languageList . size ( ) ; + + i ) {
char szBuf [ 4096 ] = " " ;
string msgTemplate = " DROPPING %s, exceeded max allowed LAG count of %f [time = %f], clientLag = %f [%f], disconnecting client. " ;
if ( lang . hasString ( " ClientLagDropping " ) = = true ) {
msgTemplate = lang . get ( " ClientLagDropping " , languageList [ i ] ) ;
}
if ( gameSettings . getNetworkPauseGameForLaggedClients ( ) = = true & &
2011-05-18 23:14:14 +02:00
( ( maxFrameCountLagAllowedEver < = 0 | | clientLagCount < = maxFrameCountLagAllowedEver ) & &
( maxClientLagTimeAllowedEver < = 0 | | clientLagTime < = maxClientLagTimeAllowedEver ) ) ) {
2011-04-05 20:39:47 +02:00
msgTemplate = " PAUSING GAME TEMPORARILY for %s, exceeded max allowed LAG count of %f [time = %f], clientLag = %f [%f], waiting for client to catch up... " ;
if ( lang . hasString ( " ClientLagPausing " ) = = true ) {
msgTemplate = lang . get ( " ClientLagPausing " , languageList [ i ] ) ;
}
}
2011-01-13 09:17:18 +01:00
# ifdef WIN32
2011-04-05 20:39:47 +02:00
_snprintf ( szBuf , 4095 , msgTemplate . c_str ( ) , connectionSlot - > getName ( ) . c_str ( ) , maxFrameCountLagAllowed , maxClientLagTimeAllowed , clientLagCount , clientLagTime ) ;
2011-01-13 09:17:18 +01:00
# else
2011-04-05 20:39:47 +02:00
snprintf ( szBuf , 4095 , msgTemplate . c_str ( ) , connectionSlot - > getName ( ) . c_str ( ) , maxFrameCountLagAllowed , maxClientLagTimeAllowed , clientLagCount , clientLagTime ) ;
2011-01-13 09:17:18 +01:00
# endif
2011-04-05 20:39:47 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] %s \n " , __FILE__ , __FUNCTION__ , __LINE__ , szBuf ) ;
2010-06-28 02:21:12 +02:00
2011-04-05 20:39:47 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-21 02:34:31 +01:00
2011-04-05 20:39:47 +02:00
if ( skipNetworkBroadCast = = false ) {
string sMsg = szBuf ;
bool echoLocal = lang . isLanguageLocal ( languageList [ i ] ) ;
sendTextMessage ( sMsg , - 1 , echoLocal , languageList [ i ] , connectionSlot - > getPlayerIndex ( ) ) ;
}
}
2010-07-01 08:11:14 +02:00
2010-08-27 20:53:59 +02:00
if ( gameSettings . getNetworkPauseGameForLaggedClients ( ) = = false | |
2011-05-16 08:32:06 +02:00
( maxFrameCountLagAllowedEver > 0 & & clientLagCount > maxFrameCountLagAllowedEver ) | |
( maxClientLagTimeAllowedEver > 0 & & clientLagTime > maxClientLagTimeAllowedEver ) ) {
2010-07-01 08:11:14 +02:00
connectionSlot - > close ( ) ;
}
2011-02-21 02:34:31 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2010-07-01 08:11:14 +02:00
}
// New lag check warning
else if ( ( maxFrameCountLagAllowed > 0 & & warnFrameCountLagPercent > 0 & &
clientLagCount > ( maxFrameCountLagAllowed * warnFrameCountLagPercent ) ) | |
( maxClientLagTimeAllowed > 0 & & warnFrameCountLagPercent > 0 & &
clientLagTime > ( maxClientLagTimeAllowed * warnFrameCountLagPercent ) ) ) {
2010-07-29 07:51:50 +02:00
clientLagExceededOrWarned . second = true ;
2010-07-01 08:11:14 +02:00
if ( connectionSlot - > getLagCountWarning ( ) = = false ) {
connectionSlot - > setLagCountWarning ( true ) ;
2011-04-05 20:39:47 +02:00
Lang & lang = Lang : : getInstance ( ) ;
const vector < string > languageList = this - > gameSettings . getUniqueNetworkPlayerLanguages ( ) ;
for ( unsigned int i = 0 ; i < languageList . size ( ) ; + + i ) {
char szBuf [ 4096 ] = " " ;
string msgTemplate = " LAG WARNING for %s, may exceed max allowed LAG count of %f [time = %f], clientLag = %f [%f], WARNING... " ;
if ( lang . hasString ( " ClientLagWarning " ) = = true ) {
msgTemplate = lang . get ( " ClientLagWarning " , languageList [ i ] ) ;
}
2010-07-01 08:11:14 +02:00
# ifdef WIN32
2011-04-05 20:39:47 +02:00
_snprintf ( szBuf , 4095 , msgTemplate . c_str ( ) , connectionSlot - > getName ( ) . c_str ( ) , maxFrameCountLagAllowed , maxClientLagTimeAllowed , clientLagCount , clientLagTime ) ;
2010-07-01 08:11:14 +02:00
# else
2011-04-05 20:39:47 +02:00
snprintf ( szBuf , 4095 , msgTemplate . c_str ( ) , connectionSlot - > getName ( ) . c_str ( ) , maxFrameCountLagAllowed , maxClientLagTimeAllowed , clientLagCount , clientLagTime ) ;
2010-07-01 08:11:14 +02:00
# endif
2011-04-05 20:39:47 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] %s \n " , __FILE__ , __FUNCTION__ , __LINE__ , szBuf ) ;
2010-07-01 08:11:14 +02:00
2011-04-05 20:39:47 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-21 02:34:31 +01:00
2011-04-05 20:39:47 +02:00
if ( skipNetworkBroadCast = = false ) {
string sMsg = szBuf ;
bool echoLocal = lang . isLanguageLocal ( languageList [ i ] ) ;
sendTextMessage ( sMsg , - 1 , echoLocal , languageList [ i ] , connectionSlot - > getPlayerIndex ( ) ) ;
}
}
2010-07-01 08:11:14 +02:00
}
}
else if ( connectionSlot - > getLagCountWarning ( ) = = true ) {
connectionSlot - > setLagCountWarning ( false ) ;
2011-02-21 02:34:31 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2010-06-28 02:21:12 +02:00
}
2010-06-17 02:08:27 +02:00
}
}
2010-06-15 07:36:07 +02:00
}
2010-07-01 08:11:14 +02:00
catch ( const exception & ex ) {
alreadyInLagCheck = false ;
2010-10-06 22:22:06 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] ERROR [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-01-13 09:17:18 +01:00
throw runtime_error ( ex . what ( ) ) ;
2010-07-01 08:11:14 +02:00
}
2011-02-21 02:34:31 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-21 02:34:31 +01:00
2011-01-13 09:17:18 +01:00
alreadyInLagCheck = false ;
return clientLagExceededOrWarned ;
}
bool ServerInterface : : signalClientReceiveCommands ( ConnectionSlot * connectionSlot , int slotIndex , bool socketTriggered , ConnectionSlotEvent & event ) {
bool slotSignalled = false ;
event . eventType = eReceiveSocketData ;
event . networkMessage = NULL ;
event . connectionSlot = connectionSlot ;
event . socketTriggered = socketTriggered ;
event . triggerId = slotIndex ;
event . eventId = getNextEventId ( ) ;
if ( connectionSlot ! = NULL ) {
if ( socketTriggered = = true | | connectionSlot - > isConnected ( ) = = false ) {
connectionSlot - > signalUpdate ( & event ) ;
slotSignalled = true ;
2010-06-29 08:50:35 +02:00
}
2011-01-13 09:17:18 +01:00
}
return slotSignalled ;
}
2010-06-17 23:46:36 +02:00
2011-01-13 09:17:18 +01:00
void ServerInterface : : updateSocketTriggeredList ( std : : map < PLATFORM_SOCKET , bool > & socketTriggeredList ) {
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
2011-11-25 00:15:21 +01:00
if ( connectionSlot ! = NULL ) {
PLATFORM_SOCKET clientSocket = connectionSlot - > getSocketId ( ) ;
if ( Socket : : isSocketValid ( & clientSocket ) = = true ) {
socketTriggeredList [ clientSocket ] = false ;
}
2011-01-13 09:17:18 +01:00
}
}
}
void ServerInterface : : validateConnectedClients ( ) {
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL ) {
connectionSlot - > validateConnection ( ) ;
}
}
}
void ServerInterface : : signalClientsToRecieveData ( std : : map < PLATFORM_SOCKET , bool > & socketTriggeredList ,
std : : map < int , ConnectionSlotEvent > & eventList ,
std : : map < int , bool > & mapSlotSignalledList ) {
2011-09-01 03:11:23 +02:00
//bool checkForNewClients = true;
2011-01-13 09:17:18 +01:00
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
bool socketTriggered = false ;
2011-11-25 00:15:21 +01:00
if ( connectionSlot ! = NULL ) {
PLATFORM_SOCKET clientSocket = connectionSlot - > getSocketId ( ) ;
if ( Socket : : isSocketValid ( & clientSocket ) ) {
socketTriggered = socketTriggeredList [ clientSocket ] ;
}
2011-01-13 09:17:18 +01:00
}
ConnectionSlotEvent & event = eventList [ i ] ;
mapSlotSignalledList [ i ] = signalClientReceiveCommands ( connectionSlot , i , socketTriggered , event ) ;
}
}
void ServerInterface : : checkForCompletedClients ( std : : map < int , bool > & mapSlotSignalledList ,
std : : vector < string > & errorMsgList ,
std : : map < int , ConnectionSlotEvent > & eventList ) {
time_t waitForThreadElapsed = time ( NULL ) ;
std : : map < int , bool > slotsCompleted ;
for ( bool threadsDone = false ;
exitServer = = false & & threadsDone = = false & &
difftime ( time ( NULL ) , waitForThreadElapsed ) < MAX_SLOT_THREAD_WAIT_TIME ; ) {
threadsDone = true ;
// Examine all threads for completion of delegation
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-11-23 09:00:09 +01:00
//printf("===> START slot %d [%p] - About to checkForCompletedClients\n",i,slots[i]);
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-11-23 09:00:09 +01:00
//printf("===> IN slot %d - About to checkForCompletedClients\n",i);
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & mapSlotSignalledList [ i ] = = true & &
slotsCompleted . find ( i ) = = slotsCompleted . end ( ) ) {
try {
2011-11-23 09:00:09 +01:00
2011-01-13 09:17:18 +01:00
std : : vector < std : : string > errorList = connectionSlot - > getThreadErrorList ( ) ;
// Collect any collected errors from threads
2011-09-01 03:11:23 +02:00
if ( errorList . empty ( ) = = false ) {
2011-01-13 09:17:18 +01:00
for ( int iErrIdx = 0 ; iErrIdx < errorList . size ( ) ; + + iErrIdx ) {
string & sErr = errorList [ iErrIdx ] ;
if ( sErr ! = " " ) {
errorMsgList . push_back ( sErr ) ;
}
}
connectionSlot - > clearThreadErrorList ( ) ;
}
// Not done waiting for data yet
bool updateFinished = ( connectionSlot ! = NULL ? connectionSlot - > updateCompleted ( & eventList [ i ] ) : true ) ;
if ( updateFinished = = false ) {
threadsDone = false ;
break ;
}
else {
slotsCompleted [ i ] = true ;
}
}
catch ( const exception & ex ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] error detected [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-11-23 09:00:09 +01:00
2011-01-13 09:17:18 +01:00
errorMsgList . push_back ( ex . what ( ) ) ;
}
2011-01-13 02:46:32 +01:00
}
2011-11-23 09:00:09 +01:00
//printf("===> END slot %d - About to checkForCompletedClients\n",i);
2010-03-17 07:25:19 +01:00
}
2011-01-13 09:17:18 +01:00
}
}
2010-03-17 07:25:19 +01:00
2011-11-25 06:37:55 +01:00
void ServerInterface : : checkForLaggingClients ( std : : map < int , bool > & mapSlotSignalledList ,
2011-01-13 09:17:18 +01:00
std : : map < int , ConnectionSlotEvent > & eventList ,
std : : map < PLATFORM_SOCKET , bool > & socketTriggeredList ,
std : : vector < string > & errorMsgList ) {
2011-05-18 23:14:14 +02:00
bool lastGlobalLagCheckTimeUpdate = false ;
2011-01-13 09:17:18 +01:00
time_t waitForClientsElapsed = time ( NULL ) ;
time_t waitForThreadElapsed = time ( NULL ) ;
std : : map < int , bool > slotsCompleted ;
std : : map < int , bool > slotsWarnedList ;
for ( bool threadsDone = false ;
exitServer = = false & & threadsDone = = false & &
difftime ( time ( NULL ) , waitForThreadElapsed ) < MAX_SLOT_THREAD_WAIT_TIME ; ) {
threadsDone = true ;
// Examine all threads for completion of delegation
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 02:46:32 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
2011-01-13 09:17:18 +01:00
if ( connectionSlot ! = NULL & & mapSlotSignalledList [ i ] = = true & &
slotsCompleted . find ( i ) = = slotsCompleted . end ( ) ) {
try {
std : : vector < std : : string > errorList = connectionSlot - > getThreadErrorList ( ) ;
// Show any collected errors from threads
2011-09-01 03:11:23 +02:00
if ( errorList . empty ( ) = = false ) {
2011-01-13 09:17:18 +01:00
for ( int iErrIdx = 0 ; iErrIdx < errorList . size ( ) ; + + iErrIdx ) {
string & sErr = errorList [ iErrIdx ] ;
if ( sErr ! = " " ) {
errorMsgList . push_back ( sErr ) ;
}
}
connectionSlot - > clearThreadErrorList ( ) ;
}
2010-08-20 22:03:06 +02:00
2011-01-13 09:17:18 +01:00
// Not done waiting for data yet
bool updateFinished = ( connectionSlot ! = NULL ? connectionSlot - > updateCompleted ( & eventList [ i ] ) : true ) ;
if ( updateFinished = = false ) {
threadsDone = false ;
break ;
}
else {
// New lag check
std : : pair < bool , bool > clientLagExceededOrWarned = std : : make_pair ( false , false ) ;
if ( gameHasBeenInitiated = = true & & connectionSlot ! = NULL & &
connectionSlot - > isConnected ( ) = = true ) {
clientLagExceededOrWarned = clientLagCheck ( connectionSlot , slotsWarnedList [ i ] ) ;
2010-08-20 22:03:06 +02:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d, gameSettings.getNetworkPauseGameForLaggedClients() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , clientLagExceededOrWarned . first , clientLagExceededOrWarned . second , gameSettings . getNetworkPauseGameForLaggedClients ( ) ) ;
2011-01-13 02:46:32 +01:00
2011-01-13 09:17:18 +01:00
if ( clientLagExceededOrWarned . first = = true ) {
slotsWarnedList [ i ] = true ;
}
}
// If the client has exceeded lag and the server wants
// to pause while they catch up, re-trigger the
// client reader thread
if ( ( clientLagExceededOrWarned . first = = true & & gameSettings . getNetworkPauseGameForLaggedClients ( ) = = true ) ) { // ||
//(clientLagExceededOrWarned.second == true && slotsWarnedAndRetried[i] == false)) {
2010-08-20 22:03:06 +02:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d, difftime(time(NULL),waitForClientsElapsed) = %.2f, MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE = %.2f \n " , __FILE__ , __FUNCTION__ , __LINE__ , clientLagExceededOrWarned . first , clientLagExceededOrWarned . second , difftime ( time ( NULL ) , waitForClientsElapsed ) , MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE ) ;
2010-05-15 20:59:17 +02:00
2011-01-13 09:17:18 +01:00
if ( difftime ( time ( NULL ) , waitForClientsElapsed ) < MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE ) {
if ( connectionSlot ! = NULL ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , clientLagExceededOrWarned . first , clientLagExceededOrWarned . second ) ;
2011-01-13 09:17:18 +01:00
bool socketTriggered = false ;
2011-11-25 00:15:21 +01:00
PLATFORM_SOCKET clientSocket = connectionSlot - > getSocketId ( ) ;
if ( clientSocket > 0 ) {
socketTriggered = socketTriggeredList [ clientSocket ] ;
2011-01-13 09:17:18 +01:00
}
ConnectionSlotEvent & event = eventList [ i ] ;
mapSlotSignalledList [ i ] = signalClientReceiveCommands ( connectionSlot , i , socketTriggered , event ) ;
threadsDone = false ;
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , clientLagExceededOrWarned . first , clientLagExceededOrWarned . second ) ;
2011-01-13 09:17:18 +01:00
}
}
else {
slotsCompleted [ i ] = true ;
}
2011-01-13 02:46:32 +01:00
}
}
2011-01-13 09:17:18 +01:00
catch ( const exception & ex ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] error detected [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-01-13 09:17:18 +01:00
errorMsgList . push_back ( ex . what ( ) ) ;
}
}
2011-05-18 23:14:14 +02:00
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) = = true ) {
try {
if ( gameHasBeenInitiated = = true & &
difftime ( time ( NULL ) , lastGlobalLagCheckTime ) > = LAG_CHECK_GRACE_PERIOD ) {
2011-05-19 01:12:49 +02:00
//printf("\n\n\n^^^^^^^^^^^^^^ PART A\n\n\n");
2011-05-18 23:14:14 +02:00
// New lag check
std : : pair < bool , bool > clientLagExceededOrWarned = std : : make_pair ( false , false ) ;
if ( gameHasBeenInitiated = = true & & connectionSlot ! = NULL & &
connectionSlot - > isConnected ( ) = = true ) {
2011-05-19 01:12:49 +02:00
//printf("\n\n\n^^^^^^^^^^^^^^ PART B\n\n\n");
2011-05-18 23:14:14 +02:00
lastGlobalLagCheckTimeUpdate = true ;
clientLagExceededOrWarned = clientLagCheck ( connectionSlot , slotsWarnedList [ i ] ) ;
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d, gameSettings.getNetworkPauseGameForLaggedClients() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , clientLagExceededOrWarned . first , clientLagExceededOrWarned . second , gameSettings . getNetworkPauseGameForLaggedClients ( ) ) ;
if ( clientLagExceededOrWarned . first = = true ) {
slotsWarnedList [ i ] = true ;
}
}
}
}
catch ( const exception & ex ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] error detected [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
errorMsgList . push_back ( ex . what ( ) ) ;
}
}
2011-01-13 09:17:18 +01:00
}
}
2011-05-18 23:14:14 +02:00
if ( lastGlobalLagCheckTimeUpdate = = true ) {
lastGlobalLagCheckTime = time ( NULL ) ;
}
2011-01-13 09:17:18 +01:00
}
void ServerInterface : : executeNetworkCommandsFromClients ( ) {
if ( gameHasBeenInitiated = = true ) {
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) = = true ) {
vector < NetworkCommand > pendingList = connectionSlot - > getPendingNetworkCommandList ( true ) ;
2011-09-01 03:11:23 +02:00
if ( pendingList . empty ( ) = = false ) {
2011-01-13 09:17:18 +01:00
for ( int idx = 0 ; exitServer = = false & & idx < pendingList . size ( ) ; + + idx ) {
NetworkCommand & cmd = pendingList [ idx ] ;
this - > requestCommand ( & cmd ) ;
}
}
}
}
}
}
void ServerInterface : : dispatchPendingChatMessages ( std : : vector < string > & errorMsgList ) {
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & &
2011-11-25 18:01:35 +01:00
connectionSlot - > getChatTextList ( false ) . empty ( ) = = false ) {
2011-01-13 09:17:18 +01:00
try {
2011-11-27 06:27:50 +01:00
std : : vector < ChatMsgInfo > chatText = connectionSlot - > getChatTextList ( true ) ;
2011-01-13 09:17:18 +01:00
for ( int chatIdx = 0 ;
2011-11-25 22:56:36 +01:00
exitServer = = false & & slots [ i ] ! = NULL & &
2011-11-27 06:27:50 +01:00
chatIdx < chatText . size ( ) ; chatIdx + + ) {
2011-11-25 22:56:36 +01:00
connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL ) {
2011-11-27 06:27:50 +01:00
ChatMsgInfo msg ( chatText [ chatIdx ] ) ;
2011-01-13 09:17:18 +01:00
this - > addChatInfo ( msg ) ;
string newChatText = msg . chatText . c_str ( ) ;
int newChatTeamIndex = msg . chatTeamIndex ;
int newChatPlayerIndex = msg . chatPlayerIndex ;
2011-04-05 20:39:47 +02:00
string newChatLanguage = msg . targetLanguage ;
2011-01-13 02:46:32 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] #1 about to broadcast nmtText chatText [%s] chatTeamIndex = %d, newChatPlayerIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , newChatText . c_str ( ) , newChatTeamIndex , newChatPlayerIndex ) ;
2011-01-13 02:46:32 +01:00
2011-04-05 20:39:47 +02:00
if ( newChatLanguage = = " " | | newChatLanguage = = connectionSlot - > getNetworkPlayerLanguage ( ) ) {
2011-04-05 22:19:25 +02:00
NetworkMessageText networkMessageText ( newChatText . c_str ( ) , newChatTeamIndex , newChatPlayerIndex , newChatLanguage ) ;
2011-04-05 20:39:47 +02:00
broadcastMessage ( & networkMessageText , connectionSlot - > getPlayerIndex ( ) , i ) ;
}
2011-01-13 02:46:32 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] after broadcast nmtText chatText [%s] chatTeamIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , newChatText . c_str ( ) , newChatTeamIndex ) ;
2011-11-25 22:56:36 +01:00
}
2011-01-13 02:46:32 +01:00
}
2011-01-13 09:17:18 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] i = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , i ) ;
2011-01-13 09:17:18 +01:00
// Its possible that the slot is disconnected here
// so check the original pointer again
2011-11-27 06:27:50 +01:00
if ( slots [ i ] ! = NULL ) {
slots [ i ] - > clearChatInfo ( ) ;
}
2011-01-13 09:17:18 +01:00
}
catch ( const exception & ex ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] error detected [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-01-13 09:17:18 +01:00
errorMsgList . push_back ( ex . what ( ) ) ;
}
}
}
}
2011-01-13 02:46:32 +01:00
2011-01-13 09:17:18 +01:00
void ServerInterface : : update ( ) {
2011-02-21 02:34:31 +01:00
Chrono chrono ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled ) chrono . start ( ) ;
2011-02-15 04:32:14 +01:00
2011-05-18 23:14:14 +02:00
//printf("\nServerInterface::update -- A\n");
2011-01-13 09:17:18 +01:00
std : : vector < string > errorMsgList ;
try {
2010-08-20 22:03:06 +02:00
// The first thing we will do is check all clients to ensure they have
// properly identified themselves within the alloted time period
validateConnectedClients ( ) ;
2011-05-18 23:14:14 +02:00
//printf("\nServerInterface::update -- B\n");
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-15 04:32:14 +01:00
2011-01-11 23:09:46 +01:00
processTextMessageQueue ( ) ;
2011-01-12 01:16:50 +01:00
processBroadCastMessageQueue ( ) ;
2011-01-11 23:09:46 +01:00
2011-05-18 23:14:14 +02:00
//printf("\nServerInterface::update -- C\n");
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-15 04:32:14 +01:00
2011-11-25 22:56:36 +01:00
std : : map < PLATFORM_SOCKET , bool > socketTriggeredList ;
2010-07-01 02:08:59 +02:00
//update all slots
2011-11-25 22:56:36 +01:00
updateSocketTriggeredList ( socketTriggeredList ) ;
2010-05-15 20:59:17 +02:00
2011-05-18 23:14:14 +02:00
//printf("\nServerInterface::update -- D\n");
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-15 04:32:14 +01:00
2011-11-25 22:56:36 +01:00
if ( gameHasBeenInitiated = = false | | socketTriggeredList . empty ( ) = = false ) {
2011-05-18 23:14:14 +02:00
//printf("\nServerInterface::update -- E\n");
2011-11-25 22:56:36 +01:00
std : : map < int , ConnectionSlotEvent > eventList ;
bool hasData = Socket : : hasDataToRead ( socketTriggeredList ) ;
2010-03-17 07:25:19 +01:00
2011-11-25 22:56:36 +01:00
if ( hasData ) if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] hasData == true \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-17 07:25:19 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-21 02:34:31 +01:00
2011-11-25 22:56:36 +01:00
if ( gameHasBeenInitiated = = false | | hasData = = true ) {
std : : map < int , bool > mapSlotSignalledList ;
2010-06-29 08:50:35 +02:00
2010-07-01 02:08:59 +02:00
// Step #1 tell all connection slot worker threads to receive socket data
2011-11-25 22:56:36 +01:00
signalClientsToRecieveData ( socketTriggeredList , eventList , mapSlotSignalledList ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] ============ Step #2 \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-07-01 02:08:59 +02:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-15 04:32:14 +01:00
2010-07-01 02:08:59 +02:00
// Step #2 check all connection slot worker threads for completed status
2011-11-25 22:56:36 +01:00
checkForCompletedClients ( mapSlotSignalledList , errorMsgList , eventList ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] ============ Step #3 \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-08-07 05:26:38 +02:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-11-27 06:27:50 +01:00
2010-08-07 05:26:38 +02:00
// Step #3 check clients for any lagging scenarios and try to deal with them
2011-11-27 06:27:50 +01:00
checkForLaggingClients ( mapSlotSignalledList , eventList , socketTriggeredList , errorMsgList ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] ============ Step #4 \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-06-29 08:50:35 +02:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-15 04:32:14 +01:00
2010-08-07 05:26:38 +02:00
// Step #4 dispatch network commands to the pending list so that they are done in proper order
2011-01-13 09:17:18 +01:00
executeNetworkCommandsFromClients ( ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] ============ Step #5 \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-05-15 20:59:17 +02:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-02-15 04:32:14 +01:00
2010-08-07 05:26:38 +02:00
// Step #5 dispatch pending chat messages
2011-01-13 09:17:18 +01:00
dispatchPendingChatMessages ( errorMsgList ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-02-15 04:32:14 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2010-07-01 02:08:59 +02:00
}
2011-11-25 22:56:36 +01:00
else if ( gameHasBeenInitiated = = true & &
difftime ( time ( NULL ) , lastGlobalLagCheckTime ) > = LAG_CHECK_GRACE_PERIOD ) {
//printf("\nServerInterface::update -- E1\n");
//std::map<int,ConnectionSlotEvent> eventList;
2011-11-27 06:27:50 +01:00
std : : map < int , bool > mapSlotSignalledList ;
checkForLaggingClients ( mapSlotSignalledList , eventList , socketTriggeredList , errorMsgList ) ;
2011-11-25 22:56:36 +01:00
}
2011-02-15 04:32:14 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2010-07-01 02:08:59 +02:00
}
2011-11-25 22:56:36 +01:00
else if ( gameHasBeenInitiated = = true & &
difftime ( time ( NULL ) , lastGlobalLagCheckTime ) > = LAG_CHECK_GRACE_PERIOD ) {
//printf("\nServerInterface::update -- F\n");
2011-11-27 06:27:50 +01:00
std : : map < int , ConnectionSlotEvent > eventList ;
std : : map < int , bool > mapSlotSignalledList ;
checkForLaggingClients ( mapSlotSignalledList , eventList , socketTriggeredList , errorMsgList ) ;
2011-11-25 22:56:36 +01:00
}
2011-05-18 23:14:14 +02:00
//printf("\nServerInterface::update -- G\n");
2010-07-01 02:08:59 +02:00
}
catch ( const exception & ex ) {
2011-05-18 23:14:14 +02:00
//printf("\nServerInterface::update -- H\n");
2010-10-06 22:22:06 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] error detected [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2010-07-01 02:08:59 +02:00
errorMsgList . push_back ( ex . what ( ) ) ;
}
2011-09-01 03:11:23 +02:00
if ( errorMsgList . empty ( ) = = false ) {
2011-01-13 09:17:18 +01:00
for ( int iErrIdx = 0 ; iErrIdx < errorMsgList . size ( ) ; + + iErrIdx ) {
string & sErr = errorMsgList [ iErrIdx ] ;
if ( sErr ! = " " ) {
DisplayErrorMessage ( sErr ) ;
}
}
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took %lld msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2011-01-13 09:17:18 +01:00
}
void ServerInterface : : updateKeyframe ( int frameCount ) {
Chrono chrono ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled ) chrono . start ( ) ;
2011-01-13 09:17:18 +01:00
currentFrameCount = frameCount ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] currentFrameCount = %d, requestedCommands.size() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , currentFrameCount , requestedCommands . size ( ) ) ;
2011-01-13 09:17:18 +01:00
NetworkMessageCommandList networkMessageCommandList ( frameCount ) ;
while ( requestedCommands . empty ( ) = = false ) {
2011-03-28 05:54:23 +02:00
if ( networkMessageCommandList . addCommand ( & requestedCommands . back ( ) ) ) {
2011-01-13 09:17:18 +01:00
pendingCommands . push_back ( requestedCommands . back ( ) ) ;
requestedCommands . pop_back ( ) ;
}
else {
break ;
}
}
try {
2010-06-30 09:03:04 +02:00
// Possible cause of out of synch since we have more commands that need
// to be sent in this frame
2011-01-02 01:39:13 +01:00
if ( requestedCommands . empty ( ) = = false ) {
2011-09-01 03:11:23 +02:00
//char szBuf[1024]="";
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] WARNING / ERROR, requestedCommands.size() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , requestedCommands . size ( ) ) ;
2011-01-02 01:39:13 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] WARNING / ERROR, requestedCommands.size() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , requestedCommands . size ( ) ) ;
2010-06-05 02:00:36 +02:00
2010-08-21 15:04:52 +02:00
string sMsg = " may go out of synch: server requestedCommands.size() = " + intToStr ( requestedCommands . size ( ) ) ;
2011-04-05 20:39:47 +02:00
sendTextMessage ( sMsg , - 1 , true , " " ) ;
2010-06-30 09:03:04 +02:00
}
2010-06-05 02:00:36 +02:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] build command list took %lld msecs, networkMessageCommandList.getCommandCount() = %d, frameCount = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) , networkMessageCommandList . getCommandCount ( ) , frameCount ) ;
2010-04-15 03:19:00 +02:00
2010-06-30 09:03:04 +02:00
//broadcast commands
broadcastMessage ( & networkMessageCommandList ) ;
}
catch ( const exception & ex ) {
2010-10-06 22:22:06 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] error detected [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2010-06-30 09:03:04 +02:00
DisplayErrorMessage ( ex . what ( ) ) ;
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] broadcastMessage took %lld msecs, networkMessageCommandList.getCommandCount() = %d, frameCount = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) , networkMessageCommandList . getCommandCount ( ) , frameCount ) ;
2011-01-13 09:17:18 +01:00
}
2010-04-15 03:19:00 +02:00
2011-01-13 09:17:18 +01:00
bool ServerInterface : : shouldDiscardNetworkMessage ( NetworkMessageType networkMessageType , ConnectionSlot * connectionSlot ) {
bool discard = false ;
if ( connectionSlot ! = NULL ) {
2010-05-04 04:32:43 +02:00
switch ( networkMessageType ) {
case nmtIntro :
{
discard = true ;
NetworkMessageIntro msg = NetworkMessageIntro ( ) ;
connectionSlot - > receiveMessage ( & msg ) ;
}
break ;
2010-07-09 17:01:49 +02:00
case nmtPing :
{
discard = true ;
NetworkMessagePing msg = NetworkMessagePing ( ) ;
connectionSlot - > receiveMessage ( & msg ) ;
2010-07-09 19:12:57 +02:00
lastPingInfo = msg ;
2010-07-09 17:01:49 +02:00
}
break ;
2010-05-04 04:32:43 +02:00
case nmtLaunch :
{
discard = true ;
NetworkMessageLaunch msg = NetworkMessageLaunch ( ) ;
connectionSlot - > receiveMessage ( & msg ) ;
}
break ;
case nmtText :
{
discard = true ;
2010-07-06 07:30:34 +02:00
NetworkMessageText netMsg = NetworkMessageText ( ) ;
connectionSlot - > receiveMessage ( & netMsg ) ;
2011-04-05 20:39:47 +02:00
ChatMsgInfo msg ( netMsg . getText ( ) . c_str ( ) , netMsg . getTeamIndex ( ) , netMsg . getPlayerIndex ( ) , netMsg . getTargetLanguage ( ) ) ;
2011-01-13 09:17:18 +01:00
this - > addChatInfo ( msg ) ;
2010-08-27 22:09:55 +02:00
string newChatText = msg . chatText . c_str ( ) ;
2010-10-23 06:00:39 +02:00
//string newChatSender = msg.chatSender.c_str();
2010-08-27 22:09:55 +02:00
int newChatTeamIndex = msg . chatTeamIndex ;
2010-10-22 09:28:55 +02:00
int newChatPlayerIndex = msg . chatPlayerIndex ;
2011-04-05 20:39:47 +02:00
string newChatLanguage = msg . targetLanguage . c_str ( ) ;
2010-08-27 22:09:55 +02:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] #1 about to broadcast nmtText chatText [%s] chatTeamIndex = %d, newChatPlayerIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , newChatText . c_str ( ) , newChatTeamIndex , newChatPlayerIndex ) ;
2010-08-27 22:09:55 +02:00
2011-04-05 20:39:47 +02:00
NetworkMessageText networkMessageText ( newChatText . c_str ( ) , newChatTeamIndex , newChatPlayerIndex , newChatLanguage ) ;
2010-08-27 22:09:55 +02:00
broadcastMessage ( & networkMessageText , connectionSlot - > getPlayerIndex ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] after broadcast nmtText chatText [%s] chatTeamIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , newChatText . c_str ( ) , newChatTeamIndex ) ;
2010-08-27 22:09:55 +02:00
2010-05-04 04:32:43 +02:00
}
break ;
case nmtSynchNetworkGameData :
{
discard = true ;
NetworkMessageSynchNetworkGameData msg = NetworkMessageSynchNetworkGameData ( ) ;
connectionSlot - > receiveMessage ( & msg ) ;
}
break ;
case nmtSynchNetworkGameDataStatus :
{
discard = true ;
NetworkMessageSynchNetworkGameDataStatus msg = NetworkMessageSynchNetworkGameDataStatus ( ) ;
connectionSlot - > receiveMessage ( & msg ) ;
}
break ;
case nmtSynchNetworkGameDataFileCRCCheck :
{
discard = true ;
NetworkMessageSynchNetworkGameDataFileCRCCheck msg = NetworkMessageSynchNetworkGameDataFileCRCCheck ( ) ;
connectionSlot - > receiveMessage ( & msg ) ;
}
break ;
case nmtSynchNetworkGameDataFileGet :
{
discard = true ;
NetworkMessageSynchNetworkGameDataFileGet msg = NetworkMessageSynchNetworkGameDataFileGet ( ) ;
connectionSlot - > receiveMessage ( & msg ) ;
}
break ;
case nmtSwitchSetupRequest :
{
discard = true ;
SwitchSetupRequest msg = SwitchSetupRequest ( ) ;
connectionSlot - > receiveMessage ( & msg ) ;
}
break ;
case nmtPlayerIndexMessage :
{
discard = true ;
PlayerIndexMessage msg = PlayerIndexMessage ( 0 ) ;
connectionSlot - > receiveMessage ( & msg ) ;
}
break ;
}
}
2011-01-13 09:17:18 +01:00
return discard ;
}
void ServerInterface : : waitUntilReady ( Checksum * checksum ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s] START \n " , __FUNCTION__ ) ;
2011-01-13 09:17:18 +01:00
Logger & logger = Logger : : getInstance ( ) ;
gameHasBeenInitiated = true ;
Chrono chrono ;
chrono . start ( ) ;
bool allReady = false ;
2011-03-31 20:30:53 +02:00
if ( Config : : getInstance ( ) . getBool ( " EnableGameServerLoadCancel " , " false " ) = = true ) {
logger . setCancelLoadingEnabled ( true ) ;
}
2011-03-31 20:13:02 +02:00
Lang & lang = Lang : : getInstance ( ) ;
2011-11-14 06:18:09 +01:00
uint64 waitLoopIterationCount = 0 ;
2011-11-15 23:10:32 +01:00
uint64 MAX_LOOP_COUNT_BEFORE_SLEEP = 10 ;
2011-11-15 17:41:10 +01:00
MAX_LOOP_COUNT_BEFORE_SLEEP = Config : : getInstance ( ) . getInt ( " NetworkServerLoopGameLoadingCap " , intToStr ( MAX_LOOP_COUNT_BEFORE_SLEEP ) . c_str ( ) ) ;
2011-11-15 23:10:32 +01:00
int sleepMillis = Config : : getInstance ( ) . getInt ( " NetworkServerLoopGameLoadingCapSleepMillis " , " 10 " ) ;
2011-11-15 17:41:10 +01:00
2011-03-31 20:13:02 +02:00
while ( exitServer = = false & & allReady = = false & & logger . getCancelLoading ( ) = = false ) {
2011-11-14 06:18:09 +01:00
waitLoopIterationCount + + ;
if ( waitLoopIterationCount > 0 & & waitLoopIterationCount % MAX_LOOP_COUNT_BEFORE_SLEEP = = 0 ) {
2011-11-15 17:41:10 +01:00
sleep ( sleepMillis ) ;
2011-11-14 06:18:09 +01:00
waitLoopIterationCount = 0 ;
}
2011-01-13 09:17:18 +01:00
vector < string > waitingForHosts ;
2010-03-17 07:25:19 +01:00
allReady = true ;
2011-01-10 16:50:16 +01:00
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2010-03-17 07:25:19 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
2010-05-04 04:32:43 +02:00
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) = = true ) {
if ( connectionSlot - > isReady ( ) = = false ) {
2011-11-25 22:56:36 +01:00
NetworkMessageType networkMessageType = connectionSlot - > getNextMessageType ( ) ;
2010-03-17 07:25:19 +01:00
2010-05-04 04:32:43 +02:00
// consume old messages from the lobby
bool discarded = shouldDiscardNetworkMessage ( networkMessageType , connectionSlot ) ;
if ( discarded = = false ) {
NetworkMessageReady networkMessageReady ;
if ( networkMessageType = = nmtReady & &
connectionSlot - > receiveMessage ( & networkMessageReady ) ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s] networkMessageType==nmtReady \n " , __FUNCTION__ ) ;
2010-05-04 04:32:43 +02:00
connectionSlot - > setReady ( ) ;
}
else if ( networkMessageType ! = nmtInvalid ) {
string sErr = " Unexpected network message: " + intToStr ( networkMessageType ) ;
2011-04-05 20:39:47 +02:00
sendTextMessage ( sErr , - 1 , true , " " , i ) ;
2010-05-04 04:32:43 +02:00
DisplayErrorMessage ( sErr ) ;
2011-03-31 20:13:02 +02:00
logger . setCancelLoading ( false ) ;
2010-05-04 04:32:43 +02:00
return ;
}
2010-03-17 07:25:19 +01:00
}
2010-04-30 04:34:19 +02:00
waitingForHosts . push_back ( connectionSlot - > getName ( ) ) ;
2010-03-17 07:25:19 +01:00
allReady = false ;
}
}
}
//check for timeout
2010-05-04 04:32:43 +02:00
if ( allReady = = false ) {
2011-01-13 09:17:18 +01:00
if ( chrono . getMillis ( ) > readyWaitTimeout ) {
2011-04-05 20:39:47 +02:00
Lang & lang = Lang : : getInstance ( ) ;
const vector < string > languageList = this - > gameSettings . getUniqueNetworkPlayerLanguages ( ) ;
for ( unsigned int i = 0 ; i < languageList . size ( ) ; + + i ) {
string sErr = " Timeout waiting for clients. " ;
if ( lang . hasString ( " TimeoutWaitingForClients " ) = = true ) {
sErr = lang . get ( " TimeoutWaitingForClients " , languageList [ i ] ) ;
}
bool localEcho = lang . isLanguageLocal ( languageList [ i ] ) ;
sendTextMessage ( sErr , - 1 , localEcho , languageList [ i ] ) ;
if ( localEcho = = true ) {
DisplayErrorMessage ( sErr ) ;
}
}
2011-03-31 20:13:02 +02:00
logger . setCancelLoading ( false ) ;
2011-01-13 09:17:18 +01:00
return ;
}
else {
if ( chrono . getMillis ( ) % 1000 = = 0 ) {
string waitForHosts = " " ;
for ( int i = 0 ; i < waitingForHosts . size ( ) ; i + + ) {
if ( waitForHosts ! = " " ) {
waitForHosts + = " , " ;
}
waitForHosts + = waitingForHosts [ i ] ;
}
char szBuf [ 1024 ] = " " ;
2011-03-31 20:13:02 +02:00
string updateTextFormat = lang . get ( " NetworkGameServerLoadStatus " ) ;
if ( updateTextFormat = = " " | | updateTextFormat [ 0 ] = = ' ? ' ) {
updateTextFormat = " Waiting for network: %lld seconds elapsed (maximum wait time: %d seconds) " ;
}
sprintf ( szBuf , updateTextFormat . c_str ( ) , ( long long int ) ( chrono . getMillis ( ) / 1000 ) , int ( readyWaitTimeout / 1000 ) ) ;
char szBuf1 [ 1024 ] = " " ;
string statusTextFormat = lang . get ( " NetworkGameStatusWaiting " ) ;
if ( statusTextFormat = = " " | | statusTextFormat [ 0 ] = = ' ? ' ) {
statusTextFormat = " Waiting for players: %s " ;
}
sprintf ( szBuf1 , statusTextFormat . c_str ( ) , waitForHosts . c_str ( ) ) ;
logger . add ( szBuf , true , szBuf1 ) ;
uint32 loadingStatus = nmls_NONE ;
//send ready message after, so clients start delayed
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-03-31 20:13:02 +02:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) = = true ) {
switch ( i ) {
case 0 :
loadingStatus | = nmls_PLAYER1_CONNECTED ;
if ( connectionSlot - > isReady ( ) ) {
loadingStatus | = nmls_PLAYER1_READY ;
}
break ;
case 1 :
loadingStatus | = nmls_PLAYER2_CONNECTED ;
if ( connectionSlot - > isReady ( ) ) {
loadingStatus | = nmls_PLAYER2_READY ;
}
break ;
case 2 :
loadingStatus | = nmls_PLAYER3_CONNECTED ;
if ( connectionSlot - > isReady ( ) ) {
loadingStatus | = nmls_PLAYER3_READY ;
}
break ;
case 3 :
loadingStatus | = nmls_PLAYER4_CONNECTED ;
if ( connectionSlot - > isReady ( ) ) {
loadingStatus | = nmls_PLAYER4_READY ;
}
break ;
case 4 :
loadingStatus | = nmls_PLAYER5_CONNECTED ;
if ( connectionSlot - > isReady ( ) ) {
loadingStatus | = nmls_PLAYER5_READY ;
}
break ;
case 5 :
loadingStatus | = nmls_PLAYER6_CONNECTED ;
if ( connectionSlot - > isReady ( ) ) {
loadingStatus | = nmls_PLAYER6_READY ;
}
break ;
case 6 :
loadingStatus | = nmls_PLAYER7_CONNECTED ;
if ( connectionSlot - > isReady ( ) ) {
loadingStatus | = nmls_PLAYER7_READY ;
}
break ;
case 7 :
loadingStatus | = nmls_PLAYER8_CONNECTED ;
if ( connectionSlot - > isReady ( ) ) {
loadingStatus | = nmls_PLAYER8_READY ;
}
break ;
}
}
}
// send loading status message
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-03-31 20:13:02 +02:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) = = true ) {
NetworkMessageLoadingStatus networkMessageLoadingStatus ( loadingStatus ) ;
connectionSlot - > sendMessage ( & networkMessageLoadingStatus ) ;
}
}
2011-01-13 09:17:18 +01:00
}
}
2010-03-17 07:25:19 +01:00
}
2011-01-20 09:19:14 +01:00
Window : : handleEvent ( ) ;
2010-03-17 07:25:19 +01:00
}
2011-03-31 20:13:02 +02:00
if ( logger . getCancelLoading ( ) = = true ) {
2011-04-05 20:39:47 +02:00
Lang & lang = Lang : : getInstance ( ) ;
const vector < string > languageList = this - > gameSettings . getUniqueNetworkPlayerLanguages ( ) ;
for ( unsigned int i = 0 ; i < languageList . size ( ) ; + + i ) {
string sErr = lang . get ( " GameCancelledByUser " , languageList [ i ] ) ;
bool localEcho = lang . isLanguageLocal ( languageList [ i ] ) ;
sendTextMessage ( sErr , - 1 , localEcho , languageList [ i ] ) ;
if ( localEcho = = true ) {
DisplayErrorMessage ( sErr ) ;
}
}
2011-03-31 20:13:02 +02:00
quitGame ( true ) ;
2011-04-05 20:39:47 +02:00
//DisplayErrorMessage(sErr);
2011-03-31 20:13:02 +02:00
logger . setCancelLoading ( false ) ;
return ;
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s] PART B (telling client we are ready! \n " , __FUNCTION__ ) ;
2011-01-13 09:17:18 +01:00
try {
2010-06-30 09:03:04 +02:00
//send ready message after, so clients start delayed
2011-01-10 16:50:16 +01:00
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2010-06-30 09:03:04 +02:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) = = true ) {
NetworkMessageReady networkMessageReady ( checksum - > getSum ( ) ) ;
connectionSlot - > sendMessage ( & networkMessageReady ) ;
}
2010-03-17 07:25:19 +01:00
}
2010-06-30 09:03:04 +02:00
gameStartTime = time ( NULL ) ;
2011-01-13 09:17:18 +01:00
}
2010-06-30 09:03:04 +02:00
catch ( const exception & ex ) {
2010-10-06 22:22:06 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] error detected [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2010-06-30 09:03:04 +02:00
DisplayErrorMessage ( ex . what ( ) ) ;
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s] END \n " , __FUNCTION__ ) ;
2011-01-13 09:17:18 +01:00
}
void ServerInterface : : processBroadCastMessageQueue ( ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( broadcastMessageQueueThreadAccessor , CODE_AT_LINE ) ;
2011-09-01 03:11:23 +02:00
if ( broadcastMessageQueue . empty ( ) = = false ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] broadcastMessageQueue.size() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , broadcastMessageQueue . size ( ) ) ;
2011-01-13 09:17:18 +01:00
for ( int i = 0 ; i < broadcastMessageQueue . size ( ) ; + + i ) {
pair < const NetworkMessage * , int > & item = broadcastMessageQueue [ i ] ;
if ( item . first ! = NULL ) {
this - > broadcastMessage ( item . first , item . second ) ;
delete item . first ;
}
item . first = NULL ;
}
broadcastMessageQueue . clear ( ) ;
}
}
void ServerInterface : : queueBroadcastMessage ( const NetworkMessage * networkMessage , int excludeSlot ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( broadcastMessageQueueThreadAccessor , CODE_AT_LINE ) ;
2011-01-13 09:17:18 +01:00
pair < const NetworkMessage * , int > item ;
item . first = networkMessage ;
item . second = excludeSlot ;
broadcastMessageQueue . push_back ( item ) ;
}
void ServerInterface : : processTextMessageQueue ( ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( textMessageQueueThreadAccessor , CODE_AT_LINE ) ;
2011-09-01 03:11:23 +02:00
if ( textMessageQueue . empty ( ) = = false ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] textMessageQueue.size() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , textMessageQueue . size ( ) ) ;
for ( int i = 0 ; i < textMessageQueue . size ( ) ; + + i ) {
TextMessageQueue & item = textMessageQueue [ i ] ;
2011-04-05 20:39:47 +02:00
sendTextMessage ( item . text , item . teamIndex , item . echoLocal , item . targetLanguage ) ;
2011-03-28 05:54:23 +02:00
}
textMessageQueue . clear ( ) ;
2011-01-13 09:17:18 +01:00
}
}
2011-04-05 20:39:47 +02:00
void ServerInterface : : queueTextMessage ( const string & text , int teamIndex ,
bool echoLocal , string targetLanguage ) {
2011-11-29 06:07:18 +01:00
//printf("Line: %d text [%s]\n",__LINE__,text.c_str());
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( textMessageQueueThreadAccessor , CODE_AT_LINE ) ;
2011-01-13 09:17:18 +01:00
TextMessageQueue item ;
item . text = text ;
item . teamIndex = teamIndex ;
item . echoLocal = echoLocal ;
2011-04-05 20:39:47 +02:00
item . targetLanguage = targetLanguage ;
2011-01-13 09:17:18 +01:00
textMessageQueue . push_back ( item ) ;
}
2011-04-05 20:39:47 +02:00
void ServerInterface : : sendTextMessage ( const string & text , int teamIndex ,
bool echoLocal , string targetLanguage ) {
sendTextMessage ( text , teamIndex , echoLocal , targetLanguage , - 1 ) ;
2011-01-13 09:17:18 +01:00
}
2011-04-05 20:39:47 +02:00
void ServerInterface : : sendTextMessage ( const string & text , int teamIndex , bool echoLocal ,
string targetLanguage , int lockedSlotIndex ) {
2011-11-29 06:07:18 +01:00
//printf("Line: %d text [%s] echoLocal = %d\n",__LINE__,text.c_str(),echoLocal);
//assert(text.length() > 0);
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] text [%s] teamIndex = %d, echoLocal = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , text . c_str ( ) , teamIndex , echoLocal , lockedSlotIndex ) ;
2011-04-05 20:39:47 +02:00
NetworkMessageText networkMessageText ( text , teamIndex , getHumanPlayerIndex ( ) , targetLanguage ) ;
2011-01-13 09:17:18 +01:00
broadcastMessage ( & networkMessageText , - 1 , lockedSlotIndex ) ;
if ( echoLocal = = true ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-07-01 08:11:14 +02:00
2010-10-23 06:00:39 +02:00
//ChatMsgInfo msg(text.c_str(),networkMessageText.getSender().c_str(),teamIndex,networkMessageText.getPlayerIndex());
2011-04-05 20:39:47 +02:00
ChatMsgInfo msg ( text . c_str ( ) , teamIndex , networkMessageText . getPlayerIndex ( ) , targetLanguage ) ;
2010-07-01 02:08:59 +02:00
this - > addChatInfo ( msg ) ;
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
}
void ServerInterface : : quitGame ( bool userManuallyQuit ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
NetworkMessageQuit networkMessageQuit ;
broadcastMessage ( & networkMessageQuit ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
}
string ServerInterface : : getNetworkStatus ( ) {
Lang & lang = Lang : : getInstance ( ) ;
string str = " " ;
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2010-03-17 07:25:19 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
str + = intToStr ( i ) + " : " ;
2011-01-13 09:17:18 +01:00
if ( connectionSlot ! = NULL ) {
if ( connectionSlot - > isConnected ( ) ) {
int clientLagCount = connectionSlot - > getCurrentLagCount ( ) ;
2010-06-15 07:44:29 +02:00
double lastClientCommandListTimeLag = difftime ( time ( NULL ) , connectionSlot - > getLastReceiveCommandListTime ( ) ) ;
2010-07-02 04:50:20 +02:00
//float pingTime = connectionSlot->getThreadedPingMS(connectionSlot->getIpAddress().c_str());
2011-01-13 09:17:18 +01:00
char szBuf [ 1024 ] = " " ;
2010-07-02 04:50:20 +02:00
//sprintf(szBuf,", lag = %d [%.2f], ping = %.2fms",clientLagCount,lastClientCommandListTimeLag,pingTime);
sprintf ( szBuf , " , lag = %d [%.2f] " , clientLagCount , lastClientCommandListTimeLag ) ;
2011-01-13 09:17:18 +01:00
str + = connectionSlot - > getName ( ) + string ( szBuf ) ;
2010-03-17 07:25:19 +01:00
}
}
2010-12-25 23:38:00 +01:00
else {
2010-03-17 07:25:19 +01:00
str + = lang . get ( " NotConnected " ) ;
}
str + = ' \n ' ;
}
2011-01-13 09:17:18 +01:00
return str ;
}
bool ServerInterface : : launchGame ( const GameSettings * gameSettings ) {
bool bOkToStart = true ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & &
2011-04-28 00:51:44 +02:00
( connectionSlot - > getAllowDownloadDataSynch ( ) = = true | | connectionSlot - > getAllowGameDataSynchCheck ( ) = = true ) & &
2011-01-13 09:17:18 +01:00
connectionSlot - > isConnected ( ) ) {
if ( connectionSlot - > getNetworkGameDataSynchCheckOk ( ) = = false ) {
2011-04-28 00:51:44 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] map [%d] tile [%d] techtree [%d] \n " , __FILE__ , __FUNCTION__ , __LINE__ , connectionSlot - > getNetworkGameDataSynchCheckOkMap ( ) , connectionSlot - > getNetworkGameDataSynchCheckOkTile ( ) , connectionSlot - > getNetworkGameDataSynchCheckOkTech ( ) ) ;
if ( SystemFlags : : VERBOSE_MODE_ENABLED ) printf ( " In [%s::%s Line: %d] map [%d] tile [%d] techtree [%d] \n " , __FILE__ , __FUNCTION__ , __LINE__ , connectionSlot - > getNetworkGameDataSynchCheckOkMap ( ) , connectionSlot - > getNetworkGameDataSynchCheckOkTile ( ) , connectionSlot - > getNetworkGameDataSynchCheckOkTech ( ) ) ;
2011-01-13 09:17:18 +01:00
bOkToStart = false ;
break ;
}
}
}
if ( bOkToStart = = true ) {
2011-02-15 04:32:14 +01:00
2011-03-05 21:15:28 +01:00
bool useInGameBlockingClientSockets = Config : : getInstance ( ) . getBool ( " EnableInGameBlockingSockets " , " true " ) ;
2011-02-16 05:43:27 +01:00
if ( useInGameBlockingClientSockets = = true ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-02-16 05:43:27 +01:00
for ( int i = 0 ; i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-02-16 05:43:27 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) ) {
connectionSlot - > getSocket ( ) - > setBlock ( true ) ;
}
2011-02-15 04:32:14 +01:00
}
}
2011-02-16 05:43:27 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] needToRepublishToMasterserver = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , needToRepublishToMasterserver ) ;
2011-01-13 09:17:18 +01:00
serverSocket . stopBroadCastThread ( ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] needToRepublishToMasterserver = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , needToRepublishToMasterserver ) ;
2011-01-13 09:17:18 +01:00
NetworkMessageLaunch networkMessageLaunch ( gameSettings , nmtLaunch ) ;
broadcastMessage ( & networkMessageLaunch ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] needToRepublishToMasterserver = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , needToRepublishToMasterserver ) ;
2011-01-13 09:17:18 +01:00
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( masterServerThreadAccessor , CODE_AT_LINE ) ;
2011-01-13 09:17:18 +01:00
delete publishToMasterserverThread ;
publishToMasterserverThread = NULL ;
lastMasterserverHeartbeatTime = 0 ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] ftpServer = %p \n " , __FILE__ , __FUNCTION__ , __LINE__ , ftpServer ) ;
2011-01-13 09:17:18 +01:00
if ( ftpServer ! = NULL ) {
ftpServer - > shutdownAndWait ( ) ;
delete ftpServer ;
ftpServer = NULL ;
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] needToRepublishToMasterserver = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , needToRepublishToMasterserver ) ;
2011-01-13 09:17:18 +01:00
if ( needToRepublishToMasterserver = = true ) {
publishToMasterserverThread = new SimpleTaskThread ( this , 0 , 125 ) ;
2010-10-24 07:52:21 +02:00
publishToMasterserverThread - > setUniqueID ( __FILE__ ) ;
publishToMasterserverThread - > start ( ) ;
2010-11-09 10:06:52 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] needToRepublishToMasterserver = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , needToRepublishToMasterserver ) ;
2011-01-13 09:17:18 +01:00
}
2010-12-25 23:38:00 +01:00
2011-01-13 09:17:18 +01:00
if ( ftpServer ! = NULL ) {
ftpServer - > shutdownAndWait ( ) ;
delete ftpServer ;
ftpServer = NULL ;
}
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
return bOkToStart ;
}
2010-06-03 09:52:17 +02:00
2011-01-13 09:17:18 +01:00
void ServerInterface : : broadcastGameSetup ( const GameSettings * gameSettings ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( serverSynchAccessor , CODE_AT_LINE ) ;
2011-01-13 09:17:18 +01:00
NetworkMessageLaunch networkMessageLaunch ( gameSettings , nmtBroadCastSetup ) ;
broadcastMessage ( & networkMessageLaunch ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
}
2010-06-03 09:52:17 +02:00
2011-01-13 09:17:18 +01:00
void ServerInterface : : broadcastMessage ( const NetworkMessage * networkMessage , int excludeSlot , int lockedSlotIndex ) {
try {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-06-03 09:52:17 +02:00
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlotBroadCastAccessor ( inBroadcastMessageThreadAccessor , CODE_AT_LINE ) ;
2011-01-13 09:17:18 +01:00
if ( inBroadcastMessage = = true & & dynamic_cast < const NetworkMessageText * > ( networkMessage ) ! = NULL ) {
safeMutexSlotBroadCastAccessor . ReleaseLock ( ) ;
const NetworkMessageText * txtMsg = dynamic_cast < const NetworkMessageText * > ( networkMessage ) ;
const NetworkMessageText * msgCopy = txtMsg - > getCopy ( ) ;
queueBroadcastMessage ( msgCopy , excludeSlot ) ;
return ;
}
else {
inBroadcastMessage = true ;
safeMutexSlotBroadCastAccessor . ReleaseLock ( true ) ;
}
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-11-27 06:27:50 +01:00
MutexSafeWrapper safeMutexSlot ( NULL , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
if ( i ! = lockedSlotIndex ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] i = %d, lockedSlotIndex = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , i , lockedSlotIndex ) ;
2011-12-02 17:07:59 +01:00
safeMutexSlot . setMutex ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2010-03-17 07:25:19 +01:00
}
2010-12-25 23:38:00 +01:00
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( i ! = excludeSlot & & connectionSlot ! = NULL ) {
if ( connectionSlot - > isConnected ( ) ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] before sendMessage \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
connectionSlot - > sendMessage ( networkMessage ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] after sendMessage \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-06-03 09:52:17 +02:00
}
2011-01-13 09:17:18 +01:00
if ( gameHasBeenInitiated = = true & & connectionSlot - > isConnected ( ) = = false ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] #1 before removeSlot for slot# %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , i ) ;
2010-12-25 23:38:00 +01:00
//safeMutexSlot.ReleaseLock();
removeSlot ( i , i ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] #1 after removeSlot for slot# %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , i ) ;
2010-06-03 09:52:17 +02:00
}
}
2011-01-13 09:17:18 +01:00
else if ( i = = excludeSlot & & gameHasBeenInitiated = = true & &
connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) = = false ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] #2 before removeSlot for slot# %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , i ) ;
2011-01-13 09:17:18 +01:00
//safeMutexSlot.ReleaseLock();
removeSlot ( i , i ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] #2 after removeSlot for slot# %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , i ) ;
2011-01-13 09:17:18 +01:00
}
}
safeMutexSlotBroadCastAccessor . Lock ( ) ;
inBroadcastMessage = false ;
safeMutexSlotBroadCastAccessor . ReleaseLock ( ) ;
}
catch ( const exception & ex ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] ERROR [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-01-13 09:17:18 +01:00
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlotBroadCastAccessor ( inBroadcastMessageThreadAccessor , CODE_AT_LINE ) ;
2011-01-13 09:17:18 +01:00
inBroadcastMessage = false ;
safeMutexSlotBroadCastAccessor . ReleaseLock ( ) ;
2010-07-08 10:29:51 +02:00
string sMsg = ex . what ( ) ;
2011-04-05 20:39:47 +02:00
sendTextMessage ( sMsg , - 1 , true , " " , lockedSlotIndex ) ;
2011-01-13 09:17:18 +01:00
}
}
2010-05-15 20:59:17 +02:00
2011-01-13 09:17:18 +01:00
void ServerInterface : : broadcastMessageToConnectedClients ( const NetworkMessage * networkMessage , int excludeSlot ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
try {
2011-01-10 16:50:16 +01:00
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
2010-03-17 07:25:19 +01:00
2011-01-13 09:17:18 +01:00
if ( i ! = excludeSlot & & connectionSlot ! = NULL ) {
2010-07-01 02:08:59 +02:00
if ( connectionSlot - > isConnected ( ) ) {
connectionSlot - > sendMessage ( networkMessage ) ;
}
2010-03-17 07:25:19 +01:00
}
}
}
2011-01-13 09:17:18 +01:00
catch ( const exception & ex ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] ERROR [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2011-01-13 09:17:18 +01:00
DisplayErrorMessage ( ex . what ( ) ) ;
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
}
void ServerInterface : : updateListen ( ) {
if ( gameHasBeenInitiated = = true ) {
return ;
}
int openSlotCount = 0 ;
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
//MutexSafeWrapper safeMutexSlot(slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
2010-05-28 07:31:17 +02:00
bool isSlotOpen = ( slots [ i ] ! = NULL & & slots [ i ] - > isConnected ( ) = = false ) ;
if ( isSlotOpen = = true ) {
2010-03-17 07:25:19 +01:00
+ + openSlotCount ;
}
}
2011-01-13 09:17:18 +01:00
serverSocket . listen ( openSlotCount ) ;
}
2010-03-17 07:25:19 +01:00
2011-01-13 09:17:18 +01:00
int ServerInterface : : getOpenSlotCount ( ) {
int openSlotCount = 0 ;
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
//MutexSafeWrapper safeMutexSlot(slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
2010-05-28 07:31:17 +02:00
bool isSlotOpen = ( slots [ i ] ! = NULL & & slots [ i ] - > isConnected ( ) = = false ) ;
2010-05-15 20:59:17 +02:00
2010-05-28 07:31:17 +02:00
if ( isSlotOpen = = true ) {
2010-05-12 17:25:56 +02:00
+ + openSlotCount ;
}
}
2011-01-13 09:17:18 +01:00
return openSlotCount ;
}
2011-09-26 06:50:13 +02:00
int ServerInterface : : getGameSettingsUpdateCount ( ) {
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] START gameSettingsUpdateCount = %d \n " , __FILE__ , __FUNCTION__ , gameSettingsUpdateCount ) ;
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( serverSynchAccessor , CODE_AT_LINE ) ;
2011-09-26 06:50:13 +02:00
int result = gameSettingsUpdateCount ;
safeMutex . ReleaseLock ( ) ;
return result ;
}
2011-01-13 09:17:18 +01:00
void ServerInterface : : setGameSettings ( GameSettings * serverGameSettings , bool waitForClientAck ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] START gameSettingsUpdateCount = %d, waitForClientAck = %d \n " , __FILE__ , __FUNCTION__ , gameSettingsUpdateCount , waitForClientAck ) ;
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( serverSynchAccessor , CODE_AT_LINE ) ;
2011-10-12 08:54:36 +02:00
string mapFile = serverGameSettings - > getMap ( ) ;
if ( find ( mapFiles . begin ( ) , mapFiles . end ( ) , mapFile ) = = mapFiles . end ( ) ) {
printf ( " Reverting map from [%s] to [%s] \n " , serverGameSettings - > getMap ( ) . c_str ( ) , gameSettings . getMap ( ) . c_str ( ) ) ;
serverGameSettings - > setMapFilterIndex ( gameSettings . getMapFilterIndex ( ) ) ;
serverGameSettings - > setMap ( gameSettings . getMap ( ) ) ;
serverGameSettings - > setMapCRC ( gameSettings . getMapCRC ( ) ) ;
}
string tilesetFile = serverGameSettings - > getTileset ( ) ;
if ( find ( tilesetFiles . begin ( ) , tilesetFiles . end ( ) , tilesetFile ) = = tilesetFiles . end ( ) ) {
printf ( " Reverting tileset from [%s] to [%s] \n " , serverGameSettings - > getTileset ( ) . c_str ( ) , gameSettings . getTileset ( ) . c_str ( ) ) ;
serverGameSettings - > setTileset ( gameSettings . getTileset ( ) ) ;
serverGameSettings - > setTilesetCRC ( gameSettings . getTilesetCRC ( ) ) ;
}
string techtreeFile = serverGameSettings - > getTech ( ) ;
if ( find ( techTreeFiles . begin ( ) , techTreeFiles . end ( ) , techtreeFile ) = = techTreeFiles . end ( ) ) {
printf ( " Reverting tech from [%s] to [%s] \n " , serverGameSettings - > getTech ( ) . c_str ( ) , gameSettings . getTech ( ) . c_str ( ) ) ;
serverGameSettings - > setTech ( gameSettings . getTech ( ) ) ;
serverGameSettings - > setTechCRC ( gameSettings . getTechCRC ( ) ) ;
}
2011-01-13 09:17:18 +01:00
gameSettings = * serverGameSettings ;
if ( getAllowGameDataSynchCheck ( ) = = true ) {
if ( waitForClientAck = = true & & gameSettingsUpdateCount > 0 ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Waiting for client acks #1 \n " , __FILE__ , __FUNCTION__ ) ;
2011-01-13 09:17:18 +01:00
time_t tStart = time ( NULL ) ;
bool gotAckFromAllClients = false ;
while ( gotAckFromAllClients = = false & & difftime ( time ( NULL ) , tStart ) < = 5 ) {
gotAckFromAllClients = true ;
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-11-23 09:00:09 +01:00
//printf("===> START slot %d - About to setGameSettings #1\n",i);
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) ) {
if ( connectionSlot - > getReceivedNetworkGameStatus ( ) = = false ) {
gotAckFromAllClients = false ;
}
connectionSlot - > update ( true , i ) ;
}
2011-11-23 09:00:09 +01:00
//printf("===> END slot %d - About to setGameSettings #1\n",i);
2011-01-13 09:17:18 +01:00
}
}
}
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) ) {
connectionSlot - > setReceivedNetworkGameStatus ( false ) ;
}
}
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData ( getGameSettings ( ) ) ;
broadcastMessageToConnectedClients ( & networkMessageSynchNetworkGameData ) ;
if ( waitForClientAck = = true ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Waiting for client acks #2 \n " , __FILE__ , __FUNCTION__ ) ;
2011-01-13 09:17:18 +01:00
time_t tStart = time ( NULL ) ;
bool gotAckFromAllClients = false ;
while ( gotAckFromAllClients = = false & & difftime ( time ( NULL ) , tStart ) < = 5 ) {
gotAckFromAllClients = true ;
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-11-23 09:00:09 +01:00
//printf("===> START slot %d - About to setGameSettings 2\n",i);
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2011-01-13 09:17:18 +01:00
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( connectionSlot ! = NULL & & connectionSlot - > isConnected ( ) ) {
if ( connectionSlot - > getReceivedNetworkGameStatus ( ) = = false ) {
gotAckFromAllClients = false ;
}
connectionSlot - > update ( true , i ) ;
}
2011-11-23 09:00:09 +01:00
//printf("===> END slot %d - About to setGameSettings 2\n",i);
2011-01-13 09:17:18 +01:00
}
}
}
}
2011-09-24 09:46:56 +02:00
gameSettingsUpdateCount + + ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] END \n " , __FILE__ , __FUNCTION__ ) ;
2011-01-13 09:17:18 +01:00
}
void ServerInterface : : close ( ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] START \n " , __FILE__ , __FUNCTION__ ) ;
2011-01-13 09:17:18 +01:00
}
string ServerInterface : : getHumanPlayerName ( int index ) {
string result = Config : : getInstance ( ) . getString ( " NetPlayerName " , Socket : : getHostName ( ) . c_str ( ) ) ;
if ( index > = 0 | | gameSettings . getThisFactionIndex ( ) > = 0 ) {
if ( index < 0 ) {
index = gameSettings . getThisFactionIndex ( ) ;
}
if ( gameSettings . getNetworkPlayerName ( index ) ! = " " ) {
result = gameSettings . getNetworkPlayerName ( index ) ;
}
}
return result ;
}
int ServerInterface : : getHumanPlayerIndex ( ) const {
return gameSettings . getStartLocationIndex ( gameSettings . getThisFactionIndex ( ) ) ;
}
std : : map < string , string > ServerInterface : : publishToMasterserver ( ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
int slotCountUsed = 1 ;
int slotCountHumans = 1 ;
int slotCountConnectedPlayers = 1 ;
Config & config = Config : : getInstance ( ) ;
std : : map < string , string > publishToServerInfo ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
for ( int i = 0 ; exitServer = = false & & i < GameConstants : : maxPlayers ; + + i ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutexSlot ( slotAccessorMutexes [ i ] , CODE_AT_LINE_X ( i ) ) ;
2010-12-18 20:52:47 +01:00
if ( slots [ i ] ! = NULL ) {
2010-10-23 11:06:47 +02:00
slotCountUsed + + ;
slotCountHumans + + ;
ConnectionSlot * connectionSlot = slots [ i ] ;
if ( ( connectionSlot ! = NULL ) & & ( connectionSlot - > isConnected ( ) ) ) {
slotCountConnectedPlayers + + ;
}
}
}
2011-01-13 09:17:18 +01:00
publishToServerInfo [ " glestVersion " ] = glestVersionString ;
publishToServerInfo [ " platform " ] = getPlatformNameString ( ) ;
publishToServerInfo [ " binaryCompileDate " ] = getCompileDateTime ( ) ;
2011-01-25 08:41:12 +01:00
publishToServerInfo [ " serverTitle " ] = getHumanPlayerName ( ) + " 's game " ;
2011-01-13 09:17:18 +01:00
publishToServerInfo [ " tech " ] = this - > getGameSettings ( ) - > getTech ( ) ;
publishToServerInfo [ " map " ] = this - > getGameSettings ( ) - > getMap ( ) ;
publishToServerInfo [ " tileset " ] = this - > getGameSettings ( ) - > getTileset ( ) ;
publishToServerInfo [ " activeSlots " ] = intToStr ( slotCountUsed ) ;
publishToServerInfo [ " networkSlots " ] = intToStr ( slotCountHumans ) ;
publishToServerInfo [ " connectedClients " ] = intToStr ( slotCountConnectedPlayers ) ;
2011-11-23 22:36:49 +01:00
string externalport = config . getString ( " MasterServerExternalPort " , intToStr ( GameConstants : : serverPort ) . c_str ( ) ) ;
2011-01-13 09:17:18 +01:00
publishToServerInfo [ " externalconnectport " ] = externalport ;
2011-01-26 22:18:26 +01:00
publishToServerInfo [ " privacyPlease " ] = intToStr ( config . getBool ( " PrivacyPlease " , " false " ) ) ;
2011-01-25 08:41:12 +01:00
publishToServerInfo [ " gameStatus " ] = intToStr ( game_status_in_progress ) ;
2011-01-13 09:17:18 +01:00
if ( publishToMasterserverThread = = NULL ) {
2010-10-23 11:06:47 +02:00
publishToServerInfo [ " gameCmd " ] = " gameOver " ;
2011-01-25 08:41:12 +01:00
publishToServerInfo [ " gameStatus " ] = intToStr ( game_status_finished ) ;
2010-10-23 11:06:47 +02:00
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-01-13 09:17:18 +01:00
return publishToServerInfo ;
}
void ServerInterface : : simpleTask ( BaseThread * callingThread ) {
2011-12-02 17:07:59 +01:00
MutexSafeWrapper safeMutex ( masterServerThreadAccessor , CODE_AT_LINE ) ;
2011-01-11 09:45:58 +01:00
if ( difftime ( time ( NULL ) , lastMasterserverHeartbeatTime ) > = MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-10-23 11:06:47 +02:00
lastMasterserverHeartbeatTime = time ( NULL ) ;
2010-10-24 00:06:49 +02:00
if ( needToRepublishToMasterserver = = true ) {
2010-12-20 17:45:31 +01:00
try {
2011-01-13 09:17:18 +01:00
if ( Config : : getInstance ( ) . getString ( " Masterserver " , " " ) ! = " " ) {
string request = Config : : getInstance ( ) . getString ( " Masterserver " ) + " addServerInfo.php? " ;
std : : map < string , string > newPublishToServerInfo = publishToMasterserver ( ) ;
CURL * handle = SystemFlags : : initHTTP ( ) ;
for ( std : : map < string , string > : : const_iterator iterMap = newPublishToServerInfo . begin ( ) ;
2011-09-01 20:08:56 +02:00
iterMap ! = newPublishToServerInfo . end ( ) ; + + iterMap ) {
2011-01-13 09:17:18 +01:00
request + = iterMap - > first ;
request + = " = " ;
request + = SystemFlags : : escapeURL ( iterMap - > second , handle ) ;
request + = " & " ;
}
//printf("the request is:\n%s\n",request.c_str());
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line %d] the request is: \n %s \n " , __FILE__ , __FUNCTION__ , __LINE__ , request . c_str ( ) ) ;
2011-01-13 09:17:18 +01:00
std : : string serverInfo = SystemFlags : : getHTTP ( request , handle ) ;
SystemFlags : : cleanupHTTP ( & handle ) ;
//printf("the result is:\n'%s'\n",serverInfo.c_str());
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugNetwork ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line %d] the result is: \n '%s' \n " , __FILE__ , __FUNCTION__ , __LINE__ , serverInfo . c_str ( ) ) ;
2011-01-13 09:17:18 +01:00
}
else {
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line %d] error, no masterserver defined! \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
}
}
catch ( const exception & ex ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line %d] error during game status update: [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , ex . what ( ) ) ;
2010-10-23 11:06:47 +02:00
}
}
}
}
2011-11-23 09:00:09 +01:00
void ServerInterface : : notifyBadClientConnectAttempt ( string ipAddress ) {
//printf("In [%s::%s Line: %d] ipAddress [%s]\n",__FILE__,__FUNCTION__,__LINE__,ipAddress.c_str());
if ( badClientConnectIPList . find ( ipAddress ) = = badClientConnectIPList . end ( ) ) {
badClientConnectIPList [ ipAddress ] = make_pair ( 0 , time ( NULL ) ) ;
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
pair < uint64 , time_t > & lastBadConnectionAttempt = badClientConnectIPList [ ipAddress ] ;
const uint64 BLOCK_BAD_CLIENT_CONNECT_MAX_SECONDS = Config : : getInstance ( ) . getInt ( " BlockBadClientConnectMaxSeconds " , " 60 " ) ;
const uint64 BLOCK_BAD_CLIENT_CONNECT_MAX_ATTEMPTS = Config : : getInstance ( ) . getInt ( " BlockBadClientConnectMaxAttempts " , " 6 " ) ;
bool addToBlockedClientsList = false ;
if ( difftime ( time ( NULL ) , lastBadConnectionAttempt . second ) < = BLOCK_BAD_CLIENT_CONNECT_MAX_SECONDS ) {
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if ( lastBadConnectionAttempt . first + 1 > BLOCK_BAD_CLIENT_CONNECT_MAX_ATTEMPTS ) {
addToBlockedClientsList = true ;
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
}
else {
// Reset after x seconds
lastBadConnectionAttempt . first = 0 ;
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if ( addToBlockedClientsList = = true ) {
serverSocket . addIPAddressToBlockedList ( ipAddress ) ;
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
lastBadConnectionAttempt . first + + ;
lastBadConnectionAttempt . second = time ( NULL ) ;
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
2010-10-23 11:06:47 +02:00
2010-03-17 07:25:19 +01:00
} } //end namespace