- Added partial threaded network server handling of incoming socket data to try to improve performance

- Small changes to client network handling to be more accurate and efficient
- Added observer mode when a user loses a network game
This commit is contained in:
Mark Vejvoda 2010-05-15 18:59:17 +00:00
parent 9ab6732f86
commit 1ae2a9ae10
11 changed files with 499 additions and 189 deletions

View File

@ -37,11 +37,13 @@ ChatManager::ChatManager(){
editEnabled= false;
teamMode= false;
thisTeamIndex= -1;
disableTeamMode = false;
}
void ChatManager::init(Console* console, int thisTeamIndex){
this->console= console;
this->thisTeamIndex= thisTeamIndex;
this->disableTeamMode= false;
}
void ChatManager::keyUp(char key){
@ -64,6 +66,13 @@ void ChatManager::keyUp(char key){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void ChatManager::setDisableTeamMode(bool value) {
disableTeamMode = value;
if(disableTeamMode == true) {
teamMode = false;
}
}
void ChatManager::keyDown(char key){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
@ -72,7 +81,7 @@ void ChatManager::keyDown(char key){
Lang &lang= Lang::getInstance();
//toggle team mode
if(!editEnabled && key=='H'){
if(editEnabled == false && disableTeamMode == false && key=='H') {
if(teamMode){
teamMode= false;
console->addLine(lang.get("ChatMode") + ": " + lang.get("All"));

View File

@ -31,6 +31,7 @@ private:
private:
bool editEnabled;
bool teamMode;
bool disableTeamMode;
Console* console;
string text;
int thisTeamIndex;
@ -47,6 +48,9 @@ public:
bool getEditEnabled() const {return editEnabled;}
bool getTeamMode() const {return teamMode;}
string getText() const {return text;}
bool getDisableTeamMode() const { return disableTeamMode; }
void setDisableTeamMode(bool value);
};
}}//end namespace

View File

@ -375,17 +375,17 @@ Command* Commander::buildCommand(const NetworkCommand* networkCommand) const{
//validate unit
if(unit == NULL) {
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s - %d] Can not find unit with id: %d. Game out of synch.",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId());
sprintf(szBuf,"In [%s::%s Line: %d] Can not find unit with id: %d. Game out of synch.",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId());
throw runtime_error(szBuf);
}
else if(unit->getType() == NULL) {
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s - %d] unit->getType() == NULL for unit with id: %d",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId());
sprintf(szBuf,"In [%s::%s Line: %d] unit->getType() == NULL for unit with id: %d",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId());
throw runtime_error(szBuf);
}
else if(unit->getFaction() == NULL) {
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s - %d] unit->getFaction() == NULL for unit with id: %d",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId());
sprintf(szBuf,"In [%s::%s Line: %d] unit->getFaction() == NULL for unit with id: %d",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId());
throw runtime_error(szBuf);
}
@ -395,8 +395,8 @@ Command* Commander::buildCommand(const NetworkCommand* networkCommand) const{
//validate command type
if(ct == NULL) {
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s - %d] Can not find command type with id = %d\n%s\n in unit = %d [%s][%s].\nGame out of synch.",
__FILE__,__FUNCTION__,__LINE__,networkCommand->getCommandTypeId(),unit->getType()->getCommandTypeListDesc().c_str(),unit->getId(), unit->getFullName().c_str(),unit->getDesc().c_str());
sprintf(szBuf,"In [%s::%s Line: %d] Can not find command type for network command = [%s]\n%s\n in unit = %d [%s][%s].\nGame out of synch.",
__FILE__,__FUNCTION__,__LINE__,networkCommand->toString().c_str(),unit->getType()->getCommandTypeListDesc().c_str(),unit->getId(), unit->getFullName().c_str(),unit->getDesc().c_str());
throw runtime_error(szBuf);
}

View File

@ -1,4 +1,3 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
@ -1061,36 +1060,43 @@ void Game::checkWinner(){
void Game::checkWinnerStandard(){
//lose
bool lose= false;
if(!hasBuilding(world.getThisFaction())){
if(hasBuilding(world.getThisFaction()) == false) {
lose= true;
for(int i=0; i<world.getFactionCount(); ++i){
if(!world.getFaction(i)->isAlly(world.getThisFaction())){
for(int i=0; i<world.getFactionCount(); ++i) {
if(world.getFaction(i)->isAlly(world.getThisFaction()) == false) {
world.getStats()->setVictorious(i);
}
}
gameOver= true;
// Let the poor user watch everything unfold
world.setFogOfWar(false);
// but don't let him cheat via teamchat
chatManager.setDisableTeamMode(true);
showLoseMessageBox();
}
//win
if(!lose){
if(lose == false) {
bool win= true;
for(int i=0; i<world.getFactionCount(); ++i){
for(int i=0; i<world.getFactionCount(); ++i) {
if(i!=world.getThisFactionIndex()){
if(hasBuilding(world.getFaction(i)) && !world.getFaction(i)->isAlly(world.getThisFaction())){
if(hasBuilding(world.getFaction(i)) && world.getFaction(i)->isAlly(world.getThisFaction()) == false) {
win= false;
}
}
}
//if win
if(win){
for(int i=0; i< world.getFactionCount(); ++i){
if(world.getFaction(i)->isAlly(world.getThisFaction())){
if(win) {
for(int i=0; i< world.getFactionCount(); ++i) {
if(world.getFaction(i)->isAlly(world.getThisFaction())) {
world.getStats()->setVictorious(i);
}
}
gameOver= true;
// Let the happy winner view everything left in the world
world.setFogOfWar(false);
showWinMessageBox();
}
}
@ -1169,7 +1175,14 @@ int Game::getUpdateLoops(){
void Game::showLoseMessageBox(){
Lang &lang= Lang::getInstance();
showMessageBox(lang.get("YouLose")+", "+lang.get("ExitGame?"), lang.get("BattleOver"), false);
NetworkManager &networkManager= NetworkManager::getInstance();
if(networkManager.isNetworkGame() == true && networkManager.getNetworkRole() == nrServer) {
showMessageBox(lang.get("YouLose")+", "+lang.get("ExitGameServer?"), lang.get("BattleOver"), false);
}
else {
showMessageBox(lang.get("YouLose")+", "+lang.get("ExitGame?"), lang.get("BattleOver"), false);
}
}
void Game::showWinMessageBox(){

View File

@ -428,8 +428,7 @@ void ClientInterface::updateKeyframe(int frameCount)
{
bool done= false;
while(done == false)
{
while(done == false) {
//wait for the next message
waitForMessage();
@ -446,9 +445,10 @@ void ClientInterface::updateKeyframe(int frameCount)
int waitCount = 0;
//make sure we read the message
NetworkMessageCommandList networkMessageCommandList;
while(receiveMessage(&networkMessageCommandList) == false)
{
sleep(waitSleepTime);
while(receiveMessage(&networkMessageCommandList) == false &&
isConnected() == true) {
//sleep(waitSleepTime);
sleep(0);
waitCount++;
}
@ -456,8 +456,7 @@ void ClientInterface::updateKeyframe(int frameCount)
chrono.start();
//check that we are in the right frame
if(networkMessageCommandList.getFrameCount() != frameCount)
{
if(networkMessageCommandList.getFrameCount() != frameCount) {
string sErr = "Network synchronization error, frame counts do not match";
//throw runtime_error("Network synchronization error, frame counts do not match");
sendTextMessage(sErr,-1);
@ -468,8 +467,7 @@ void ClientInterface::updateKeyframe(int frameCount)
}
// give all commands
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i)
{
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i) {
pendingCommands.push_back(*networkMessageCommandList.getCommand(i));
}
@ -482,10 +480,12 @@ void ClientInterface::updateKeyframe(int frameCount)
case nmtQuit:
{
NetworkMessageQuit networkMessageQuit;
if(receiveMessage(&networkMessageQuit))
{
quit= true;
//if(receiveMessage(&networkMessageQuit)) {
while(receiveMessage(&networkMessageQuit) == false &&
isConnected() == true) {
sleep(0);
}
quit= true;
done= true;
}
break;
@ -493,12 +493,14 @@ void ClientInterface::updateKeyframe(int frameCount)
case nmtText:
{
NetworkMessageText networkMessageText;
if(receiveMessage(&networkMessageText))
{
chatText = networkMessageText.getText();
chatSender = networkMessageText.getSender();
chatTeamIndex = networkMessageText.getTeamIndex();
while(receiveMessage(&networkMessageText) == false &&
isConnected() == true) {
sleep(0);
}
chatText = networkMessageText.getText();
chatSender = networkMessageText.getSender();
chatTeamIndex = networkMessageText.getTeamIndex();
}
break;
case nmtInvalid:
@ -673,10 +675,8 @@ void ClientInterface::waitForMessage()
chrono.start();
int waitLoopCount = 0;
while(getNextMessageType(true) == nmtInvalid)
{
if(isConnected() == false)
{
while(getNextMessageType(true) == nmtInvalid) {
if(isConnected() == false) {
//throw runtime_error("Disconnected");
sendTextMessage("Server has Disconnected.",-1);
DisplayErrorMessage("Server has Disconnected.");
@ -685,8 +685,7 @@ void ClientInterface::waitForMessage()
return;
}
if(chrono.getMillis() > messageWaitTimeout)
{
if(chrono.getMillis() > messageWaitTimeout) {
//throw runtime_error("Timeout waiting for message");
sendTextMessage("Timeout waiting for message",-1);
DisplayErrorMessage("Timeout waiting for message");

View File

@ -60,15 +60,12 @@ ConnectionSlot::~ConnectionSlot()
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ConnectionSlot::update()
{
void ConnectionSlot::update() {
update(true);
}
void ConnectionSlot::update(bool checkForNewClients)
{
if(socket == NULL)
{
void ConnectionSlot::update(bool checkForNewClients) {
if(socket == NULL) {
if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap = false;
if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false;
if(networkGameDataSynchCheckOkTech) networkGameDataSynchCheckOkTech = false;
@ -76,8 +73,7 @@ void ConnectionSlot::update(bool checkForNewClients)
// 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());
bool hasOpenSlots = (serverInterface->getOpenSlotCount() > 0);
if(serverInterface->getServerSocket()->hasDataToRead() == true) {
@ -110,10 +106,8 @@ void ConnectionSlot::update(bool checkForNewClients)
}
}
}
else
{
if(socket->isConnected())
{
else {
if(socket->isConnected()) {
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
@ -121,7 +115,7 @@ void ConnectionSlot::update(bool checkForNewClients)
NetworkMessageType networkMessageType= getNextMessageType();
//process incoming commands
switch(networkMessageType){
switch(networkMessageType) {
case nmtInvalid:
break;
@ -131,8 +125,7 @@ void ConnectionSlot::update(bool checkForNewClients)
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__);
NetworkMessageText networkMessageText;
if(receiveMessage(&networkMessageText))
{
if(receiveMessage(&networkMessageText)) {
chatText = networkMessageText.getText();
chatSender = networkMessageText.getSender();
chatTeamIndex = networkMessageText.getTeamIndex();
@ -148,10 +141,8 @@ void ConnectionSlot::update(bool checkForNewClients)
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtCommandList\n",__FILE__,__FUNCTION__);
NetworkMessageCommandList networkMessageCommandList;
if(receiveMessage(&networkMessageCommandList))
{
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i)
{
if(receiveMessage(&networkMessageCommandList)) {
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i) {
serverInterface->requestCommand(networkMessageCommandList.getCommand(i));
}
}
@ -222,19 +213,15 @@ void ConnectionSlot::update(bool checkForNewClients)
if( networkGameDataSynchCheckOkMap == true &&
networkGameDataSynchCheckOkTile == true &&
networkGameDataSynchCheckOkTech == true) // &&
//networkGameDataSynchCheckOkFogOfWar == true)
{
networkGameDataSynchCheckOkTech == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] client data synch ok\n",__FILE__,__FUNCTION__);
}
else
{
else {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] mapCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameDataStatus.getMapCRC());
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] tilesetCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameDataStatus.getTilesetCRC());
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] techCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameDataStatus.getTechCRC());
if(allowDownloadDataSynch == true)
{
if(allowDownloadDataSynch == true) {
// Now get all filenames with their CRC values and send to the client
vctFileList.clear();
@ -250,34 +237,27 @@ void ConnectionSlot::update(bool checkForNewClients)
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getGameSettings()->getScenarioDir().c_str(),serverInterface->getGameSettings()->getScenario().c_str(),scenarioDir.c_str());
}
if(networkGameDataSynchCheckOkTile == false)
{
if(tilesetCRC == 0)
{
if(networkGameDataSynchCheckOkTile == false) {
if(tilesetCRC == 0) {
//vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_tilesets) + "/" + serverInterface->getGameSettings()->getTileset() + "/*", "", &vctFileList);
vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + serverInterface->getGameSettings()->getTileset() + string("/*"), "", &vctFileList);
}
else
{
else {
//vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_tilesets) + "/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList);
vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTilesets,scenarioDir), "/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList);
}
}
if(networkGameDataSynchCheckOkTech == false)
{
if(techCRC == 0)
{
if(networkGameDataSynchCheckOkTech == false) {
if(techCRC == 0) {
//vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_techs) + "/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList);
vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList);
}
else
{
else {
//vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_techs) + "/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList);
vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList);
}
}
if(networkGameDataSynchCheckOkMap == false)
{
if(networkGameDataSynchCheckOkMap == false) {
vctFileList.push_back(std::pair<string,int32>(Map::getMapPath(serverInterface->getGameSettings()->getMap(),scenarioDir),mapCRC));
}
@ -313,8 +293,7 @@ void ConnectionSlot::update(bool checkForNewClients)
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataFileGet\n",__FILE__,__FUNCTION__);
NetworkMessageSynchNetworkGameDataFileGet networkMessageSynchNetworkGameDataFileGet;
if(receiveMessage(&networkMessageSynchNetworkGameDataFileGet))
{
if(receiveMessage(&networkMessageSynchNetworkGameDataFileGet)) {
FileTransferInfo fileInfo;
fileInfo.hostType = eServer;
//fileInfo.serverIP = this->ip.getString();
@ -330,10 +309,8 @@ void ConnectionSlot::update(bool checkForNewClients)
case nmtSwitchSetupRequest:
{
SwitchSetupRequest switchSetupRequest;
if(receiveMessage(&switchSetupRequest))
{
if(serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()]==NULL)
{
if(receiveMessage(&switchSetupRequest)) {
if(serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()]==NULL) {
serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()]= new SwitchSetupRequest();
}
*(serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()])=switchSetupRequest;
@ -367,8 +344,7 @@ void ConnectionSlot::update(bool checkForNewClients)
close();
}
}
else
{
else {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling close...\n",__FILE__,__FUNCTION__);
close();
@ -376,8 +352,7 @@ void ConnectionSlot::update(bool checkForNewClients)
}
}
void ConnectionSlot::close()
{
void ConnectionSlot::close() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START\n",__FILE__,__FUNCTION__);
delete socket;
@ -394,15 +369,7 @@ void ConnectionSlot::close()
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
/*
bool ConnectionSlot::getFogOfWar()
{
return networkGameDataSynchCheckOkFogOfWar;
}
*/
bool ConnectionSlot::hasValidSocketId()
{
bool ConnectionSlot::hasValidSocketId() {
bool result = (socket != NULL && socket->getSocketId() > 0);
return result;
}

View File

@ -0,0 +1,58 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martio Figueroa
//
// 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
// ==============================================================
#ifndef _GLEST_GAME_NETWORKMANAGER_H_
#define _GLEST_GAME_NETWORKMANAGER_H_
#include <cassert>
#include "socket.h"
#include "checksum.h"
#include "server_interface.h"
#include "client_interface.h"
using Shared::Util::Checksum;
namespace Glest{ namespace Game{
// =====================================================
// class NetworkManager
// =====================================================
enum NetworkRole{
nrServer,
nrClient,
nrIdle
};
class NetworkManager{
private:
GameNetworkInterface* gameNetworkInterface;
NetworkRole networkRole;
public:
static NetworkManager &getInstance();
NetworkManager();
void init(NetworkRole networkRole);
void end();
void update();
bool isNetworkGame();
GameNetworkInterface* getGameNetworkInterface();
ServerInterface* getServerInterface();
ClientInterface* getClientInterface();
NetworkRole getNetworkRole() { return networkRole; }
};
}}//end namespace
#endif

View File

@ -37,6 +37,7 @@ NetworkCommand::NetworkCommand(World *world, int networkCommandType, int unitId,
, wantQueue(wantQueue) {
assert(targetId == -1 || facing == -1);
this->targetId = targetId >= 0 ? targetId : facing;
this->fromFactionIndex = world->getThisFactionIndex();
if(this->networkCommandType == nctGiveCommand) {
const Unit *unit= world->findUnitById(this->unitId);
@ -74,8 +75,8 @@ void NetworkCommand::preprocessNetworkCommand(World *world) {
string NetworkCommand::toString() const {
char szBuf[1024]="";
sprintf(szBuf,"networkCommandType = %d\nunitId = %d\ncommandTypeId = %d\npositionX = %d\nthis->positionY = %d\nunitTypeId = %d\ntargetId = %d\nwantQueue= %d",
networkCommandType,unitId,commandTypeId,positionX,this->positionY,unitTypeId,targetId,wantQueue);
sprintf(szBuf,"networkCommandType = %d\nunitId = %d\ncommandTypeId = %d\npositionX = %d\npositionY = %d\nunitTypeId = %d\ntargetId = %d\nwantQueue= %d\nfromFactionIndex = %d",
networkCommandType,unitId,commandTypeId,positionX,this->positionY,unitTypeId,targetId,wantQueue,fromFactionIndex);
string result = szBuf;
return result;

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
// Copyright (C) 2001-2008 Martio Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
@ -68,6 +68,7 @@ private:
int16 unitTypeId;
int16 targetId;
int16 wantQueue;
int16 fromFactionIndex;
public:
NetworkCommand(){};
@ -91,6 +92,7 @@ public:
int getUnitTypeId() const {return unitTypeId;}
int getTargetId() const {return targetId;}
int getWantQueue() const {return wantQueue;}
int getFromFactionIndex() const {return fromFactionIndex;}
void preprocessNetworkCommand(World *world);
string toString() const;

View File

@ -30,6 +30,113 @@ using namespace Shared::Util;
namespace Glest{ namespace Game{
ConnectionSlotThread::ConnectionSlotThread() : BaseThread() {
this->slotInterface = NULL;
}
ConnectionSlotThread::ConnectionSlotThread(ConnectionSlotCallbackInterface *slotInterface) : BaseThread() {
this->slotInterface = slotInterface;
}
void ConnectionSlotThread::setQuitStatus(bool value) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d value = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
BaseThread::setQuitStatus(value);
if(value == true) {
signalUpdate(NULL);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
void ConnectionSlotThread::signalUpdate(ConnectionSlotEvent *event) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(event != NULL) {
triggerIdMutex.p();
this->event = event;
triggerIdMutex.v();
}
semTaskSignalled.signal();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
void ConnectionSlotThread::setTaskCompleted(ConnectionSlotEvent *event) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(event != NULL) {
triggerIdMutex.p();
event->eventCompleted = true;
triggerIdMutex.v();
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
bool ConnectionSlotThread::isSignalCompleted() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
triggerIdMutex.p();
bool result = this->event->eventCompleted;
triggerIdMutex.v();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
return result;
}
void ConnectionSlotThread::execute() {
try {
setRunningStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
unsigned int idx = 0;
for(;this->slotInterface != NULL;) {
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
semTaskSignalled.waitTillSignalled();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
this->slotInterface->slotUpdateTask(this->event);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
setTaskCompleted(this->event);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
catch(const exception &ex) {
setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw runtime_error(ex.what());
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(false);
}
// =====================================================
// class ServerInterface
// =====================================================
@ -41,6 +148,7 @@ ServerInterface::ServerInterface(){
for(int i= 0; i<GameConstants::maxPlayers; ++i){
slots[i]= NULL;
switchSetupRequests[i]= NULL;
slotThreads[i] = NULL;
}
serverSocket.setBlock(false);
serverSocket.bind(Config::getInstance().getInt("ServerPort",intToStr(GameConstants::serverPort).c_str()));
@ -50,6 +158,10 @@ ServerInterface::~ServerInterface(){
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START\n",__FILE__,__FUNCTION__);
for(int i= 0; i<GameConstants::maxPlayers; ++i){
BaseThread::shutdownAndWait(slotThreads[i]);
delete slotThreads[i];
slotThreads[i] = NULL;
delete slots[i];
slots[i]=NULL;
delete switchSetupRequests[i];
@ -71,12 +183,15 @@ void ServerInterface::addSlot(int playerIndex){
slots[playerIndex]= new ConnectionSlot(this, playerIndex);
updateListen();
slotThreads[playerIndex] = new ConnectionSlotThread(this);
slotThreads[playerIndex]->start();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
bool ServerInterface::switchSlot(int fromPlayerIndex,int toPlayerIndex){
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START\n",__FILE__,__FUNCTION__);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
bool result=false;
assert(fromPlayerIndex>=0 && fromPlayerIndex<GameConstants::maxPlayers);
assert(toPlayerIndex>=0 && toPlayerIndex<GameConstants::maxPlayers);
@ -95,19 +210,27 @@ bool ServerInterface::switchSlot(int fromPlayerIndex,int toPlayerIndex){
result=true;
updateListen();
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
return result;
}
void ServerInterface::removeSlot(int playerIndex){
void ServerInterface::removeSlot(int playerIndex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START\n",__FILE__,__FUNCTION__);
//BaseThread::shutdownAndWait(slotThreads[playerIndex]);
//delete slotThreads[playerIndex];
//slotThreads[playerIndex] = NULL;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex);
delete slots[playerIndex];
slots[playerIndex]= NULL;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex);
updateListen();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex);
}
ConnectionSlot* ServerInterface::getSlot(int playerIndex){
@ -125,83 +248,139 @@ int ServerInterface::getConnectedSlotCount(){
return connectedSlotCount;
}
void ServerInterface::update()
{
void ServerInterface::slotUpdateTask(ConnectionSlotEvent *event) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(event != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
updateSlot(event);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void ServerInterface::updateSlot(ConnectionSlotEvent *event) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(event != NULL) {
ConnectionSlot *connectionSlot = event->connectionSlot;
bool &socketTriggered = event->socketTriggered;
bool checkForNewClients = true;
if(connectionSlot != NULL &&
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggered == true))) {
if(connectionSlot->isConnected() == false || socketTriggered == true) {
if(gameHasBeenInitiated) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socketTriggeredList[i] = %i\n",__FILE__,__FUNCTION__,(socketTriggered ? 1 : 0));
if(connectionSlot->isConnected()) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] about to call connectionSlot->update() for socketId = %d\n",__FILE__,__FUNCTION__,__LINE__,connectionSlot->getSocket()->getSocketId());
}
else {
if(gameHasBeenInitiated) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] getSocket() == NULL\n",__FILE__,__FUNCTION__);
}
connectionSlot->update(checkForNewClients);
// This means no clients are trying to connect at the moment
if(connectionSlot != NULL && connectionSlot->getSocket() == NULL) {
checkForNewClients = false;
}
if(connectionSlot != NULL &&
connectionSlot->getChatText().empty() == false) {
chatText = connectionSlot->getChatText();
chatSender = connectionSlot->getChatSender();
chatTeamIndex = connectionSlot->getChatTeamIndex();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 about to broadcast nmtText chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,chatText.c_str(),chatSender.c_str(),chatTeamIndex);
NetworkMessageText networkMessageText(chatText,chatSender,chatTeamIndex);
broadcastMessage(&networkMessageText, connectionSlot->getPlayerIndex());
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::update() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
std::map<PLATFORM_SOCKET,bool> socketTriggeredList;
//update all slots
for(int i= 0; i < GameConstants::maxPlayers; ++i)
{
for(int i= 0; i < GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL &&
slots[i]->getSocket()->getSocketId() > 0)
{
slots[i]->getSocket()->getSocketId() > 0) {
socketTriggeredList[connectionSlot->getSocket()->getSocketId()] = false;
}
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0)
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0) {
if(gameHasBeenInitiated) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socketTriggeredList.size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
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)
{
//if(gameHasBeenInitiated && Socket::enableNetworkDebugInfo) printf("In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
//std::vector<TeamMessageData> vctTeamMessages;
if(gameHasBeenInitiated == false || hasData == true) {
//update all slots
bool checkForNewClients = true;
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i];
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false);
ConnectionSlotEvent &event = eventList[i];
event.connectionSlot = connectionSlot;
event.socketTriggered = socketTriggered;
event.triggerId = i;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(slotThreads[i] != NULL) {
slotThreads[i]->signalUpdate(&event);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
//updateSlot(event);
/*
if(connectionSlot != NULL &&
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)))
{
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))) {
if(connectionSlot->isConnected() == false ||
(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))
{
(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)) {
if(gameHasBeenInitiated) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socketTriggeredList[i] = %i\n",__FILE__,__FUNCTION__,(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] ? 1 : 0));
if(connectionSlot->isConnected())
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling slots[i]->update() for slot = %d socketId = %d\n",
if(connectionSlot->isConnected()) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] about to call slots[i]->update() for slot = %d socketId = %d\n",
__FILE__,__FUNCTION__,i,connectionSlot->getSocket()->getSocketId());
}
else
{
else {
if(gameHasBeenInitiated) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] slot = %d getSocket() == NULL\n",__FILE__,__FUNCTION__,i);
}
connectionSlot->update(checkForNewClients);
// This means no clients are trying to connect at the moment
if(connectionSlot != NULL && connectionSlot->getSocket() == NULL)
{
if(connectionSlot != NULL && connectionSlot->getSocket() == NULL) {
checkForNewClients = false;
}
if(connectionSlot != NULL &&
//connectionSlot->isConnected() == true &&
connectionSlot->getChatText().empty() == false)
{
connectionSlot->getChatText().empty() == false) {
chatText = connectionSlot->getChatText();
chatSender = connectionSlot->getChatSender();
chatTeamIndex = connectionSlot->getChatTeamIndex();
//TeamMessageData teamMessageData;
//teamMessageData.chatSender = connectionSlot->getChatSender();
//teamMessageData.chatText = connectionSlot->getChatText();
//teamMessageData.chatTeamIndex = connectionSlot->getChatTeamIndex();
//teamMessageData.sourceTeamIndex = i;
//vctTeamMessages.push_back(teamMessageData);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 about to broadcast nmtText chatText [%s] chatSender [%s] chatTeamIndex = %d for SlotIndex# %d\n",__FILE__,__FUNCTION__,__LINE__,chatText.c_str(),chatSender.c_str(),chatTeamIndex,i);
NetworkMessageText networkMessageText(chatText,chatSender,chatTeamIndex);
@ -212,32 +391,51 @@ void ServerInterface::update()
}
}
}
*/
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
std::map<int,bool> slotsCompleted;
for(bool threadsDone = false; threadsDone == false;) {
threadsDone = true;
// Examine all threads for completion of delegation
for(int i= 0; i< GameConstants::maxPlayers; ++i) {
if(slotThreads[i] != NULL && slotsCompleted.find(i) == slotsCompleted.end()) {
if(slotThreads[i]->isSignalCompleted() == false &&
slotThreads[i]->getQuitStatus() == false &&
slotThreads[i]->getRunningStatus() == true) {
threadsDone = false;
break;
}
else {
slotsCompleted[i] = true;
}
}
}
sleep(0);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//process text messages
if(chatText.empty() == true)
{
if(chatText.empty() == true) {
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
for(int i= 0; i< GameConstants::maxPlayers; ++i)
{
for(int i= 0; i< GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot!= NULL &&
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)))
{
if(connectionSlot->isConnected() && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)
{
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))) {
if(connectionSlot->isConnected() && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true) {
if(connectionSlot->getSocket() != NULL) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling connectionSlot->getNextMessageType() for slots[i]->getSocket()->getSocketId() = %d\n",
__FILE__,__FUNCTION__,connectionSlot->getSocket()->getSocketId());
if(connectionSlot->getNextMessageType() == nmtText)
{
if(connectionSlot->getNextMessageType() == nmtText) {
NetworkMessageText networkMessageText;
if(connectionSlot->receiveMessage(&networkMessageText))
{
if(connectionSlot->receiveMessage(&networkMessageText)) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 about to broadcast nmtText msg for SlotIndex# %d\n",__FILE__,__FUNCTION__,i);
broadcastMessage(&networkMessageText, i);
@ -251,8 +449,12 @@ void ServerInterface::update()
}
}
}
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::updateKeyframe(int frameCount){
@ -262,12 +464,12 @@ void ServerInterface::updateKeyframe(int frameCount){
NetworkMessageCommandList networkMessageCommandList(frameCount);
//build command list, remove commands from requested and add to pending
while(!requestedCommands.empty()){
if(networkMessageCommandList.addCommand(&requestedCommands.back())){
while(!requestedCommands.empty()) {
if(networkMessageCommandList.addCommand(&requestedCommands.back())) {
pendingCommands.push_back(requestedCommands.back());
requestedCommands.pop_back();
}
else{
else {
break;
}
}
@ -507,6 +709,8 @@ bool ServerInterface::launchGame(const GameSettings* gameSettings){
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
serverSynchAccessor.p();
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
ConnectionSlot *connectionSlot= slots[i];
@ -522,6 +726,8 @@ bool ServerInterface::launchGame(const GameSettings* gameSettings){
}
}
serverSynchAccessor.v();
if(bOkToStart == true)
{
serverSocket.stopBroadCastThread();
@ -535,7 +741,7 @@ bool ServerInterface::launchGame(const GameSettings* gameSettings){
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__);
NetworkMessageLaunch networkMessageLaunch(gameSettings,nmtBroadCastSetup);
@ -546,61 +752,64 @@ void ServerInterface::broadcastGameSetup(const GameSettings* gameSettings){
void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot){
serverSynchAccessor.p();
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; i<GameConstants::maxPlayers; ++i)
{
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i];
if(i != excludeSlot && connectionSlot != NULL)
{
if(connectionSlot->isConnected())
{
if(i != excludeSlot && connectionSlot != NULL) {
if(connectionSlot->isConnected()) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
connectionSlot->sendMessage(networkMessage);
}
else if(gameHasBeenInitiated == true)
{
else if(gameHasBeenInitiated == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
}
}
else if(i == excludeSlot && gameHasBeenInitiated == true &&
connectionSlot != NULL && connectionSlot->isConnected() == false)
{
connectionSlot != NULL && connectionSlot->isConnected() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
}
}
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
serverSynchAccessor.v();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot){
serverSynchAccessor.p();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
for(int i= 0; i<GameConstants::maxPlayers; ++i){
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i];
if(i!= excludeSlot && connectionSlot!= NULL){
if(connectionSlot->isConnected()){
if(i!= excludeSlot && connectionSlot!= NULL) {
if(connectionSlot->isConnected()) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
connectionSlot->sendMessage(networkMessage);
}
}
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
serverSynchAccessor.v();
}
void ServerInterface::updateListen()
{
void ServerInterface::updateListen() {
if(gameHasBeenInitiated == true) {
return;
}
serverSynchAccessor.p();
int openSlotCount= 0;
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
@ -611,11 +820,15 @@ void ServerInterface::updateListen()
}
serverSocket.listen(openSlotCount);
serverSynchAccessor.v();
}
int ServerInterface::getOpenSlotCount() {
int openSlotCount= 0;
serverSynchAccessor.p();
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
if(slots[i] != NULL && slots[i]->isConnected() == false)
@ -624,6 +837,8 @@ int ServerInterface::getOpenSlotCount() {
}
}
serverSynchAccessor.v();
return openSlotCount;
}

View File

@ -18,32 +18,71 @@
#include "network_interface.h"
#include "connection_slot.h"
#include "socket.h"
#include "base_thread.h"
using std::vector;
using Shared::Platform::ServerSocket;
namespace Glest{ namespace Game{
// =====================================================
// class ConnectionSlotThread
// =====================================================
class ConnectionSlotEvent {
public:
int64 triggerId;
ConnectionSlot* connectionSlot;
bool socketTriggered;
bool eventCompleted;
};
//
// This interface describes the methods a callback object must implement
//
class ConnectionSlotCallbackInterface {
public:
virtual void slotUpdateTask(ConnectionSlotEvent *event) = 0;
};
class ConnectionSlotThread : public BaseThread
{
protected:
ConnectionSlotCallbackInterface *slotInterface;
Semaphore semTaskSignalled;
Mutex triggerIdMutex;
ConnectionSlotEvent *event;
virtual void setQuitStatus(bool value);
virtual void setTaskCompleted(ConnectionSlotEvent *event);
public:
ConnectionSlotThread();
ConnectionSlotThread(ConnectionSlotCallbackInterface *slotInterface);
virtual void execute();
void signalUpdate(ConnectionSlotEvent *event);
bool isSignalCompleted();
};
// =====================================================
// class ServerInterface
// =====================================================
typedef struct
{
string chatText;
string chatSender;
int chatTeamIndex;
int sourceTeamIndex;
class ServerInterface: public GameNetworkInterface, public ConnectionSlotCallbackInterface {
} TeamMessageData;
class ServerInterface: public GameNetworkInterface{
private:
ConnectionSlot* slots[GameConstants::maxPlayers];
ServerSocket serverSocket;
bool gameHasBeenInitiated;
int gameSettingsUpdateCount;
SwitchSetupRequest* switchSetupRequests[GameConstants::maxPlayers];
Mutex serverSynchAccessor;
ConnectionSlotThread* slotThreads[GameConstants::maxPlayers];
public:
ServerInterface();
@ -81,10 +120,13 @@ public:
void updateListen();
virtual bool getConnectHasHandshaked() const { return false; }
virtual void slotUpdateTask(ConnectionSlotEvent *event);
private:
void broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot= -1);
void broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot = -1);
bool shouldDiscardNetworkMessage(NetworkMessageType networkMessageType,ConnectionSlot* connectionSlot);
void updateSlot(ConnectionSlotEvent *event);
};
}}//end namespace