- FINALLY fixed freeze with tomreyn's fuzzer and helped further stabilize mutexes and network messages in threads.

This commit is contained in:
Mark Vejvoda
2011-01-13 08:17:18 +00:00
parent 6f601777ef
commit 469cf14b92
7 changed files with 963 additions and 1099 deletions

View File

@@ -808,7 +808,7 @@ void printParameterHelp(const char *argv0, bool foundInvalidArgs) {
printf("\n%s=x\t\t\tdisplays merged ini settings information.",GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]); printf("\n%s=x\t\t\tdisplays merged ini settings information.",GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]);
printf("\n \t\tWhere x is an optional property name to filter (default shows all)."); printf("\n \t\tWhere x is an optional property name to filter (default shows all).");
printf("\n \t\texample: %s %s=DebugMode",argv0,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]); printf("\n \t\texample: %s %s=DebugMode",argv0,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]);
printf("\n%s\t\t\tdisables stack backtrace on errors.",GAME_ARGS[GAME_ARG_DISABLE_BACKTRACE]); printf("\n%s\t\tdisables stack backtrace on errors.",GAME_ARGS[GAME_ARG_DISABLE_BACKTRACE]);
printf("\n%s\t\t\tdisplays verbose information in the console.",GAME_ARGS[GAME_ARG_VERBOSE_MODE]); printf("\n%s\t\t\tdisplays verbose information in the console.",GAME_ARGS[GAME_ARG_VERBOSE_MODE]);
printf("\n\n"); printf("\n\n");

View File

@@ -277,17 +277,14 @@ ConnectionSlot::~ConnectionSlot() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
} }
void ConnectionSlot::update() { void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
try {
clearThreadErrorList();
if(slotThreadWorker != NULL) { if(slotThreadWorker != NULL) {
slotThreadWorker->purgeCompletedEvents(); slotThreadWorker->purgeCompletedEvents();
} }
update(true);
}
void ConnectionSlot::update(bool checkForNewClients) {
clearThreadErrorList();
try {
if(socket == NULL) { if(socket == NULL) {
if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap = false; if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap = false;
if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false; if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false;
@@ -295,7 +292,6 @@ void ConnectionSlot::update(bool checkForNewClients) {
this->setReceivedDataSynchCheck(false); this->setReceivedDataSynchCheck(false);
// Is the listener socket ready to be read? // Is the listener socket ready to be read?
//if(serverInterface->getServerSocket()->isReadable() == true)
if(checkForNewClients == true) { if(checkForNewClients == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] BEFORE accept new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] BEFORE accept new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount());
bool hasOpenSlots = (serverInterface->getOpenSlotCount() > 0); bool hasOpenSlots = (serverInterface->getOpenSlotCount() > 0);
@@ -466,7 +462,6 @@ void ConnectionSlot::update(bool checkForNewClients) {
//check consistency //check consistency
bool compatible = checkVersionComptability(getNetworkVersionString(), networkMessageIntro.getVersionString()); bool compatible = checkVersionComptability(getNetworkVersionString(), networkMessageIntro.getVersionString());
if(compatible == false) { if(compatible == false) {
//if(networkMessageIntro.getVersionString() != getNetworkVersionString()) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
bool versionMatched = false; bool versionMatched = false;
@@ -479,10 +474,10 @@ void ConnectionSlot::update(bool checkForNewClients) {
"\nClient: " + networkMessageIntro.getVersionString() + " player [" + playerNameStr + "]"; "\nClient: " + networkMessageIntro.getVersionString() + " player [" + playerNameStr + "]";
printf("%s\n",sErr.c_str()); printf("%s\n",sErr.c_str());
serverInterface->sendTextMessage("Server and client binary mismatch!!",-1, true); serverInterface->sendTextMessage("Server and client binary mismatch!!",-1, true,lockedSlotIndex);
serverInterface->sendTextMessage(" Server:" + getNetworkVersionString(),-1, true); serverInterface->sendTextMessage(" Server:" + getNetworkVersionString(),-1, true,lockedSlotIndex);
serverInterface->sendTextMessage(" Client: "+ networkMessageIntro.getVersionString(),-1, true); serverInterface->sendTextMessage(" Client: "+ networkMessageIntro.getVersionString(),-1, true,lockedSlotIndex);
serverInterface->sendTextMessage(" Client player [" + playerNameStr + "]",-1, true); serverInterface->sendTextMessage(" Client player [" + playerNameStr + "]",-1, true,lockedSlotIndex);
} }
else { else {
versionMatched = true; versionMatched = true;
@@ -492,18 +487,11 @@ void ConnectionSlot::update(bool checkForNewClients) {
"\nClient: " + networkMessageIntro.getVersionString() + " player [" + playerNameStr + "]"; "\nClient: " + networkMessageIntro.getVersionString() + " player [" + playerNameStr + "]";
printf("%s\n",sErr.c_str()); printf("%s\n",sErr.c_str());
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
//sendTextMessage("Server and client have different platform mismatch.",-1, true);
//sendTextMessage(" Server:" + networkMessageIntro.getVersionString(),-1, true);
//sendTextMessage(" Client: "+ getNetworkVersionString(),-1, true);
//sendTextMessage(" Client player [" + playerNameStr + "]",-1, true);
} }
if(Config::getInstance().getBool("PlatformConsistencyChecks","true") && if(Config::getInstance().getBool("PlatformConsistencyChecks","true") &&
versionMatched == false) { // error message and disconnect only if checked versionMatched == false) { // error message and disconnect only if checked
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
//DisplayErrorMessage(sErr);
//quit= true;
close(); close();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,sErr.c_str());
return; return;

View File

@@ -127,8 +127,7 @@ public:
ConnectionSlot(ServerInterface* serverInterface, int playerIndex); ConnectionSlot(ServerInterface* serverInterface, int playerIndex);
~ConnectionSlot(); ~ConnectionSlot();
void update(bool checkForNewClients); void update(bool checkForNewClients,int lockedSlotIndex);
virtual void update();
void setPlayerIndex(int value) { playerIndex = value; } void setPlayerIndex(int value) { playerIndex = value; }
int getPlayerIndex() {return playerIndex;} int getPlayerIndex() {return playerIndex;}
@@ -181,6 +180,8 @@ protected:
Mutex * getServerSynchAccessor(); Mutex * getServerSynchAccessor();
std::vector<std::string> threadErrorList; std::vector<std::string> threadErrorList;
Mutex socketSynchAccessor; Mutex socketSynchAccessor;
virtual void update() {}
}; };
}}//end namespace }}//end namespace

View File

@@ -418,6 +418,12 @@ NetworkMessageText::NetworkMessageText(const string &text, int teamIndex, int pl
data.playerIndex = playerIndex; data.playerIndex = playerIndex;
} }
NetworkMessageText * NetworkMessageText::getCopy() const {
NetworkMessageText *copy = new NetworkMessageText();
copy->data = this->data;
return copy;
}
bool NetworkMessageText::receive(Socket* socket){ bool NetworkMessageText::receive(Socket* socket){
bool result = NetworkMessage::receive(socket, &data, sizeof(data)); bool result = NetworkMessage::receive(socket, &data, sizeof(data));

View File

@@ -319,6 +319,7 @@ public:
virtual bool receive(Socket* socket); virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const; virtual void send(Socket* socket) const;
NetworkMessageText * getCopy() const;
}; };
#pragma pack(pop) #pragma pack(pop)

View File

@@ -30,17 +30,19 @@ using namespace Shared::Platform;
using namespace Shared::Util; using namespace Shared::Util;
namespace Glest { namespace Game { namespace Glest { namespace Game {
bool enabledThreadedClientCommandBroadcast = false;
double maxFrameCountLagAllowed = 30; double maxFrameCountLagAllowed = 30;
double maxClientLagTimeAllowed = 20; double maxClientLagTimeAllowed = 20;
double maxFrameCountLagAllowedEver = 50; double maxFrameCountLagAllowedEver = 50;
double warnFrameCountLagPercent = 0.65; double warnFrameCountLagPercent = 0.65;
double LAG_CHECK_GRACE_PERIOD = 15; double LAG_CHECK_GRACE_PERIOD = 15;
double MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE = 1; double MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE = 1;
ServerInterface::ServerInterface() const int MAX_SLOT_THREAD_WAIT_TIME = 3;
:GameNetworkInterface() const int MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS = 30;
{
ServerInterface::ServerInterface() :GameNetworkInterface() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
nextEventId = 1; nextEventId = 1;
gameHasBeenInitiated = false; gameHasBeenInitiated = false;
exitServer = false; exitServer = false;
@@ -51,21 +53,26 @@ namespace Glest{ namespace Game{
lastMasterserverHeartbeatTime = 0; lastMasterserverHeartbeatTime = 0;
needToRepublishToMasterserver = false; needToRepublishToMasterserver = false;
ftpServer = NULL; ftpServer = NULL;
enabledThreadedClientCommandBroadcast = Config::getInstance().getBool("EnableThreadedClientCommandBroadcast", "false"); inBroadcastMessage = false;
maxFrameCountLagAllowed = Config::getInstance().getInt("MaxFrameCountLagAllowed", intToStr(maxFrameCountLagAllowed).c_str()); maxFrameCountLagAllowed = Config::getInstance().getInt("MaxFrameCountLagAllowed", intToStr(maxFrameCountLagAllowed).c_str());
maxFrameCountLagAllowedEver = Config::getInstance().getInt("MaxFrameCountLagAllowedEver", intToStr(maxFrameCountLagAllowedEver).c_str()); maxFrameCountLagAllowedEver = Config::getInstance().getInt("MaxFrameCountLagAllowedEver", intToStr(maxFrameCountLagAllowedEver).c_str());
maxClientLagTimeAllowed = Config::getInstance().getInt("MaxClientLagTimeAllowed", intToStr(maxClientLagTimeAllowed).c_str()); maxClientLagTimeAllowed = Config::getInstance().getInt("MaxClientLagTimeAllowed", intToStr(maxClientLagTimeAllowed).c_str());
warnFrameCountLagPercent = Config::getInstance().getFloat("WarnFrameCountLagPercent", doubleToStr(warnFrameCountLagPercent).c_str()); warnFrameCountLagPercent = Config::getInstance().getFloat("WarnFrameCountLagPercent", doubleToStr(warnFrameCountLagPercent).c_str());
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] enabledThreadedClientCommandBroadcast = %d, maxFrameCountLagAllowed = %f, maxFrameCountLagAllowedEver = %f, maxClientLagTimeAllowed = %f\n",__FILE__,__FUNCTION__,__LINE__,enabledThreadedClientCommandBroadcast,maxFrameCountLagAllowed,maxFrameCountLagAllowedEver,maxClientLagTimeAllowed);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] maxFrameCountLagAllowed = %f, maxFrameCountLagAllowedEver = %f, maxClientLagTimeAllowed = %f\n",__FILE__,__FUNCTION__,__LINE__,maxFrameCountLagAllowed,maxFrameCountLagAllowedEver,maxClientLagTimeAllowed);
for(int i= 0; i < GameConstants::maxPlayers; ++i) { for(int i= 0; i < GameConstants::maxPlayers; ++i) {
slots[i] = NULL; slots[i] = NULL;
switchSetupRequests[i] = NULL; switchSetupRequests[i] = NULL;
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
serverSocket.setBlock(false); serverSocket.setBlock(false);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
serverSocket.setBindPort(Config::getInstance().getInt("ServerPort", intToStr(GameConstants::serverPort).c_str())); serverSocket.setBindPort(Config::getInstance().getInt("ServerPort", intToStr(GameConstants::serverPort).c_str()));
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(Config::getInstance().getBool("EnableFTPServer","true") == true) { if(Config::getInstance().getBool("EnableFTPServer","true") == true) {
std::pair<string,string> mapsPath; std::pair<string,string> mapsPath;
vector<string> pathList = Config::getInstance().getPathListForType(ptMaps); vector<string> pathList = Config::getInstance().getPathListForType(ptMaps);
@@ -94,8 +101,7 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
ServerInterface::~ServerInterface() ServerInterface::~ServerInterface() {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
exitServer = true; exitServer = true;
for(int i= 0; i < GameConstants::maxPlayers; ++i) { for(int i= 0; i < GameConstants::maxPlayers; ++i) {
@@ -110,6 +116,7 @@ namespace Glest{ namespace Game{
switchSetupRequests[i]=NULL; switchSetupRequests[i]=NULL;
} }
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
close(); close();
if(ftpServer != NULL) { if(ftpServer != NULL) {
@@ -128,8 +135,7 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
int ServerInterface::isValidClientType(uint32 clientIp) int ServerInterface::isValidClientType(uint32 clientIp) {
{
int result = 0; int result = 0;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
if(slots[i] != NULL) { if(slots[i] != NULL) {
@@ -148,13 +154,11 @@ namespace Glest{ namespace Game{
return result; return result;
} }
void ServerInterface::addClientToServerIPAddress(uint32 clientIp, uint32 ServerIp) void ServerInterface::addClientToServerIPAddress(uint32 clientIp, uint32 ServerIp) {
{
FTPServerThread::addClientToServerIPAddress(clientIp, ServerIp); FTPServerThread::addClientToServerIPAddress(clientIp, ServerIp);
} }
void ServerInterface::addSlot(int playerIndex) void ServerInterface::addSlot(int playerIndex) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
assert(playerIndex >= 0 && playerIndex < GameConstants::maxPlayers); assert(playerIndex >= 0 && playerIndex < GameConstants::maxPlayers);
MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__));
@@ -162,6 +166,7 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
serverSocket.bind(serverSocket.getBindPort()); serverSocket.bind(serverSocket.getBindPort());
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + "_" + intToStr(playerIndex)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + "_" + intToStr(playerIndex));
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
@@ -180,14 +185,14 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
bool ServerInterface::switchSlot(int fromPlayerIndex, int toPlayerIndex) bool ServerInterface::switchSlot(int fromPlayerIndex, int toPlayerIndex) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
bool result = false; bool result = false;
assert(fromPlayerIndex >= 0 && fromPlayerIndex < GameConstants::maxPlayers); assert(fromPlayerIndex >= 0 && fromPlayerIndex < GameConstants::maxPlayers);
assert(toPlayerIndex >= 0 && toPlayerIndex < GameConstants::maxPlayers); assert(toPlayerIndex >= 0 && toPlayerIndex < GameConstants::maxPlayers);
if(fromPlayerIndex == toPlayerIndex) if(fromPlayerIndex == toPlayerIndex) {
return false; return false;
}
MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__));
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[fromPlayerIndex],intToStr(__LINE__) + "_" + intToStr(fromPlayerIndex)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[fromPlayerIndex],intToStr(__LINE__) + "_" + intToStr(fromPlayerIndex));
@@ -205,7 +210,8 @@ namespace Glest{ namespace Game{
safeMutexSlot2.ReleaseLock(); safeMutexSlot2.ReleaseLock();
result = true; result = true;
updateListen(); updateListen();
}else{ }
else {
safeMutexSlot.ReleaseLock(); safeMutexSlot.ReleaseLock();
safeMutexSlot2.ReleaseLock(); safeMutexSlot2.ReleaseLock();
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
@@ -214,8 +220,7 @@ namespace Glest{ namespace Game{
return result; return result;
} }
void ServerInterface::removeSlot(int playerIndex, int lockedSlotIndex) void ServerInterface::removeSlot(int playerIndex, int lockedSlotIndex) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex);
MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__));
MutexSafeWrapper safeMutexSlot(NULL,intToStr(__LINE__) + "_" + intToStr(playerIndex)); MutexSafeWrapper safeMutexSlot(NULL,intToStr(__LINE__) + "_" + intToStr(playerIndex));
@@ -249,6 +254,7 @@ namespace Glest{ namespace Game{
delete slot; delete slot;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex);
updateListen(); updateListen();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex);
if(notifyDisconnect == true) { if(notifyDisconnect == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex);
@@ -259,13 +265,11 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex);
} }
ConnectionSlot *ServerInterface::getSlot(int playerIndex) ConnectionSlot *ServerInterface::getSlot(int playerIndex) {
{
return slots[playerIndex]; return slots[playerIndex];
} }
bool ServerInterface::hasClientConnection() bool ServerInterface::hasClientConnection() {
{
bool result = false; bool result = false;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
@@ -277,8 +281,7 @@ namespace Glest{ namespace Game{
return result; return result;
} }
int ServerInterface::getConnectedSlotCount() int ServerInterface::getConnectedSlotCount() {
{
int connectedSlotCount = 0; int connectedSlotCount = 0;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
@@ -289,8 +292,7 @@ namespace Glest{ namespace Game{
return connectedSlotCount; return connectedSlotCount;
} }
int64 ServerInterface::getNextEventId() int64 ServerInterface::getNextEventId() {
{
nextEventId++; nextEventId++;
if(nextEventId > INT_MAX) { if(nextEventId > INT_MAX) {
nextEventId = 1; nextEventId = 1;
@@ -298,8 +300,7 @@ namespace Glest{ namespace Game{
return nextEventId; return nextEventId;
} }
void ServerInterface::slotUpdateTask(ConnectionSlotEvent *event) void ServerInterface::slotUpdateTask(ConnectionSlotEvent *event) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(event != NULL) { if(event != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] event->eventType = %d\n",__FILE__,__FUNCTION__,__LINE__,event->eventType); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] event->eventType = %d\n",__FILE__,__FUNCTION__,__LINE__,event->eventType);
@@ -320,8 +321,7 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
void ServerInterface::updateSlot(ConnectionSlotEvent *event) void ServerInterface::updateSlot(ConnectionSlotEvent *event) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(event != NULL) { if(event != NULL) {
bool &socketTriggered = event->socketTriggered; bool &socketTriggered = event->socketTriggered;
@@ -343,7 +343,7 @@ namespace Glest{ namespace Game{
(gameHasBeenInitiated == false || (gameHasBeenInitiated == false ||
(connectionSlot->getSocket() != NULL && socketTriggered == true))) { (connectionSlot->getSocket() != NULL && socketTriggered == true))) {
if(connectionSlot->isConnected() == false || socketTriggered == true) { if(connectionSlot->isConnected() == false || socketTriggered == true) {
connectionSlot->update(checkForNewClients); connectionSlot->update(checkForNewClients,event->triggerId);
// This means no clients are trying to connect at the moment // This means no clients are trying to connect at the moment
if(connectionSlot != NULL && connectionSlot->getSocket() == NULL) { if(connectionSlot != NULL && connectionSlot->getSocket() == NULL) {
@@ -356,13 +356,13 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
std::pair<bool,bool> ServerInterface::clientLagCheck(ConnectionSlot *connectionSlot, bool skipNetworkBroadCast) std::pair<bool,bool> ServerInterface::clientLagCheck(ConnectionSlot *connectionSlot, bool skipNetworkBroadCast) {
{
std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false, false); std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false, false);
static bool alreadyInLagCheck = false; static bool alreadyInLagCheck = false;
if(alreadyInLagCheck == true) { if(alreadyInLagCheck == true) {
return clientLagExceededOrWarned; return clientLagExceededOrWarned;
} }
try { try {
alreadyInLagCheck = true; alreadyInLagCheck = true;
@@ -471,18 +471,18 @@ namespace Glest{ namespace Game{
bool ServerInterface::signalClientReceiveCommands(ConnectionSlot *connectionSlot, int slotIndex, bool socketTriggered, ConnectionSlotEvent & event) { bool ServerInterface::signalClientReceiveCommands(ConnectionSlot *connectionSlot, int slotIndex, bool socketTriggered, ConnectionSlotEvent & event) {
bool slotSignalled = false; bool slotSignalled = false;
event.eventType = eReceiveSocketData; event.eventType = eReceiveSocketData;
event.networkMessage = NULL; event.networkMessage = NULL;
event.connectionSlot = connectionSlot; event.connectionSlot = connectionSlot;
event.socketTriggered = socketTriggered; event.socketTriggered = socketTriggered;
event.triggerId = slotIndex; event.triggerId = slotIndex;
event.eventId = getNextEventId(); event.eventId = getNextEventId();
if(connectionSlot != NULL) { if(connectionSlot != NULL) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex);
if(socketTriggered == true || connectionSlot->isConnected() == false) { if(socketTriggered == true || connectionSlot->isConnected() == false) {
connectionSlot->signalUpdate(&event); connectionSlot->signalUpdate(&event);
slotSignalled = true; slotSignalled = true;
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex);
} }
} }
return slotSignalled; return slotSignalled;
@@ -504,52 +504,15 @@ namespace Glest{ namespace Game{
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i]; ConnectionSlot* connectionSlot = slots[i];
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Slot # %d\n",__FILE__,__FUNCTION__,__LINE__,i);
if(connectionSlot != NULL) { if(connectionSlot != NULL) {
connectionSlot->validateConnection(); connectionSlot->validateConnection();
} }
} }
} }
void ServerInterface::signalClientsToRecieveDataX(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList, std::map<int,ConnectionSlotEvent> & eventList, std::map<int,bool> & mapSlotSignalledList) void ServerInterface::signalClientsToRecieveData(std::map<PLATFORM_SOCKET,bool> &socketTriggeredList,
{ std::map<int,ConnectionSlotEvent> &eventList,
bool checkForNewClients = true; std::map<int,bool> & mapSlotSignalledList) {
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i];
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
bool socketTriggered = false;
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL) {
socketTriggered = socketTriggeredList[connectionSlot->getSocket()->getSocketId()];
}
ConnectionSlotEvent &event = eventList[i];
mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
}
}
void ServerInterface::test(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList, std::map<int,ConnectionSlotEvent> & eventList, std::map<int,bool> & mapSlotSignalledList)
{
bool checkForNewClients = true;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i];
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
bool socketTriggered = false;
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL) {
socketTriggered = socketTriggeredList[connectionSlot->getSocket()->getSocketId()];
}
ConnectionSlotEvent &event = eventList[i];
mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
}
}
void ServerInterface::fsf(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList, std::map<int,ConnectionSlotEvent> & eventList, std::map<int,bool> & mapSlotSignalledList)
{
bool checkForNewClients = true; bool checkForNewClients = true;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
@@ -564,47 +527,9 @@ namespace Glest{ namespace Game{
} }
} }
void ServerInterface::update() { void ServerInterface::checkForCompletedClients(std::map<int,bool> & mapSlotSignalledList,
const int MAX_SLOT_THREAD_WAIT_TIME = 3; std::vector <string> &errorMsgList,
std::vector < string > errorMsgList; std::map<int,ConnectionSlotEvent> &eventList) {
try {
// The first thing we will do is check all clients to ensure they have
// properly identified themselves within the alloted time period
validateConnectedClients();
processTextMessageQueue();
processBroadCastMessageQueue();
std::map<PLATFORM_SOCKET,bool> socketTriggeredList;
//update all slots
updateSocketTriggeredList(socketTriggeredList);
if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0) {
std::map<int,ConnectionSlotEvent> eventList;
bool hasData = Socket::hasDataToRead(socketTriggeredList);
if(hasData) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
if(gameHasBeenInitiated == false || hasData == true) {
std::map<int,bool> mapSlotSignalledList;
// Step #1 tell all connection slot worker threads to receive socket data
bool checkForNewClients = true;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i];
bool socketTriggered = false;
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL) {
socketTriggered = socketTriggeredList[connectionSlot->getSocket()->getSocketId()];
}
ConnectionSlotEvent &event = eventList[i];
mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #2\n",__FILE__,__FUNCTION__,__LINE__);
// Step #2 check all connection slot worker threads for completed status
time_t waitForThreadElapsed = time(NULL); time_t waitForThreadElapsed = time(NULL);
std::map<int,bool> slotsCompleted; std::map<int,bool> slotsCompleted;
for(bool threadsDone = false; for(bool threadsDone = false;
@@ -648,14 +573,15 @@ namespace Glest{ namespace Game{
} }
} }
} }
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #3\n",__FILE__,__FUNCTION__,__LINE__); void ServerInterface::checForLaggingClients(std::map<int,bool> &mapSlotSignalledList,
std::map<int,ConnectionSlotEvent> &eventList,
// Step #3 check clients for any lagging scenarios and try to deal with them std::map<PLATFORM_SOCKET,bool> &socketTriggeredList,
std::vector <string> &errorMsgList) {
time_t waitForClientsElapsed = time(NULL); time_t waitForClientsElapsed = time(NULL);
waitForThreadElapsed = time(NULL); time_t waitForThreadElapsed = time(NULL);
slotsCompleted.clear(); std::map<int,bool> slotsCompleted;
//std::map<int,bool> slotsWarnedAndRetried;
std::map<int,bool> slotsWarnedList; std::map<int,bool> slotsWarnedList;
for(bool threadsDone = false; for(bool threadsDone = false;
exitServer == false && threadsDone == false && exitServer == false && threadsDone == false &&
@@ -735,10 +661,9 @@ namespace Glest{ namespace Game{
} }
} }
} }
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #4\n",__FILE__,__FUNCTION__,__LINE__); void ServerInterface::executeNetworkCommandsFromClients() {
// Step #4 dispatch network commands to the pending list so that they are done in proper order
if(gameHasBeenInitiated == true) { if(gameHasBeenInitiated == true) {
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
@@ -754,9 +679,9 @@ namespace Glest{ namespace Game{
} }
} }
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #5\n",__FILE__,__FUNCTION__,__LINE__); }
// Step #5 dispatch pending chat messages void ServerInterface::dispatchPendingChatMessages(std::vector <string> &errorMsgList) {
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
@@ -798,7 +723,49 @@ namespace Glest{ namespace Game{
} }
} }
} }
}
void ServerInterface::update() {
std::vector <string> errorMsgList;
try {
// The first thing we will do is check all clients to ensure they have
// properly identified themselves within the alloted time period
validateConnectedClients();
processTextMessageQueue();
processBroadCastMessageQueue();
std::map<PLATFORM_SOCKET,bool> socketTriggeredList;
//update all slots
updateSocketTriggeredList(socketTriggeredList);
if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0) {
std::map<int,ConnectionSlotEvent> eventList;
bool hasData = Socket::hasDataToRead(socketTriggeredList);
if(hasData) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
if(gameHasBeenInitiated == false || hasData == true) {
std::map<int,bool> mapSlotSignalledList;
// Step #1 tell all connection slot worker threads to receive socket data
signalClientsToRecieveData(socketTriggeredList, eventList, mapSlotSignalledList);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #2\n",__FILE__,__FUNCTION__,__LINE__);
// Step #2 check all connection slot worker threads for completed status
checkForCompletedClients(mapSlotSignalledList,errorMsgList, eventList);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #3\n",__FILE__,__FUNCTION__,__LINE__);
// Step #3 check clients for any lagging scenarios and try to deal with them
checForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #4\n",__FILE__,__FUNCTION__,__LINE__);
// Step #4 dispatch network commands to the pending list so that they are done in proper order
executeNetworkCommandsFromClients();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #5\n",__FILE__,__FUNCTION__,__LINE__);
// Step #5 dispatch pending chat messages
dispatchPendingChatMessages(errorMsgList);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
} }
} }
@@ -820,8 +787,7 @@ namespace Glest{ namespace Game{
} }
void ServerInterface::updateKeyframe(int frameCount) void ServerInterface::updateKeyframe(int frameCount) {
{
Chrono chrono; Chrono chrono;
chrono.start(); chrono.start();
currentFrameCount = frameCount; currentFrameCount = frameCount;
@@ -831,7 +797,8 @@ namespace Glest{ namespace Game{
if(networkMessageCommandList.addCommand(&requestedCommands.back())){ if(networkMessageCommandList.addCommand(&requestedCommands.back())){
pendingCommands.push_back(requestedCommands.back()); pendingCommands.push_back(requestedCommands.back());
requestedCommands.pop_back(); requestedCommands.pop_back();
}else{ }
else {
break; break;
} }
} }
@@ -861,8 +828,7 @@ namespace Glest{ namespace Game{
if(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); if(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);
} }
bool ServerInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMessageType, ConnectionSlot *connectionSlot) bool ServerInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMessageType, ConnectionSlot *connectionSlot) {
{
bool discard = false; bool discard = false;
if(connectionSlot != NULL) { if(connectionSlot != NULL) {
switch(networkMessageType) { switch(networkMessageType) {
@@ -959,14 +925,15 @@ namespace Glest{ namespace Game{
return discard; return discard;
} }
void ServerInterface::waitUntilReady(Checksum *checksum) void ServerInterface::waitUntilReady(Checksum *checksum) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] START\n",__FUNCTION__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] START\n",__FUNCTION__);
Logger & logger = Logger::getInstance(); Logger & logger = Logger::getInstance();
gameHasBeenInitiated = true; gameHasBeenInitiated = true;
Chrono chrono; Chrono chrono;
bool allReady = false;
chrono.start(); chrono.start();
bool allReady = false;
while(exitServer == false && allReady == false) { while(exitServer == false && allReady == false) {
vector<string> waitingForHosts; vector<string> waitingForHosts;
allReady= true; allReady= true;
@@ -988,14 +955,12 @@ namespace Glest{ namespace Game{
connectionSlot->setReady(); connectionSlot->setReady();
} }
else if(networkMessageType != nmtInvalid) { else if(networkMessageType != nmtInvalid) {
//throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
string sErr = "Unexpected network message: " + intToStr(networkMessageType); string sErr = "Unexpected network message: " + intToStr(networkMessageType);
sendTextMessage(sErr,-1, true,i); sendTextMessage(sErr,-1, true,i);
DisplayErrorMessage(sErr); DisplayErrorMessage(sErr);
return; return;
} }
} }
//waitingForHosts.push_back(connectionSlot->getHostName());
waitingForHosts.push_back(connectionSlot->getName()); waitingForHosts.push_back(connectionSlot->getName());
allReady= false; allReady= false;
@@ -1006,7 +971,6 @@ namespace Glest{ namespace Game{
//check for timeout //check for timeout
if(allReady == false) { if(allReady == false) {
if(chrono.getMillis() > readyWaitTimeout) { if(chrono.getMillis() > readyWaitTimeout) {
//throw runtime_error("Timeout waiting for clients");
string sErr = "Timeout waiting for clients."; string sErr = "Timeout waiting for clients.";
sendTextMessage(sErr,-1, true); sendTextMessage(sErr,-1, true);
DisplayErrorMessage(sErr); DisplayErrorMessage(sErr);
@@ -1051,8 +1015,7 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] END\n",__FUNCTION__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] END\n",__FUNCTION__);
} }
void ServerInterface::processBroadCastMessageQueue() void ServerInterface::processBroadCastMessageQueue() {
{
MutexSafeWrapper safeMutexSlot(&broadcastMessageQueueThreadAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutexSlot(&broadcastMessageQueueThreadAccessor,intToStr(__LINE__));
if(broadcastMessageQueue.size() > 0) { if(broadcastMessageQueue.size() > 0) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] broadcastMessageQueue.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,broadcastMessageQueue.size()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] broadcastMessageQueue.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,broadcastMessageQueue.size());
@@ -1068,8 +1031,7 @@ namespace Glest{ namespace Game{
} }
} }
void ServerInterface::queueBroadcastMessage(const NetworkMessage *networkMessage, int excludeSlot) void ServerInterface::queueBroadcastMessage(const NetworkMessage *networkMessage, int excludeSlot) {
{
MutexSafeWrapper safeMutexSlot(&broadcastMessageQueueThreadAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutexSlot(&broadcastMessageQueueThreadAccessor,intToStr(__LINE__));
pair<const NetworkMessage*,int> item; pair<const NetworkMessage*,int> item;
item.first = networkMessage; item.first = networkMessage;
@@ -1077,8 +1039,7 @@ namespace Glest{ namespace Game{
broadcastMessageQueue.push_back(item); broadcastMessageQueue.push_back(item);
} }
void ServerInterface::processTextMessageQueue() void ServerInterface::processTextMessageQueue() {
{
MutexSafeWrapper safeMutexSlot(&textMessageQueueThreadAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutexSlot(&textMessageQueueThreadAccessor,intToStr(__LINE__));
if(textMessageQueue.size() > 0) { if(textMessageQueue.size() > 0) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] textMessageQueue.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,textMessageQueue.size()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] textMessageQueue.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,textMessageQueue.size());
@@ -1090,8 +1051,7 @@ namespace Glest{ namespace Game{
} }
} }
void ServerInterface::queueTextMessage(const string & text, int teamIndex, bool echoLocal) void ServerInterface::queueTextMessage(const string & text, int teamIndex, bool echoLocal) {
{
MutexSafeWrapper safeMutexSlot(&textMessageQueueThreadAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutexSlot(&textMessageQueueThreadAccessor,intToStr(__LINE__));
TextMessageQueue item; TextMessageQueue item;
item.text = text; item.text = text;
@@ -1100,13 +1060,11 @@ namespace Glest{ namespace Game{
textMessageQueue.push_back(item); textMessageQueue.push_back(item);
} }
void ServerInterface::sendTextMessage(const string & text, int teamIndex, bool echoLocal) void ServerInterface::sendTextMessage(const string & text, int teamIndex, bool echoLocal) {
{
sendTextMessage(text, teamIndex, echoLocal, -1); sendTextMessage(text, teamIndex, echoLocal, -1);
} }
void ServerInterface::sendTextMessage(const string & text, int teamIndex, bool echoLocal, int lockedSlotIndex) void ServerInterface::sendTextMessage(const string & text, int teamIndex, bool echoLocal, int lockedSlotIndex) {
{
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); 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);
NetworkMessageText networkMessageText(text, teamIndex, getHumanPlayerIndex()); NetworkMessageText networkMessageText(text, teamIndex, getHumanPlayerIndex());
broadcastMessage(&networkMessageText, -1, lockedSlotIndex); broadcastMessage(&networkMessageText, -1, lockedSlotIndex);
@@ -1120,20 +1078,16 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
} }
void ServerInterface::quitGame(bool userManuallyQuit) void ServerInterface::quitGame(bool userManuallyQuit) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(userManuallyQuit == true){
}
NetworkMessageQuit networkMessageQuit; NetworkMessageQuit networkMessageQuit;
broadcastMessage(&networkMessageQuit); broadcastMessage(&networkMessageQuit);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
} }
string ServerInterface::getNetworkStatus() string ServerInterface::getNetworkStatus() {
{
Lang &lang = Lang::getInstance(); Lang &lang = Lang::getInstance();
string str; string str="";
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
@@ -1145,10 +1099,9 @@ namespace Glest{ namespace Game{
int clientLagCount = connectionSlot->getCurrentLagCount(); int clientLagCount = connectionSlot->getCurrentLagCount();
double lastClientCommandListTimeLag = difftime(time(NULL),connectionSlot->getLastReceiveCommandListTime()); double lastClientCommandListTimeLag = difftime(time(NULL),connectionSlot->getLastReceiveCommandListTime());
//float pingTime = connectionSlot->getThreadedPingMS(connectionSlot->getIpAddress().c_str()); //float pingTime = connectionSlot->getThreadedPingMS(connectionSlot->getIpAddress().c_str());
char szBuf[100]=""; char szBuf[1024]="";
//sprintf(szBuf,", lag = %d [%.2f], ping = %.2fms",clientLagCount,lastClientCommandListTimeLag,pingTime); //sprintf(szBuf,", lag = %d [%.2f], ping = %.2fms",clientLagCount,lastClientCommandListTimeLag,pingTime);
sprintf(szBuf,", lag = %d [%.2f]",clientLagCount,lastClientCommandListTimeLag); sprintf(szBuf,", lag = %d [%.2f]",clientLagCount,lastClientCommandListTimeLag);
str+= connectionSlot->getName() + string(szBuf); str+= connectionSlot->getName() + string(szBuf);
} }
} }
@@ -1161,8 +1114,7 @@ namespace Glest{ namespace Game{
return str; return str;
} }
bool ServerInterface::launchGame(const GameSettings *gameSettings) bool ServerInterface::launchGame(const GameSettings *gameSettings) {
{
bool bOkToStart = true; bool bOkToStart = true;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
@@ -1205,7 +1157,6 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] needToRepublishToMasterserver = %d\n",__FILE__,__FUNCTION__,__LINE__,needToRepublishToMasterserver); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] needToRepublishToMasterserver = %d\n",__FILE__,__FUNCTION__,__LINE__,needToRepublishToMasterserver);
if(needToRepublishToMasterserver == true) { if(needToRepublishToMasterserver == true) {
//publishToMasterserverThread = new SimpleTaskThread(this,0,25);
publishToMasterserverThread = new SimpleTaskThread(this,0,125); publishToMasterserverThread = new SimpleTaskThread(this,0,125);
publishToMasterserverThread->setUniqueID(__FILE__); publishToMasterserverThread->setUniqueID(__FILE__);
publishToMasterserverThread->start(); publishToMasterserverThread->start();
@@ -1223,8 +1174,7 @@ namespace Glest{ namespace Game{
return bOkToStart; return bOkToStart;
} }
void ServerInterface::broadcastGameSetup(const GameSettings *gameSettings) void ServerInterface::broadcastGameSetup(const GameSettings *gameSettings) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__));
NetworkMessageLaunch networkMessageLaunch(gameSettings, nmtBroadCastSetup); NetworkMessageLaunch networkMessageLaunch(gameSettings, nmtBroadCastSetup);
@@ -1232,93 +1182,27 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
} }
void ServerInterface::broadcastMessage(const NetworkMessage *networkMessage, int excludeSlot, int lockedSlotIndex) void ServerInterface::broadcastMessage(const NetworkMessage *networkMessage, int excludeSlot, int lockedSlotIndex) {
{
try { try {
if(enabledThreadedClientCommandBroadcast == true) {
// Step #1 signal worker threads to send this broadcast to each client
std::map<int,ConnectionSlotEvent> eventList;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(NULL,intToStr(__LINE__) + "_" + intToStr(i));
if(i != lockedSlotIndex) {
safeMutexSlot.setMutex(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
}
ConnectionSlot* connectionSlot = slots[i];
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] networkMessage = %p\n",__FILE__,__FUNCTION__,__LINE__,networkMessage);
ConnectionSlotEvent &event = eventList[i];
event.eventType = eSendSocketData;
event.networkMessage = networkMessage;
event.connectionSlot = connectionSlot;
event.socketTriggered = true;
event.triggerId = i;
event.eventId = getNextEventId();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// Step #1 tell all connection slot worker threads to receive socket data MutexSafeWrapper safeMutexSlotBroadCastAccessor(&inBroadcastMessageThreadAccessor,intToStr(__LINE__));
if(i != excludeSlot && connectionSlot != NULL) { if(inBroadcastMessage == true && dynamic_cast<const NetworkMessageText *>(networkMessage) != NULL) {
if(connectionSlot->isConnected()) { safeMutexSlotBroadCastAccessor.ReleaseLock();
connectionSlot->signalUpdate(&event); const NetworkMessageText *txtMsg = dynamic_cast<const NetworkMessageText *>(networkMessage);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); const NetworkMessageText *msgCopy = txtMsg->getCopy();
} queueBroadcastMessage(msgCopy, excludeSlot);
else if(gameHasBeenInitiated == true) { return;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i);
removeSlot(i,i);
}
}
else if(i == excludeSlot &&
gameHasBeenInitiated == true &&
connectionSlot != NULL &&
connectionSlot->isConnected() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i);
removeSlot(i,i);
}
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// Step #2 check all connection slot worker threads for completed status
std::map<int,bool> slotsCompleted;
for(bool threadsDone = false; exitServer == false && threadsDone == false;) {
threadsDone = true;
// Examine all threads for completion of delegation
for(int i = 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(NULL,intToStr(__LINE__) + "_" + intToStr(i));
if(i != lockedSlotIndex) {
safeMutexSlot.setMutex(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
}
ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && slotsCompleted.find(i) == slotsCompleted.end()) {
std::vector<std::string> errorList = connectionSlot->getThreadErrorList();
if(errorList.size() > 0) {
for(int iErrIdx = 0; iErrIdx < errorList.size(); ++iErrIdx) {
string &sErr = errorList[iErrIdx];
DisplayErrorMessage(sErr);
}
connectionSlot->clearThreadErrorList();
}
if(connectionSlot->updateCompleted(&eventList[i]) == false) {
threadsDone = false;
break;
} }
else { else {
slotsCompleted[i] = true; inBroadcastMessage = true;
safeMutexSlotBroadCastAccessor.ReleaseLock(true);
} }
}
}
}
}
else {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(NULL,intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(NULL,intToStr(__LINE__) + "_" + intToStr(i));
if(i != lockedSlotIndex) { if(i != lockedSlotIndex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] i = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,i,lockedSlotIndex);
safeMutexSlot.setMutex(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); safeMutexSlot.setMutex(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
} }
@@ -1328,11 +1212,13 @@ namespace Glest{ namespace Game{
if(connectionSlot->isConnected()) { if(connectionSlot->isConnected()) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] before sendMessage\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] before sendMessage\n",__FILE__,__FUNCTION__,__LINE__);
connectionSlot->sendMessage(networkMessage); connectionSlot->sendMessage(networkMessage);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] after sendMessage\n",__FILE__,__FUNCTION__,__LINE__);
} }
else if(gameHasBeenInitiated == true) { if(gameHasBeenInitiated == true && connectionSlot->isConnected() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i);
//safeMutexSlot.ReleaseLock(); //safeMutexSlot.ReleaseLock();
removeSlot(i,i); removeSlot(i,i);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 after removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i);
} }
} }
else if(i == excludeSlot && gameHasBeenInitiated == true && else if(i == excludeSlot && gameHasBeenInitiated == true &&
@@ -1340,23 +1226,28 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i);
//safeMutexSlot.ReleaseLock(); //safeMutexSlot.ReleaseLock();
removeSlot(i,i); removeSlot(i,i);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #2 after removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i);
} }
} }
}
safeMutexSlotBroadCastAccessor.Lock();
inBroadcastMessage = false;
safeMutexSlotBroadCastAccessor.ReleaseLock();
} }
catch(const exception &ex) { catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
//throw runtime_error(ex.what());
//DisplayErrorMessage(ex.what()); MutexSafeWrapper safeMutexSlotBroadCastAccessor(&inBroadcastMessageThreadAccessor,intToStr(__LINE__));
inBroadcastMessage = false;
safeMutexSlotBroadCastAccessor.ReleaseLock();
string sMsg = ex.what(); string sMsg = ex.what();
sendTextMessage(sMsg,-1, true, lockedSlotIndex); sendTextMessage(sMsg,-1, true, lockedSlotIndex);
} }
} }
void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage *networkMessage, int excludeSlot) void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage *networkMessage, int excludeSlot) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
try { try {
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
@@ -1365,8 +1256,6 @@ namespace Glest{ namespace Game{
if(i != excludeSlot && connectionSlot != NULL) { if(i != excludeSlot && connectionSlot != NULL) {
if(connectionSlot->isConnected()) { if(connectionSlot->isConnected()) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
connectionSlot->sendMessage(networkMessage); connectionSlot->sendMessage(networkMessage);
} }
} }
@@ -1375,14 +1264,12 @@ namespace Glest{ namespace Game{
catch(const exception &ex) { catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
//throw runtime_error(ex.what());
DisplayErrorMessage(ex.what()); DisplayErrorMessage(ex.what());
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
} }
void ServerInterface::updateListen() void ServerInterface::updateListen() {
{
if(gameHasBeenInitiated == true){ if(gameHasBeenInitiated == true){
return; return;
} }
@@ -1398,8 +1285,7 @@ namespace Glest{ namespace Game{
serverSocket.listen(openSlotCount); serverSocket.listen(openSlotCount);
} }
int ServerInterface::getOpenSlotCount() int ServerInterface::getOpenSlotCount() {
{
int openSlotCount = 0; int openSlotCount = 0;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
//MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); //MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
@@ -1412,21 +1298,17 @@ namespace Glest{ namespace Game{
return openSlotCount; return openSlotCount;
} }
void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck) void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START gameSettingsUpdateCount = %d, waitForClientAck = %d\n",__FILE__,__FUNCTION__,gameSettingsUpdateCount,waitForClientAck); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START gameSettingsUpdateCount = %d, waitForClientAck = %d\n",__FILE__,__FUNCTION__,gameSettingsUpdateCount,waitForClientAck);
MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__));
gameSettings = *serverGameSettings; gameSettings = *serverGameSettings;
if(getAllowGameDataSynchCheck() == true) if(getAllowGameDataSynchCheck() == true) {
{ if(waitForClientAck == true && gameSettingsUpdateCount > 0) {
if(waitForClientAck == true && gameSettingsUpdateCount > 0)
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Waiting for client acks #1\n",__FILE__,__FUNCTION__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Waiting for client acks #1\n",__FILE__,__FUNCTION__);
time_t tStart = time(NULL); time_t tStart = time(NULL);
bool gotAckFromAllClients = false; bool gotAckFromAllClients = false;
while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) {
{
gotAckFromAllClients = true; gotAckFromAllClients = true;
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
@@ -1436,7 +1318,7 @@ namespace Glest{ namespace Game{
gotAckFromAllClients = false; gotAckFromAllClients = false;
} }
connectionSlot->update(); connectionSlot->update(true,i);
} }
} }
} }
@@ -1468,7 +1350,7 @@ namespace Glest{ namespace Game{
gotAckFromAllClients = false; gotAckFromAllClients = false;
} }
connectionSlot->update(); connectionSlot->update(true,i);
} }
} }
} }
@@ -1479,13 +1361,11 @@ namespace Glest{ namespace Game{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
} }
void ServerInterface::close() void ServerInterface::close() {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START\n",__FILE__,__FUNCTION__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START\n",__FILE__,__FUNCTION__);
} }
string ServerInterface::getHumanPlayerName(int index) string ServerInterface::getHumanPlayerName(int index) {
{
string result = Config::getInstance().getString("NetPlayerName", Socket::getHostName().c_str()); string result = Config::getInstance().getString("NetPlayerName", Socket::getHostName().c_str());
if(index >= 0 || gameSettings.getThisFactionIndex() >= 0) { if(index >= 0 || gameSettings.getThisFactionIndex() >= 0) {
if(index < 0) { if(index < 0) {
@@ -1499,13 +1379,11 @@ namespace Glest{ namespace Game{
return result; return result;
} }
int ServerInterface::getHumanPlayerIndex() const int ServerInterface::getHumanPlayerIndex() const {
{
return gameSettings.getStartLocationIndex(gameSettings.getThisFactionIndex()); return gameSettings.getStartLocationIndex(gameSettings.getThisFactionIndex());
} }
std::map<string,string> ServerInterface::publishToMasterserver() std::map<string,string> ServerInterface::publishToMasterserver() {
{
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
int slotCountUsed = 1; int slotCountUsed = 1;
int slotCountHumans = 1; int slotCountHumans = 1;
@@ -1544,19 +1422,15 @@ namespace Glest{ namespace Game{
return publishToServerInfo; return publishToServerInfo;
} }
void ServerInterface::simpleTask(BaseThread *callingThread) void ServerInterface::simpleTask(BaseThread *callingThread) {
{
MutexSafeWrapper safeMutex(&masterServerThreadAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutex(&masterServerThreadAccessor,intToStr(__LINE__));
const int MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS = 30;
if(difftime(time(NULL),lastMasterserverHeartbeatTime) >= MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS) { if(difftime(time(NULL),lastMasterserverHeartbeatTime) >= MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
lastMasterserverHeartbeatTime = time(NULL); lastMasterserverHeartbeatTime = time(NULL);
if(needToRepublishToMasterserver == true) { if(needToRepublishToMasterserver == true) {
try { try {
if(Config::getInstance().getString("Masterserver","") != "") { if(Config::getInstance().getString("Masterserver","") != "") {
//string request = Config::getInstance().getString("Masterserver") + "addServerInfo.php?" + newPublishToServerInfo;
string request = Config::getInstance().getString("Masterserver") + "addServerInfo.php?"; string request = Config::getInstance().getString("Masterserver") + "addServerInfo.php?";
std::map<string,string> newPublishToServerInfo = publishToMasterserver(); std::map<string,string> newPublishToServerInfo = publishToMasterserver();
@@ -1579,12 +1453,6 @@ namespace Glest{ namespace Game{
//printf("the result is:\n'%s'\n",serverInfo.c_str()); //printf("the result is:\n'%s'\n",serverInfo.c_str());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] the result is:\n'%s'\n",__FILE__,__FUNCTION__,__LINE__,serverInfo.c_str()); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] the result is:\n'%s'\n",__FILE__,__FUNCTION__,__LINE__,serverInfo.c_str());
// uncomment to enable router setup check of this server
if(EndsWith(serverInfo, "OK") == false) {
//showMasterserverError=true;
//masterServererErrorToShow = (serverInfo != "" ? serverInfo : "No Reply");
}
} }
else { else {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line %d] error, no masterserver defined!\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line %d] error, no masterserver defined!\n",__FILE__,__FUNCTION__,__LINE__);

View File

@@ -70,6 +70,9 @@ private:
Mutex broadcastMessageQueueThreadAccessor; Mutex broadcastMessageQueueThreadAccessor;
vector<pair<const NetworkMessage *,int> > broadcastMessageQueue; vector<pair<const NetworkMessage *,int> > broadcastMessageQueue;
Mutex inBroadcastMessageThreadAccessor;
bool inBroadcastMessage;
public: public:
ServerInterface(); ServerInterface();
virtual ~ServerInterface(); virtual ~ServerInterface();
@@ -83,11 +86,7 @@ public:
virtual void close(); virtual void close();
virtual void update(); virtual void update();
virtual void updateLobby() virtual void updateLobby() { };
{
}
;
virtual void updateKeyframe(int frameCount); virtual void updateKeyframe(int frameCount);
virtual void waitUntilReady(Checksum *checksum); virtual void waitUntilReady(Checksum *checksum);
virtual void sendTextMessage(const string & text, int teamIndex, bool echoLocal = false); virtual void sendTextMessage(const string & text, int teamIndex, bool echoLocal = false);
@@ -159,8 +158,7 @@ public:
} }
public: public:
Mutex *getServerSynchAccessor() Mutex *getServerSynchAccessor() {
{
return &serverSynchAccessor; return &serverSynchAccessor;
} }
@@ -177,10 +175,12 @@ private:
int64 getNextEventId(); int64 getNextEventId();
void processTextMessageQueue(); void processTextMessageQueue();
void processBroadCastMessageQueue(); void processBroadCastMessageQueue();
void fsf(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList, std::map<int,ConnectionSlotEvent> & eventList, std::map<int,bool> & mapSlotSignalledList);
protected: protected:
void signalClientsToRecieveDataX(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList, std::map<int,ConnectionSlotEvent> & eventList, std::map<int,bool> & mapSlotSignalledList); void signalClientsToRecieveData(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList, std::map<int,ConnectionSlotEvent> & eventList, std::map<int,bool> & mapSlotSignalledList);
void test(std::map<PLATFORM_SOCKET,bool> & socketTriggeredList, std::map<int,ConnectionSlotEvent> & eventList, std::map<int,bool> & mapSlotSignalledList); void checkForCompletedClients(std::map<int,bool> & mapSlotSignalledList,std::vector <string> &errorMsgList,std::map<int,ConnectionSlotEvent> &eventList);
void checForLaggingClients(std::map<int,bool> &mapSlotSignalledList, std::map<int,ConnectionSlotEvent> &eventList, std::map<PLATFORM_SOCKET,bool> &socketTriggeredList,std::vector <string> &errorMsgList);
void executeNetworkCommandsFromClients();
void dispatchPendingChatMessages(std::vector <string> &errorMsgList);
}; };
}}//end namespace }}//end namespace