Updated with initial 3.4.4 codebase includes:
- network fixes for multiplayer defects found - initial code (disabled currently) for content crc checking and downloading - code compiles on Win32 using VS2008 express, project files not yet included
This commit is contained in:
parent
58ea5ec552
commit
fb5035c230
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
@ -22,7 +22,7 @@ using namespace Shared::Util;
|
|||
namespace Glest{ namespace Game{
|
||||
|
||||
const string mailString= "contact_game@glest.org";
|
||||
const string glestVersionString= "v3.2.3";
|
||||
const string glestVersionString= "v3.2.4-4-beta1";
|
||||
|
||||
string getCrashDumpFileName(){
|
||||
return "glest"+glestVersionString+".dmp";
|
||||
|
@ -52,11 +52,11 @@ string getAboutString2(int i){
|
|||
|
||||
string getTeammateName(int i){
|
||||
switch(i){
|
||||
case 0: return "Marti<EFBFBD>o Figueroa";
|
||||
case 1: return "Jos<EFBFBD> Luis Gonz<6E>lez";
|
||||
case 2: return "Tucho Fern<EFBFBD>ndez";
|
||||
case 3: return "Jos<EFBFBD> Zanni";
|
||||
case 4: return "F<EFBFBD>lix Men<65>ndez";
|
||||
case 0: return "Martiño Figueroa";
|
||||
case 1: return "José Luis González";
|
||||
case 2: return "Tucho Fernández";
|
||||
case 3: return "José Zanni";
|
||||
case 4: return "Félix Menéndez";
|
||||
case 5: return "Marcos Caruncho";
|
||||
case 6: return "Matthias Braun";
|
||||
}
|
||||
|
|
|
@ -86,16 +86,22 @@ void ChatManager::keyPress(char c){
|
|||
}
|
||||
}
|
||||
|
||||
void ChatManager::updateNetwork(){
|
||||
void ChatManager::updateNetwork()
|
||||
{
|
||||
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
|
||||
string text;
|
||||
string sender;
|
||||
|
||||
if(!gameNetworkInterface->getChatText().empty()){
|
||||
if(!gameNetworkInterface->getChatText().empty())
|
||||
{
|
||||
int teamIndex= gameNetworkInterface->getChatTeamIndex();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtText [%s] for team = %d\n",__FILE__,__FUNCTION__,gameNetworkInterface->getChatText().c_str(),teamIndex);
|
||||
|
||||
if(teamIndex==-1 || teamIndex==thisTeamIndex){
|
||||
console->addLine(gameNetworkInterface->getChatSender()+": "+gameNetworkInterface->getChatText(), true);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Added text to console\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,10 @@ void Game::load(){
|
|||
}
|
||||
}
|
||||
|
||||
void Game::init(){
|
||||
void Game::init()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
Lang &lang= Lang::getInstance();
|
||||
Logger &logger= Logger::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
|
@ -122,6 +125,7 @@ void Game::init(){
|
|||
Map *map= world.getMap();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Initializing\n",__FILE__,__FUNCTION__);
|
||||
logger.setState(lang.get("Initializing"));
|
||||
|
||||
//mesage box
|
||||
|
@ -143,6 +147,8 @@ void Game::init(){
|
|||
gameCamera.setPos(Vec2f(v.x, v.y));
|
||||
scriptManager.init(&world, &gameCamera);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] creating AI's\n",__FILE__,__FUNCTION__);
|
||||
|
||||
//create IAs
|
||||
aiInterfaces.resize(world.getFactionCount());
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
|
@ -174,6 +180,7 @@ void Game::init(){
|
|||
}
|
||||
|
||||
//init renderer state
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Initializing renderer\n",__FILE__,__FUNCTION__);
|
||||
logger.add("Initializing renderer", true);
|
||||
renderer.initGame(this);
|
||||
|
||||
|
@ -195,14 +202,18 @@ void Game::init(){
|
|||
soundRenderer.playAmbient(ambientSounds->getSnow());
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Waiting for network\n",__FILE__,__FUNCTION__);
|
||||
logger.add("Waiting for network", true);
|
||||
networkManager.getGameNetworkInterface()->waitUntilReady(&checksum);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Starting music stream\n",__FILE__,__FUNCTION__);
|
||||
logger.add("Starting music stream", true);
|
||||
StrSound *gameMusic= world.getThisFaction()->getType()->getMusic();
|
||||
soundRenderer.playMusic(gameMusic);
|
||||
|
||||
logger.add("Launching game");
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
|
@ -349,12 +360,15 @@ void Game::mouseDownLeft(int x, int y){
|
|||
//exit message box, has to be the last thing to do in this function
|
||||
if(mainMessageBox.getEnabled()){
|
||||
int button= 1;
|
||||
if(mainMessageBox.mouseClick(x, y, button)){
|
||||
if(button==1){
|
||||
networkManager.getGameNetworkInterface()->quitGame();
|
||||
if(mainMessageBox.mouseClick(x, y, button))
|
||||
{
|
||||
if(button==1)
|
||||
{
|
||||
networkManager.getGameNetworkInterface()->quitGame(true);
|
||||
quitGame();
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
//close message box
|
||||
mainMessageBox.setEnabled(false);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
|
|
@ -41,7 +41,50 @@ private:
|
|||
bool defaultResources;
|
||||
bool defaultVictoryConditions;
|
||||
|
||||
void CopyAll(const GameSettings &game)
|
||||
{
|
||||
description = game.description;
|
||||
map = game.map;
|
||||
tileset = game.tileset;
|
||||
tech = game.tech;
|
||||
scenario = game.scenario;
|
||||
scenarioDir = game.scenarioDir;
|
||||
thisFactionIndex = game.thisFactionIndex;
|
||||
factionCount = game.factionCount;
|
||||
defaultUnits = game.defaultUnits;
|
||||
defaultResources = game.defaultResources;
|
||||
defaultVictoryConditions = game.defaultVictoryConditions;
|
||||
|
||||
for(int i = 0; i < GameConstants::maxPlayers; i++)
|
||||
{
|
||||
factionTypeNames[i] = game.factionTypeNames[i]; //faction names
|
||||
factionControls[i] = game.factionControls[i];
|
||||
teams[i] = game.teams[i];
|
||||
startLocationIndex[i] = game.startLocationIndex[i];
|
||||
}
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTileset() = [%s]\n",__FILE__,__FUNCTION__,getTileset().c_str());
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTech() = [%s]\n",__FILE__,__FUNCTION__,getTech().c_str());
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getMap() = [%s]\n",__FILE__,__FUNCTION__,getMap().c_str());
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
GameSettings() { }
|
||||
|
||||
GameSettings(const GameSettings &game)
|
||||
{
|
||||
CopyAll(game);
|
||||
}
|
||||
|
||||
GameSettings & operator=(const GameSettings &game)
|
||||
{
|
||||
CopyAll(game);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//get
|
||||
const string &getDescription() const {return description;}
|
||||
const string &getMap() const {return map;}
|
||||
|
|
|
@ -699,7 +699,8 @@ void Renderer::renderResourceStatus(){
|
|||
glEnable(GL_TEXTURE_2D);
|
||||
renderQuad(j*100+200, metrics.getVirtualH()-30, 16, 16, rt->getImage());
|
||||
|
||||
if(rt->getClass()!=rcStatic){
|
||||
if(rt->getClass() != rcStatic)
|
||||
{
|
||||
str+= "/" + intToStr(thisFaction->getStoreAmount(rt));
|
||||
}
|
||||
if(rt->getClass()==rcConsumable){
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
|
|
@ -157,17 +157,29 @@ void Program::resize(SizeState sizeState){
|
|||
|
||||
// ==================== misc ====================
|
||||
|
||||
void Program::setState(ProgramState *programState){
|
||||
void Program::setState(ProgramState *programState)
|
||||
{
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
delete this->programState;
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] A\n",__FILE__,__FUNCTION__);
|
||||
|
||||
this->programState= programState;
|
||||
programState->load();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] B\n",__FILE__,__FUNCTION__);
|
||||
|
||||
programState->init();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] C\n",__FILE__,__FUNCTION__);
|
||||
|
||||
updateTimer.reset();
|
||||
updateCameraTimer.reset();
|
||||
fpsTimer.reset();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void Program::exit(){
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
@ -25,6 +25,7 @@
|
|||
#include "game.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
#include <time.h>
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
|
@ -40,6 +41,9 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b
|
|||
Lang &lang= Lang::getInstance();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
|
||||
needToSetChangedGameSettings = false;
|
||||
lastSetChangedGameSettings = time(NULL);;
|
||||
|
||||
vector<string> results, teamItems, controlItems;
|
||||
|
||||
//create
|
||||
|
@ -156,6 +160,9 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b
|
|||
}
|
||||
updateControlers();
|
||||
updateNetworkSlots();
|
||||
|
||||
//chatManager.init(&console, world.getThisTeamIndex());
|
||||
chatManager.init(&console, -1);
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
|
@ -168,30 +175,66 @@ void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){
|
|||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
mainMenu->setState(new MenuStateNewGame(program, mainMenu));
|
||||
}
|
||||
else if(buttonPlayNow.mouseClick(x,y)){
|
||||
GameSettings gameSettings;
|
||||
else if(buttonPlayNow.mouseClick(x,y) && buttonPlayNow.getEnabled()) {
|
||||
|
||||
closeUnusedSlots();
|
||||
soundRenderer.playFx(coreData.getClickSoundC());
|
||||
|
||||
GameSettings gameSettings;
|
||||
loadGameSettings(&gameSettings);
|
||||
serverInterface->launchGame(&gameSettings);
|
||||
program->setState(new Game(program, &gameSettings));
|
||||
|
||||
// Send the game settings to each client if we have at least one networked client
|
||||
if( hasNetworkGameSettings() == true &&
|
||||
needToSetChangedGameSettings == true)
|
||||
{
|
||||
serverInterface->setGameSettings(&gameSettings,true);
|
||||
|
||||
needToSetChangedGameSettings = false;
|
||||
lastSetChangedGameSettings = time(NULL);
|
||||
}
|
||||
|
||||
bool bOkToStart = serverInterface->launchGame(&gameSettings);
|
||||
if(bOkToStart == true)
|
||||
{
|
||||
|
||||
program->setState(new Game(program, &gameSettings));
|
||||
}
|
||||
}
|
||||
else if(listBoxMap.mouseClick(x, y)){
|
||||
loadMapInfo(Map::getMapPath(mapFiles[listBoxMap.getSelectedItemIndex()]), &mapInfo);
|
||||
labelMapInfo.setText(mapInfo.desc);
|
||||
updateControlers();
|
||||
|
||||
if(hasNetworkGameSettings() == true)
|
||||
{
|
||||
needToSetChangedGameSettings = true;
|
||||
lastSetChangedGameSettings = time(NULL);;
|
||||
}
|
||||
}
|
||||
else if(listBoxTileset.mouseClick(x, y)){
|
||||
|
||||
if(hasNetworkGameSettings() == true)
|
||||
{
|
||||
needToSetChangedGameSettings = true;
|
||||
lastSetChangedGameSettings = time(NULL);;
|
||||
}
|
||||
}
|
||||
else if(listBoxTechTree.mouseClick(x, y)){
|
||||
reloadFactions();
|
||||
}
|
||||
else{
|
||||
for(int i=0; i<mapInfo.players; ++i){
|
||||
//ensure thet only 1 human player is present
|
||||
if(listBoxControls[i].mouseClick(x, y)){
|
||||
|
||||
if(hasNetworkGameSettings() == true)
|
||||
{
|
||||
needToSetChangedGameSettings = true;
|
||||
lastSetChangedGameSettings = time(NULL);;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0; i<mapInfo.players; ++i)
|
||||
{
|
||||
//ensure thet only 1 human player is present
|
||||
if(listBoxControls[i].mouseClick(x, y))
|
||||
{
|
||||
//look for human players
|
||||
int humanIndex1= -1;
|
||||
int humanIndex2= -1;
|
||||
|
@ -217,10 +260,28 @@ void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){
|
|||
listBoxControls[humanIndex1==i? humanIndex2: humanIndex1].setSelectedItemIndex(ctClosed);
|
||||
}
|
||||
updateNetworkSlots();
|
||||
|
||||
if(hasNetworkGameSettings() == true)
|
||||
{
|
||||
needToSetChangedGameSettings = true;
|
||||
lastSetChangedGameSettings = time(NULL);;
|
||||
}
|
||||
}
|
||||
else if(listBoxFactions[i].mouseClick(x, y)){
|
||||
|
||||
if(hasNetworkGameSettings() == true)
|
||||
{
|
||||
needToSetChangedGameSettings = true;
|
||||
lastSetChangedGameSettings = time(NULL);;
|
||||
}
|
||||
}
|
||||
else if(listBoxTeams[i].mouseClick(x, y)){
|
||||
else if(listBoxTeams[i].mouseClick(x, y))
|
||||
{
|
||||
if(hasNetworkGameSettings() == true)
|
||||
{
|
||||
needToSetChangedGameSettings = true;
|
||||
lastSetChangedGameSettings = time(NULL);;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,33 +331,131 @@ void MenuStateCustomGame::render(){
|
|||
renderer.renderListBox(&listBoxMap);
|
||||
renderer.renderListBox(&listBoxTileset);
|
||||
renderer.renderListBox(&listBoxTechTree);
|
||||
|
||||
renderer.renderChatManager(&chatManager);
|
||||
renderer.renderConsole(&console);
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::update(){
|
||||
void MenuStateCustomGame::update()
|
||||
{
|
||||
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
|
||||
Lang& lang= Lang::getInstance();
|
||||
|
||||
for(int i= 0; i<mapInfo.players; ++i){
|
||||
if(listBoxControls[i].getSelectedItemIndex()==ctNetwork){
|
||||
bool haveAtLeastOneNetworkClientConnected = false;
|
||||
|
||||
for(int i= 0; i<mapInfo.players; ++i)
|
||||
{
|
||||
if(listBoxControls[i].getSelectedItemIndex() == ctNetwork)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] START - ctNetwork\n",__FILE__,__FUNCTION__);
|
||||
|
||||
ConnectionSlot* connectionSlot= serverInterface->getSlot(i);
|
||||
|
||||
assert(connectionSlot!=NULL);
|
||||
|
||||
if(connectionSlot->isConnected()){
|
||||
labelNetStatus[i].setText(connectionSlot->getName());
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] A - ctNetwork\n",__FILE__,__FUNCTION__);
|
||||
|
||||
if(connectionSlot->isConnected())
|
||||
{
|
||||
haveAtLeastOneNetworkClientConnected = true;
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] B - ctNetwork\n",__FILE__,__FUNCTION__);
|
||||
|
||||
string label = connectionSlot->getName();
|
||||
if(connectionSlot->getAllowDownloadDataSynch() == true &&
|
||||
connectionSlot->getAllowGameDataSynchCheck() == true)
|
||||
{
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOk() == false)
|
||||
{
|
||||
label = connectionSlot->getName() + " - waiting to synch:";
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false)
|
||||
{
|
||||
label = label + " map";
|
||||
}
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false)
|
||||
{
|
||||
label = label + " tile";
|
||||
}
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false)
|
||||
{
|
||||
label = label + " techtree";
|
||||
}
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOkFogOfWar() == false)
|
||||
{
|
||||
label = label + " FogOfWar == false";
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
label = connectionSlot->getName() + " - data synch is ok";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label = connectionSlot->getName();
|
||||
|
||||
if(connectionSlot->getAllowGameDataSynchCheck() == true)
|
||||
{
|
||||
label += " - warning synch mismatch for:";
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false)
|
||||
{
|
||||
label = label + " map";
|
||||
}
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false)
|
||||
{
|
||||
label = label + " tile";
|
||||
}
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false)
|
||||
{
|
||||
label = label + " techtree";
|
||||
}
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOkFogOfWar() == false)
|
||||
{
|
||||
label = label + " FogOfWar == false";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
labelNetStatus[i].setText(label);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] C - ctNetwork\n",__FILE__,__FUNCTION__);
|
||||
|
||||
labelNetStatus[i].setText(lang.get("NotConnected"));
|
||||
}
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] END - ctNetwork\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
else{
|
||||
labelNetStatus[i].setText("");
|
||||
}
|
||||
}
|
||||
|
||||
// Send the game settings to each client if we have at least one networked client
|
||||
if( serverInterface->getAllowDownloadDataSynch() == true &&
|
||||
haveAtLeastOneNetworkClientConnected == true &&
|
||||
needToSetChangedGameSettings == true &&
|
||||
difftime(time(NULL),lastSetChangedGameSettings) >= 2)
|
||||
{
|
||||
GameSettings gameSettings;
|
||||
loadGameSettings(&gameSettings);
|
||||
serverInterface->setGameSettings(&gameSettings);
|
||||
|
||||
needToSetChangedGameSettings = false;
|
||||
lastSetChangedGameSettings = time(NULL);
|
||||
}
|
||||
|
||||
//call the chat manager
|
||||
chatManager.updateNetwork();
|
||||
|
||||
//console
|
||||
console.update();
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){
|
||||
void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
int factionCount= 0;
|
||||
|
||||
|
@ -308,10 +467,13 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){
|
|||
gameSettings->setDefaultResources(true);
|
||||
gameSettings->setDefaultVictoryConditions(true);
|
||||
|
||||
for(int i=0; i<mapInfo.players; ++i){
|
||||
for(int i=0; i<mapInfo.players; ++i)
|
||||
{
|
||||
ControlType ct= static_cast<ControlType>(listBoxControls[i].getSelectedItemIndex());
|
||||
if(ct!=ctClosed){
|
||||
if(ct==ctHuman){
|
||||
if(ct != ctClosed)
|
||||
{
|
||||
if(ct == ctHuman)
|
||||
{
|
||||
gameSettings->setThisFactionIndex(factionCount);
|
||||
}
|
||||
gameSettings->setFactionControl(factionCount, ct);
|
||||
|
@ -322,10 +484,36 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){
|
|||
}
|
||||
}
|
||||
gameSettings->setFactionCount(factionCount);
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTileset() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getTileset().c_str());
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTech() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getTech().c_str());
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getMap() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getMap().c_str());
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
// ============ PRIVATE ===========================
|
||||
|
||||
bool MenuStateCustomGame::hasNetworkGameSettings()
|
||||
{
|
||||
bool hasNetworkSlot = false;
|
||||
|
||||
for(int i=0; i<mapInfo.players; ++i)
|
||||
{
|
||||
ControlType ct= static_cast<ControlType>(listBoxControls[i].getSelectedItemIndex());
|
||||
if(ct != ctClosed)
|
||||
{
|
||||
if(ct == ctNetwork)
|
||||
{
|
||||
hasNetworkSlot = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hasNetworkSlot;
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo){
|
||||
|
||||
struct MapFileHeader{
|
||||
|
@ -411,17 +599,33 @@ void MenuStateCustomGame::closeUnusedSlots(){
|
|||
updateNetworkSlots();
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::updateNetworkSlots(){
|
||||
void MenuStateCustomGame::updateNetworkSlots()
|
||||
{
|
||||
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
if(serverInterface->getSlot(i)==NULL && listBoxControls[i].getSelectedItemIndex()==ctNetwork){
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
if(serverInterface->getSlot(i) == NULL && listBoxControls[i].getSelectedItemIndex() == ctNetwork)
|
||||
{
|
||||
serverInterface->addSlot(i);
|
||||
}
|
||||
if(serverInterface->getSlot(i) != NULL && listBoxControls[i].getSelectedItemIndex()!=ctNetwork){
|
||||
if(serverInterface->getSlot(i) != NULL && listBoxControls[i].getSelectedItemIndex() != ctNetwork)
|
||||
{
|
||||
serverInterface->removeSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::keyDown(char key)
|
||||
{
|
||||
//send key to the chat manager
|
||||
chatManager.keyDown(key);
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::keyPress(char c)
|
||||
{
|
||||
chatManager.keyPress(c);
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define _GLEST_GAME_MENUSTATECUSTOMGAME_H_
|
||||
|
||||
#include "main_menu.h"
|
||||
#include "chat_manager.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
|
@ -45,6 +46,12 @@ private:
|
|||
GraphicLabel labelNetStatus[GameConstants::maxPlayers];
|
||||
MapInfo mapInfo;
|
||||
|
||||
bool needToSetChangedGameSettings;
|
||||
time_t lastSetChangedGameSettings;
|
||||
|
||||
Console console;
|
||||
ChatManager chatManager;
|
||||
|
||||
public:
|
||||
MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots= false);
|
||||
|
||||
|
@ -53,7 +60,12 @@ public:
|
|||
void render();
|
||||
void update();
|
||||
|
||||
virtual void keyDown(char key);
|
||||
virtual void keyPress(char c);
|
||||
|
||||
private:
|
||||
|
||||
bool hasNetworkGameSettings();
|
||||
void loadGameSettings(GameSettings *gameSettings);
|
||||
void loadMapInfo(string file, MapInfo *mapInfo);
|
||||
void reloadFactions();
|
||||
|
|
|
@ -87,7 +87,8 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool
|
|||
playerIndex= -1;
|
||||
|
||||
//server ip
|
||||
if(connect){
|
||||
if(connect)
|
||||
{
|
||||
labelServerIp.setText(serverIp.getString() + "_");
|
||||
connectToServer();
|
||||
}
|
||||
|
@ -95,9 +96,13 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool
|
|||
{
|
||||
labelServerIp.setText(config.getString("ServerIp") + "_");
|
||||
}
|
||||
|
||||
chatManager.init(&console, -1);
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
@ -121,25 +126,42 @@ void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton){
|
|||
}
|
||||
|
||||
//return
|
||||
if(buttonReturn.mouseClick(x, y)){
|
||||
if(buttonReturn.mouseClick(x, y))
|
||||
{
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
|
||||
if(clientInterface->getSocket() != NULL)
|
||||
{
|
||||
if(clientInterface->isConnected() == true)
|
||||
{
|
||||
string sQuitText = clientInterface->getHostName() + " has chosen to leave the game!";
|
||||
clientInterface->sendTextMessage(sQuitText,-1);
|
||||
}
|
||||
clientInterface->close();
|
||||
}
|
||||
|
||||
mainMenu->setState(new MenuStateRoot(program, mainMenu));
|
||||
}
|
||||
|
||||
//connect
|
||||
else if(buttonConnect.mouseClick(x, y)){
|
||||
else if(buttonConnect.mouseClick(x, y))
|
||||
{
|
||||
ClientInterface* clientInterface= networkManager.getClientInterface();
|
||||
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
labelInfo.setText("");
|
||||
|
||||
if(clientInterface->isConnected()){
|
||||
if(clientInterface->isConnected())
|
||||
{
|
||||
clientInterface->reset();
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
connectToServer();
|
||||
}
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::mouseMove(int x, int y, const MouseState *ms){
|
||||
|
@ -174,52 +196,145 @@ void MenuStateJoinGame::render(){
|
|||
{
|
||||
renderer.renderListBox(&listBoxServers);
|
||||
}
|
||||
|
||||
renderer.renderChatManager(&chatManager);
|
||||
renderer.renderConsole(&console);
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::update(){
|
||||
void MenuStateJoinGame::update()
|
||||
{
|
||||
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
//update status label
|
||||
if(clientInterface->isConnected()){
|
||||
if(clientInterface->isConnected())
|
||||
{
|
||||
buttonConnect.setText(lang.get("Disconnect"));
|
||||
if(!clientInterface->getServerName().empty()){
|
||||
labelStatus.setText(lang.get("ConnectedToServer") + " " + clientInterface->getServerName());
|
||||
|
||||
if(clientInterface->getAllowDownloadDataSynch() == false)
|
||||
{
|
||||
string label = lang.get("ConnectedToServer");
|
||||
|
||||
if(!clientInterface->getServerName().empty())
|
||||
{
|
||||
label = label + " " + clientInterface->getServerName();
|
||||
}
|
||||
|
||||
if(clientInterface->getAllowGameDataSynchCheck() == true &&
|
||||
clientInterface->getNetworkGameDataSynchCheckOk() == false)
|
||||
{
|
||||
label = label + " - warning synch mismatch for:";
|
||||
if(clientInterface->getNetworkGameDataSynchCheckOkMap() == false)
|
||||
{
|
||||
label = label + " map";
|
||||
}
|
||||
if(clientInterface->getNetworkGameDataSynchCheckOkTile() == false)
|
||||
{
|
||||
label = label + " tile";
|
||||
}
|
||||
if(clientInterface->getNetworkGameDataSynchCheckOkTech() == false)
|
||||
{
|
||||
label = label + " techtree";
|
||||
}
|
||||
if(clientInterface->getNetworkGameDataSynchCheckOkFogOfWar() == false)
|
||||
{
|
||||
label = label + " FogOfWar == false";
|
||||
}
|
||||
}
|
||||
else if(clientInterface->getAllowGameDataSynchCheck() == true)
|
||||
{
|
||||
label += " - data synch is ok";
|
||||
}
|
||||
|
||||
labelStatus.setText(label);
|
||||
}
|
||||
else{
|
||||
labelStatus.setText(lang.get("ConnectedToServer"));
|
||||
else
|
||||
{
|
||||
string label = lang.get("ConnectedToServer");
|
||||
|
||||
if(!clientInterface->getServerName().empty())
|
||||
{
|
||||
label = label + " " + clientInterface->getServerName();
|
||||
}
|
||||
|
||||
if(clientInterface->getAllowGameDataSynchCheck() == true &&
|
||||
clientInterface->getNetworkGameDataSynchCheckOk() == false)
|
||||
{
|
||||
label = label + " - waiting to synch:";
|
||||
if(clientInterface->getNetworkGameDataSynchCheckOkMap() == false)
|
||||
{
|
||||
label = label + " map";
|
||||
}
|
||||
if(clientInterface->getNetworkGameDataSynchCheckOkTile() == false)
|
||||
{
|
||||
label = label + " tile";
|
||||
}
|
||||
if(clientInterface->getNetworkGameDataSynchCheckOkTech() == false)
|
||||
{
|
||||
label = label + " techtree";
|
||||
}
|
||||
if(clientInterface->getNetworkGameDataSynchCheckOkFogOfWar() == false)
|
||||
{
|
||||
label = label + " FogOfWar == false";
|
||||
}
|
||||
}
|
||||
else if(clientInterface->getAllowGameDataSynchCheck() == true)
|
||||
{
|
||||
label += " - data synch is ok";
|
||||
}
|
||||
|
||||
labelStatus.setText(label);
|
||||
}
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
buttonConnect.setText(lang.get("Connect"));
|
||||
labelStatus.setText(lang.get("NotConnected"));
|
||||
labelInfo.setText("");
|
||||
}
|
||||
|
||||
//process network messages
|
||||
if(clientInterface->isConnected()){
|
||||
|
||||
if(clientInterface->isConnected())
|
||||
{
|
||||
//update lobby
|
||||
clientInterface->updateLobby();
|
||||
|
||||
//call the chat manager
|
||||
chatManager.updateNetwork();
|
||||
|
||||
//console
|
||||
console.update();
|
||||
|
||||
//intro
|
||||
if(clientInterface->getIntroDone()){
|
||||
if(clientInterface->getIntroDone())
|
||||
{
|
||||
labelInfo.setText(lang.get("WaitingHost"));
|
||||
servers.setString(clientInterface->getServerName(), Ip(labelServerIp.getText()).getString());
|
||||
}
|
||||
|
||||
//launch
|
||||
if(clientInterface->getLaunchGame()){
|
||||
if(clientInterface->getLaunchGame())
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - A\n",__FILE__,__FUNCTION__);
|
||||
|
||||
servers.save(serverFileName);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - B\n",__FILE__,__FUNCTION__);
|
||||
|
||||
program->setState(new Game(program, clientInterface->getGameSettings()));
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - C\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText && clientInterface->getLaunchGame()) printf("In [%s::%s] clientInterface->getLaunchGame() - D\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::keyDown(char key){
|
||||
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
|
||||
|
||||
if(!clientInterface->isConnected()){
|
||||
if(!clientInterface->isConnected())
|
||||
{
|
||||
if(key==vkBack){
|
||||
string text= labelServerIp.getText();
|
||||
|
||||
|
@ -230,12 +345,18 @@ void MenuStateJoinGame::keyDown(char key){
|
|||
labelServerIp.setText(text);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//send key to the chat manager
|
||||
chatManager.keyDown(key);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::keyPress(char c){
|
||||
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
|
||||
|
||||
if(!clientInterface->isConnected()){
|
||||
if(!clientInterface->isConnected())
|
||||
{
|
||||
int maxTextSize= 16;
|
||||
|
||||
if(c>='0' && c<='9'){
|
||||
|
@ -258,20 +379,32 @@ void MenuStateJoinGame::keyPress(char c){
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chatManager.keyPress(c);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::connectToServer(){
|
||||
void MenuStateJoinGame::connectToServer()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
|
||||
Config& config= Config::getInstance();
|
||||
Ip serverIp(labelServerIp.getText());
|
||||
|
||||
clientInterface->connect(serverIp, GameConstants::serverPort);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] server - [%s]\n",__FILE__,__FUNCTION__,serverIp.getString().c_str());
|
||||
|
||||
labelServerIp.setText(serverIp.getString()+'_');
|
||||
labelInfo.setText("");
|
||||
|
||||
//save server ip
|
||||
config.setString("ServerIp", serverIp.getString());
|
||||
config.save();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "properties.h"
|
||||
#include "main_menu.h"
|
||||
#include "chat_manager.h"
|
||||
|
||||
using Shared::Util::Properties;
|
||||
|
||||
|
@ -45,6 +46,9 @@ private:
|
|||
int playerIndex;
|
||||
Properties servers;
|
||||
|
||||
Console console;
|
||||
ChatManager chatManager;
|
||||
|
||||
public:
|
||||
MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool connect= false, Ip serverIp= Ip());
|
||||
|
||||
|
@ -52,8 +56,8 @@ public:
|
|||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void render();
|
||||
void update();
|
||||
void keyDown(char key);
|
||||
void keyPress(char c);
|
||||
virtual void keyDown(char key);
|
||||
virtual void keyPress(char c);
|
||||
|
||||
private:
|
||||
void connectToServer();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
#include "lang.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
#include "map.h"
|
||||
#include "config.h"
|
||||
#include "logger.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
|
@ -39,25 +43,56 @@ ClientInterface::ClientInterface(){
|
|||
launchGame= false;
|
||||
introDone= false;
|
||||
playerIndex= -1;
|
||||
|
||||
networkGameDataSynchCheckOkMap = false;
|
||||
networkGameDataSynchCheckOkTile = false;
|
||||
networkGameDataSynchCheckOkTech = false;
|
||||
}
|
||||
|
||||
ClientInterface::~ClientInterface(){
|
||||
ClientInterface::~ClientInterface()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
if(clientSocket != NULL && clientSocket->isConnected() == true)
|
||||
{
|
||||
string sQuitText = getHostName() + " has chosen to leave the game!";
|
||||
sendTextMessage(sQuitText,-1);
|
||||
}
|
||||
|
||||
delete clientSocket;
|
||||
clientSocket = NULL;
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ClientInterface::connect(const Ip &ip, int port){
|
||||
void ClientInterface::connect(const Ip &ip, int port)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
delete clientSocket;
|
||||
|
||||
this->ip = ip;
|
||||
this->port = port;
|
||||
|
||||
clientSocket= new ClientSocket();
|
||||
clientSocket->setBlock(false);
|
||||
clientSocket->connect(ip, port);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END - socket = %d\n",__FILE__,__FUNCTION__,clientSocket->getSocketId());
|
||||
}
|
||||
|
||||
void ClientInterface::reset(){
|
||||
delete clientSocket;
|
||||
clientSocket= NULL;
|
||||
void ClientInterface::reset()
|
||||
{
|
||||
if(getSocket() != NULL)
|
||||
{
|
||||
string sQuitText = getHostName() + " has chosen to leave the game!";
|
||||
sendTextMessage(sQuitText,-1);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void ClientInterface::update(){
|
||||
void ClientInterface::update()
|
||||
{
|
||||
NetworkMessageCommandList networkMessageCommandList;
|
||||
|
||||
//send as many commands as we can
|
||||
|
@ -79,93 +114,275 @@ void ClientInterface::update(){
|
|||
chatTeamIndex= -1;
|
||||
}
|
||||
|
||||
void ClientInterface::updateLobby(){
|
||||
NetworkMessageType networkMessageType= getNextMessageType();
|
||||
void ClientInterface::updateLobby()
|
||||
{
|
||||
//clear chat variables
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
|
||||
switch(networkMessageType){
|
||||
case nmtInvalid:
|
||||
break;
|
||||
NetworkMessageType networkMessageType = getNextMessageType(true);
|
||||
|
||||
case nmtIntro:{
|
||||
NetworkMessageIntro networkMessageIntro;
|
||||
switch(networkMessageType)
|
||||
{
|
||||
case nmtInvalid:
|
||||
break;
|
||||
|
||||
if(receiveMessage(&networkMessageIntro)){
|
||||
case nmtIntro:
|
||||
{
|
||||
NetworkMessageIntro networkMessageIntro;
|
||||
|
||||
//check consistency
|
||||
if(Config::getInstance().getBool("NetworkConsistencyChecks")){
|
||||
if(networkMessageIntro.getVersionString()!=getNetworkVersionString()){
|
||||
throw runtime_error("Server and client versions do not match (" + networkMessageIntro.getVersionString() + "). You have to use the same binaries.");
|
||||
}
|
||||
}
|
||||
if(receiveMessage(&networkMessageIntro))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got NetworkMessageIntro\n",__FILE__,__FUNCTION__);
|
||||
|
||||
//send intro message
|
||||
NetworkMessageIntro sendNetworkMessageIntro(getNetworkVersionString(), getHostName(), -1);
|
||||
//check consistency
|
||||
if(Config::getInstance().getBool("NetworkConsistencyChecks"))
|
||||
{
|
||||
if(networkMessageIntro.getVersionString()!=getNetworkVersionString())
|
||||
{
|
||||
throw runtime_error("Server and client versions do not match (" + networkMessageIntro.getVersionString() + "). You have to use the same binaries.");
|
||||
}
|
||||
}
|
||||
|
||||
playerIndex= networkMessageIntro.getPlayerIndex();
|
||||
serverName= networkMessageIntro.getName();
|
||||
sendMessage(&sendNetworkMessageIntro);
|
||||
//send intro message
|
||||
NetworkMessageIntro sendNetworkMessageIntro(getNetworkVersionString(), getHostName(), -1);
|
||||
|
||||
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
|
||||
introDone= true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
playerIndex= networkMessageIntro.getPlayerIndex();
|
||||
serverName= networkMessageIntro.getName();
|
||||
sendMessage(&sendNetworkMessageIntro);
|
||||
|
||||
case nmtLaunch:{
|
||||
NetworkMessageLaunch networkMessageLaunch;
|
||||
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
|
||||
introDone= true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
if(receiveMessage(&networkMessageLaunch)){
|
||||
networkMessageLaunch.buildGameSettings(&gameSettings);
|
||||
case nmtSynchNetworkGameData:
|
||||
{
|
||||
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData;
|
||||
|
||||
//replace server player by network
|
||||
for(int i= 0; i<gameSettings.getFactionCount(); ++i){
|
||||
if(receiveMessage(&networkMessageSynchNetworkGameData))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got NetworkMessageSynchNetworkGameData\n",__FILE__,__FUNCTION__);
|
||||
|
||||
//replace by network
|
||||
if(gameSettings.getFactionControl(i)==ctHuman){
|
||||
gameSettings.setFactionControl(i, ctNetwork);
|
||||
}
|
||||
// check the checksum's
|
||||
//Checksum checksum;
|
||||
//tileset
|
||||
//string file = "tilesets/" + networkMessageSynchNetworkGameData.getTileset() + "/" + networkMessageSynchNetworkGameData.getTileset() + ".xml";
|
||||
//checksum.addFile(file);
|
||||
// models
|
||||
// sounds
|
||||
// textures
|
||||
//int32 tilesetCRC = checksum.getSum();
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),tilesetCRC);
|
||||
|
||||
//set the faction index
|
||||
if(gameSettings.getStartLocationIndex(i)==playerIndex){
|
||||
gameSettings.setThisFactionIndex(i);
|
||||
}
|
||||
}
|
||||
launchGame= true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
//if(tilesetCRC != networkMessageSynchNetworkGameData.getTilesetCRC())
|
||||
//{
|
||||
// if(Socket::enableDebugText) printf("In [%s::%s] tilesetCRC mismatch, local = %d, remote = %d\n",
|
||||
// __FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameData.getTilesetCRC());
|
||||
//}
|
||||
|
||||
default:
|
||||
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
|
||||
}
|
||||
int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively("tilesets/" +
|
||||
networkMessageSynchNetworkGameData.getTileset() + "/*", ".xml", NULL);
|
||||
|
||||
this->setNetworkGameDataSynchCheckOkTile((tilesetCRC == networkMessageSynchNetworkGameData.getTilesetCRC()));
|
||||
if(this->getNetworkGameDataSynchCheckOkTile() == false)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] tilesetCRC mismatch, local = %d, remote = %d\n",
|
||||
__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameData.getTilesetCRC());
|
||||
}
|
||||
|
||||
|
||||
//tech, load before map because of resources
|
||||
//checksum = Checksum();
|
||||
//file = "techs/" + networkMessageSynchNetworkGameData.getTech() + "/" + networkMessageSynchNetworkGameData.getTech() + ".xml";
|
||||
//checksum.addFile(file);
|
||||
// factions
|
||||
// resources
|
||||
//int32 techCRC = checksum.getSum();
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),techCRC);
|
||||
|
||||
//if(techCRC != networkMessageSynchNetworkGameData.getTechCRC())
|
||||
//{
|
||||
// if(Socket::enableDebugText) printf("In [%s::%s] techCRC mismatch, local = %d, remote = %d\n",
|
||||
// __FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameData.getTechCRC());
|
||||
//}
|
||||
|
||||
int32 techCRC = getFolderTreeContentsCheckSumRecursively("techs/" +
|
||||
networkMessageSynchNetworkGameData.getTech() + "/*", ".xml", NULL);
|
||||
|
||||
this->setNetworkGameDataSynchCheckOkTech((techCRC == networkMessageSynchNetworkGameData.getTechCRC()));
|
||||
|
||||
if(this->getNetworkGameDataSynchCheckOkTech() == false)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] techCRC mismatch, local = %d, remote = %d\n",
|
||||
__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameData.getTechCRC());
|
||||
}
|
||||
|
||||
//map
|
||||
Checksum checksum;
|
||||
string file = Map::getMapPath(networkMessageSynchNetworkGameData.getMap());
|
||||
checksum.addFile(file);
|
||||
int32 mapCRC = checksum.getSum();
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),mapCRC);
|
||||
|
||||
this->setNetworkGameDataSynchCheckOkMap((mapCRC == networkMessageSynchNetworkGameData.getMapCRC()));
|
||||
|
||||
if(this->getNetworkGameDataSynchCheckOkMap() == false)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] mapCRC mismatch, local = %d, remote = %d\n",
|
||||
__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameData.getMapCRC());
|
||||
}
|
||||
|
||||
|
||||
this->setNetworkGameDataSynchCheckOkFogOfWar((getFogOfWar() == networkMessageSynchNetworkGameData.getFogOfWar()));
|
||||
|
||||
if(this->getNetworkGameDataSynchCheckOkFogOfWar() == false)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] getFogOfWar mismatch, local = %d, remote = %d\n",
|
||||
__FILE__,__FUNCTION__,getFogOfWar(),networkMessageSynchNetworkGameData.getFogOfWar());
|
||||
}
|
||||
|
||||
NetworkMessageSynchNetworkGameDataStatus sendNetworkMessageSynchNetworkGameDataStatus(mapCRC,tilesetCRC,techCRC,getFogOfWar());
|
||||
sendMessage(&sendNetworkMessageSynchNetworkGameDataStatus);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtSynchNetworkGameDataFileCRCCheck:
|
||||
{
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck;
|
||||
if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck))
|
||||
{
|
||||
/*
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck totalfiles = %d, fileindex = %d, crc = %d, file [%s]\n",
|
||||
__FILE__,__FUNCTION__,networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount(),
|
||||
networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex(),
|
||||
networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC(),
|
||||
networkMessageSynchNetworkGameDataFileCRCCheck.getFileName().c_str());
|
||||
*/
|
||||
Checksum checksum;
|
||||
string file = networkMessageSynchNetworkGameDataFileCRCCheck.getFileName();
|
||||
checksum.addFile(file);
|
||||
int32 fileCRC = checksum.getSum();
|
||||
|
||||
if(fileCRC != networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC())
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck localCRC = %d, remoteCRC = %d, file [%s]\n",
|
||||
__FILE__,__FUNCTION__,fileCRC,
|
||||
networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC(),
|
||||
networkMessageSynchNetworkGameDataFileCRCCheck.getFileName().c_str());
|
||||
|
||||
// Here we initiate a download of missing or mismatched content
|
||||
|
||||
NetworkMessageSynchNetworkGameDataFileGet sendNetworkMessageSynchNetworkGameDataFileGet(networkMessageSynchNetworkGameDataFileCRCCheck.getFileName());
|
||||
sendMessage(&sendNetworkMessageSynchNetworkGameDataFileGet);
|
||||
|
||||
FileTransferInfo fileInfo;
|
||||
fileInfo.hostType = eClient;
|
||||
fileInfo.serverIP = this->ip.getString();
|
||||
fileInfo.serverPort = this->port;
|
||||
fileInfo.fileName = networkMessageSynchNetworkGameDataFileCRCCheck.getFileName();
|
||||
|
||||
FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo);
|
||||
fileXferThread->start();
|
||||
}
|
||||
|
||||
if(networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex() < networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount())
|
||||
{
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck sendNetworkMessageSynchNetworkGameDataFileCRCCheck(
|
||||
networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount(),
|
||||
networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex() + 1,
|
||||
0,
|
||||
"");
|
||||
sendMessage(&sendNetworkMessageSynchNetworkGameDataFileCRCCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtText:
|
||||
{
|
||||
NetworkMessageText networkMessageText;
|
||||
if(receiveMessage(&networkMessageText))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__);
|
||||
|
||||
chatText = networkMessageText.getText();
|
||||
chatSender = networkMessageText.getSender();
|
||||
chatTeamIndex = networkMessageText.getTeamIndex();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtLaunch:
|
||||
{
|
||||
NetworkMessageLaunch networkMessageLaunch;
|
||||
|
||||
if(receiveMessage(&networkMessageLaunch))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got NetworkMessageLaunch\n",__FILE__,__FUNCTION__);
|
||||
|
||||
networkMessageLaunch.buildGameSettings(&gameSettings);
|
||||
|
||||
//replace server player by network
|
||||
for(int i= 0; i<gameSettings.getFactionCount(); ++i)
|
||||
{
|
||||
//replace by network
|
||||
if(gameSettings.getFactionControl(i)==ctHuman)
|
||||
{
|
||||
gameSettings.setFactionControl(i, ctNetwork);
|
||||
}
|
||||
|
||||
//set the faction index
|
||||
if(gameSettings.getStartLocationIndex(i)==playerIndex)
|
||||
{
|
||||
gameSettings.setThisFactionIndex(i);
|
||||
}
|
||||
}
|
||||
launchGame= true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType));
|
||||
}
|
||||
}
|
||||
|
||||
void ClientInterface::updateKeyframe(int frameCount){
|
||||
|
||||
void ClientInterface::updateKeyframe(int frameCount)
|
||||
{
|
||||
bool done= false;
|
||||
|
||||
while(!done){
|
||||
while(!done)
|
||||
{
|
||||
//wait for the next message
|
||||
waitForMessage();
|
||||
|
||||
//check we have an expected message
|
||||
NetworkMessageType networkMessageType= getNextMessageType();
|
||||
NetworkMessageType networkMessageType= getNextMessageType(true);
|
||||
|
||||
switch(networkMessageType){
|
||||
case nmtCommandList:{
|
||||
switch(networkMessageType)
|
||||
{
|
||||
case nmtCommandList:
|
||||
{
|
||||
//make sure we read the message
|
||||
NetworkMessageCommandList networkMessageCommandList;
|
||||
while(!receiveMessage(&networkMessageCommandList)){
|
||||
while(!receiveMessage(&networkMessageCommandList))
|
||||
{
|
||||
sleep(waitSleepTime);
|
||||
}
|
||||
|
||||
//check that we are in the right frame
|
||||
if(networkMessageCommandList.getFrameCount()!=frameCount){
|
||||
if(networkMessageCommandList.getFrameCount()!=frameCount)
|
||||
{
|
||||
throw runtime_error("Network synchronization error, frame counts do not match");
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
@ -173,58 +390,87 @@ void ClientInterface::updateKeyframe(int frameCount){
|
|||
}
|
||||
break;
|
||||
|
||||
case nmtQuit:{
|
||||
case nmtQuit:
|
||||
{
|
||||
NetworkMessageQuit networkMessageQuit;
|
||||
if(receiveMessage(&networkMessageQuit)){
|
||||
if(receiveMessage(&networkMessageQuit))
|
||||
{
|
||||
quit= true;
|
||||
}
|
||||
done= true;
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtText:{
|
||||
case nmtText:
|
||||
{
|
||||
NetworkMessageText networkMessageText;
|
||||
if(receiveMessage(&networkMessageText)){
|
||||
chatText= networkMessageText.getText();
|
||||
chatSender= networkMessageText.getSender();
|
||||
chatTeamIndex= networkMessageText.getTeamIndex();
|
||||
if(receiveMessage(&networkMessageText))
|
||||
{
|
||||
chatText = networkMessageText.getText();
|
||||
chatSender = networkMessageText.getSender();
|
||||
chatTeamIndex = networkMessageText.getTeamIndex();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nmtInvalid:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error("Unexpected message in client interface: " + intToStr(networkMessageType));
|
||||
throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected message in client interface: " + intToStr(networkMessageType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientInterface::waitUntilReady(Checksum* checksum){
|
||||
void ClientInterface::waitUntilReady(Checksum* checksum)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
Logger &logger= Logger::getInstance();
|
||||
|
||||
NetworkMessageReady networkMessageReady;
|
||||
Chrono chrono;
|
||||
|
||||
chrono.start();
|
||||
|
||||
// FOR TESTING ONLY - delay to see the client count up while waiting
|
||||
//sleep(5000);
|
||||
|
||||
//send ready message
|
||||
NetworkMessageReady networkMessageReady;
|
||||
sendMessage(&networkMessageReady);
|
||||
|
||||
int64 lastMillisCheck = 0;
|
||||
//wait until we get a ready message from the server
|
||||
while(true){
|
||||
while(true)
|
||||
{
|
||||
NetworkMessageType networkMessageType = getNextMessageType(true);
|
||||
|
||||
NetworkMessageType networkMessageType= getNextMessageType();
|
||||
|
||||
if(networkMessageType==nmtReady){
|
||||
if(receiveMessage(&networkMessageReady)){
|
||||
if(networkMessageType == nmtReady)
|
||||
{
|
||||
if(receiveMessage(&networkMessageReady))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(networkMessageType==nmtInvalid){
|
||||
if(chrono.getMillis()>readyWaitTimeout){
|
||||
else if(networkMessageType == nmtInvalid)
|
||||
{
|
||||
if(chrono.getMillis() > readyWaitTimeout)
|
||||
{
|
||||
throw runtime_error("Timeout waiting for server");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(chrono.getMillis() / 1000 > lastMillisCheck)
|
||||
{
|
||||
lastMillisCheck = (chrono.getMillis() / 1000);
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Waiting for network: %llu seconds elapsed (maximum wait time: %d seconds)",lastMillisCheck,int(readyWaitTimeout / 1000));
|
||||
logger.add(szBuf, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType) );
|
||||
else
|
||||
{
|
||||
throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType) );
|
||||
}
|
||||
|
||||
// sleep a bit
|
||||
|
@ -232,14 +478,18 @@ void ClientInterface::waitUntilReady(Checksum* checksum){
|
|||
}
|
||||
|
||||
//check checksum
|
||||
if(Config::getInstance().getBool("NetworkConsistencyChecks")){
|
||||
if(networkMessageReady.getChecksum()!=checksum->getSum()){
|
||||
if(Config::getInstance().getBool("NetworkConsistencyChecks"))
|
||||
{
|
||||
if(networkMessageReady.getChecksum() != checksum->getSum())
|
||||
{
|
||||
throw runtime_error("Checksum error, you don't have the same data as the server");
|
||||
}
|
||||
}
|
||||
|
||||
//delay the start a bit, so clients have nore room to get messages
|
||||
sleep(GameConstants::networkExtraLatency);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ClientInterface::sendTextMessage(const string &text, int teamIndex){
|
||||
|
@ -251,18 +501,20 @@ string ClientInterface::getNetworkStatus() const{
|
|||
return Lang::getInstance().get("Server") + ": " + serverName;
|
||||
}
|
||||
|
||||
void ClientInterface::waitForMessage(){
|
||||
void ClientInterface::waitForMessage()
|
||||
{
|
||||
Chrono chrono;
|
||||
|
||||
chrono.start();
|
||||
|
||||
while(getNextMessageType()==nmtInvalid){
|
||||
|
||||
if(!isConnected()){
|
||||
while(getNextMessageType(true) == nmtInvalid)
|
||||
{
|
||||
if(!isConnected())
|
||||
{
|
||||
throw runtime_error("Disconnected");
|
||||
}
|
||||
|
||||
if(chrono.getMillis()>messageWaitTimeout){
|
||||
if(chrono.getMillis()>messageWaitTimeout)
|
||||
{
|
||||
throw runtime_error("Timeout waiting for message");
|
||||
}
|
||||
|
||||
|
@ -270,4 +522,31 @@ void ClientInterface::waitForMessage(){
|
|||
}
|
||||
}
|
||||
|
||||
void ClientInterface::quitGame(bool userManuallyQuit)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
if(clientSocket != NULL && userManuallyQuit == true)
|
||||
{
|
||||
string sQuitText = getHostName() + " has chosen to leave the game!";
|
||||
sendTextMessage(sQuitText,-1);
|
||||
close();
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ClientInterface::close()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
delete clientSocket;
|
||||
clientSocket= NULL;
|
||||
}
|
||||
|
||||
bool ClientInterface::getFogOfWar()
|
||||
{
|
||||
return Config::getInstance().getBool("FogOfWar");
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "network_interface.h"
|
||||
#include "game_settings.h"
|
||||
//#include "game_settings.h"
|
||||
|
||||
#include "socket.h"
|
||||
|
||||
|
@ -36,18 +36,22 @@ private:
|
|||
|
||||
private:
|
||||
ClientSocket *clientSocket;
|
||||
GameSettings gameSettings;
|
||||
//GameSettings gameSettings;
|
||||
string serverName;
|
||||
bool introDone;
|
||||
bool launchGame;
|
||||
int playerIndex;
|
||||
|
||||
Ip ip;
|
||||
int port;
|
||||
|
||||
public:
|
||||
ClientInterface();
|
||||
virtual ~ClientInterface();
|
||||
|
||||
virtual Socket* getSocket() {return clientSocket;}
|
||||
virtual const Socket* getSocket() const {return clientSocket;}
|
||||
virtual void close();
|
||||
|
||||
//message processing
|
||||
virtual void update();
|
||||
|
@ -57,7 +61,7 @@ public:
|
|||
|
||||
// message sending
|
||||
virtual void sendTextMessage(const string &text, int teamIndex);
|
||||
virtual void quitGame(){}
|
||||
virtual void quitGame(bool userManuallyQuit);
|
||||
|
||||
//misc
|
||||
virtual string getNetworkStatus() const;
|
||||
|
@ -67,10 +71,11 @@ public:
|
|||
bool getLaunchGame() const {return launchGame;}
|
||||
bool getIntroDone() const {return introDone;}
|
||||
int getPlayerIndex() const {return playerIndex;}
|
||||
const GameSettings *getGameSettings() {return &gameSettings;}
|
||||
//const GameSettings *getGameSettings() {return &gameSettings;}
|
||||
|
||||
void connect(const Ip &ip, int port);
|
||||
void reset();
|
||||
virtual bool getFogOfWar();
|
||||
|
||||
private:
|
||||
void waitForMessage();
|
||||
|
|
|
@ -20,8 +20,12 @@
|
|||
#include "network_message.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
#include "platform_util.h"
|
||||
#include "map.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Util;
|
||||
//using namespace Shared::Platform;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
|
@ -29,43 +33,108 @@ namespace Glest{ namespace Game{
|
|||
// class ClientConnection
|
||||
// =====================================================
|
||||
|
||||
ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex){
|
||||
ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex)
|
||||
{
|
||||
this->serverInterface= serverInterface;
|
||||
this->playerIndex= playerIndex;
|
||||
socket= NULL;
|
||||
ready= false;
|
||||
|
||||
networkGameDataSynchCheckOkMap = false;
|
||||
networkGameDataSynchCheckOkTile = false;
|
||||
networkGameDataSynchCheckOkTech = false;
|
||||
networkGameDataSynchCheckOkFogOfWar = false;
|
||||
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
}
|
||||
|
||||
ConnectionSlot::~ConnectionSlot(){
|
||||
ConnectionSlot::~ConnectionSlot()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
close();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ConnectionSlot::update(){
|
||||
if(socket==NULL){
|
||||
socket= serverInterface->getServerSocket()->accept();
|
||||
void ConnectionSlot::update()
|
||||
{
|
||||
update(true);
|
||||
}
|
||||
|
||||
//send intro message when connected
|
||||
if(socket!=NULL){
|
||||
NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex);
|
||||
sendMessage(&networkMessageIntro);
|
||||
}
|
||||
void ConnectionSlot::update(bool checkForNewClients)
|
||||
{
|
||||
if(socket == NULL)
|
||||
{
|
||||
if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap = false;
|
||||
if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false;
|
||||
if(networkGameDataSynchCheckOkTech) networkGameDataSynchCheckOkTech = false;
|
||||
if(networkGameDataSynchCheckOkFogOfWar) networkGameDataSynchCheckOkFogOfWar = false;
|
||||
|
||||
// Is the listener socket ready to be read?
|
||||
//if(serverInterface->getServerSocket()->isReadable() == true)
|
||||
if(checkForNewClients == true)
|
||||
{
|
||||
socket = serverInterface->getServerSocket()->accept();
|
||||
|
||||
//send intro message when connected
|
||||
if(socket != NULL)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] accepted new client connection\n",__FILE__,__FUNCTION__);
|
||||
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
|
||||
NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex);
|
||||
sendMessage(&networkMessageIntro);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(socket->isConnected()){
|
||||
else
|
||||
{
|
||||
if(socket->isConnected())
|
||||
{
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
|
||||
NetworkMessageType networkMessageType= getNextMessageType();
|
||||
|
||||
//process incoming commands
|
||||
switch(networkMessageType){
|
||||
|
||||
case nmtInvalid:
|
||||
case nmtText:
|
||||
break;
|
||||
|
||||
case nmtText:
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__);
|
||||
|
||||
NetworkMessageText networkMessageText;
|
||||
if(receiveMessage(&networkMessageText))
|
||||
{
|
||||
chatText = networkMessageText.getText();
|
||||
chatSender = networkMessageText.getSender();
|
||||
chatTeamIndex = networkMessageText.getTeamIndex();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,chatText.c_str(),chatSender.c_str(),chatTeamIndex);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//command list
|
||||
case nmtCommandList:{
|
||||
case nmtCommandList: {
|
||||
|
||||
if(Socket::enableDebugText) printf("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));
|
||||
}
|
||||
}
|
||||
|
@ -73,10 +142,143 @@ void ConnectionSlot::update(){
|
|||
break;
|
||||
|
||||
//process intro messages
|
||||
case nmtIntro:{
|
||||
case nmtIntro:
|
||||
{
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtIntro\n",__FILE__,__FUNCTION__);
|
||||
|
||||
NetworkMessageIntro networkMessageIntro;
|
||||
if(receiveMessage(&networkMessageIntro)){
|
||||
if(receiveMessage(&networkMessageIntro))
|
||||
{
|
||||
name= networkMessageIntro.getName();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got name [%s]\n",__FILE__,__FUNCTION__,name.c_str());
|
||||
|
||||
if(getAllowGameDataSynchCheck() == true && serverInterface->getGameSettings() != NULL)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] sending NetworkMessageSynchNetworkGameData\n",__FILE__,__FUNCTION__);
|
||||
|
||||
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(serverInterface->getGameSettings());
|
||||
sendMessage(&networkMessageSynchNetworkGameData);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//process datasynch messages
|
||||
case nmtSynchNetworkGameDataStatus:
|
||||
{
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataStatus\n",__FILE__,__FUNCTION__);
|
||||
|
||||
NetworkMessageSynchNetworkGameDataStatus networkMessageSynchNetworkGameDataStatus;
|
||||
if(receiveMessage(&networkMessageSynchNetworkGameDataStatus))
|
||||
{
|
||||
receivedNetworkGameStatus = true;
|
||||
|
||||
int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", NULL);
|
||||
int32 techCRC = getFolderTreeContentsCheckSumRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL);
|
||||
Checksum checksum;
|
||||
string file = Map::getMapPath(serverInterface->getGameSettings()->getMap());
|
||||
checksum.addFile(file);
|
||||
int32 mapCRC = checksum.getSum();
|
||||
|
||||
networkGameDataSynchCheckOkMap = (networkMessageSynchNetworkGameDataStatus.getMapCRC() == mapCRC);
|
||||
networkGameDataSynchCheckOkTile = (networkMessageSynchNetworkGameDataStatus.getTilesetCRC() == tilesetCRC);
|
||||
networkGameDataSynchCheckOkTech = (networkMessageSynchNetworkGameDataStatus.getTechCRC() == techCRC);
|
||||
networkGameDataSynchCheckOkFogOfWar = (networkMessageSynchNetworkGameDataStatus.getFogOfWar() == serverInterface->getFogOfWar() == true);
|
||||
|
||||
// For testing
|
||||
//techCRC++;
|
||||
|
||||
if( networkGameDataSynchCheckOkMap == true &&
|
||||
networkGameDataSynchCheckOkTile == true &&
|
||||
networkGameDataSynchCheckOkTech == true &&
|
||||
networkGameDataSynchCheckOkFogOfWar == true)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] client data synch ok\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] mapCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameDataStatus.getMapCRC());
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] tilesetCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameDataStatus.getTilesetCRC());
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] techCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameDataStatus.getTechCRC());
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] serverInterface->getFogOfWar() = %d, remote = %d\n",__FILE__,__FUNCTION__,serverInterface->getFogOfWar(),networkMessageSynchNetworkGameDataStatus.getFogOfWar());
|
||||
|
||||
if(allowDownloadDataSynch == true)
|
||||
{
|
||||
// Now get all filenames with their CRC values and send to the client
|
||||
vctFileList.clear();
|
||||
|
||||
if(networkGameDataSynchCheckOkTile == false)
|
||||
{
|
||||
if(tilesetCRC == 0)
|
||||
{
|
||||
vctFileList = getFolderTreeContentsCheckSumListRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", "", &vctFileList);
|
||||
}
|
||||
else
|
||||
{
|
||||
vctFileList = getFolderTreeContentsCheckSumListRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList);
|
||||
}
|
||||
}
|
||||
if(networkGameDataSynchCheckOkTech == false)
|
||||
{
|
||||
if(techCRC == 0)
|
||||
{
|
||||
vctFileList = getFolderTreeContentsCheckSumListRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList);
|
||||
}
|
||||
else
|
||||
{
|
||||
vctFileList = getFolderTreeContentsCheckSumListRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList);
|
||||
}
|
||||
}
|
||||
if(networkGameDataSynchCheckOkMap == false)
|
||||
{
|
||||
vctFileList.push_back(std::pair<string,int32>(Map::getMapPath(serverInterface->getGameSettings()->getMap()),mapCRC));
|
||||
}
|
||||
|
||||
//for(int i = 0; i < vctFileList.size(); i++)
|
||||
//{
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck(vctFileList.size(), 1, vctFileList[0].second, vctFileList[0].first);
|
||||
sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtSynchNetworkGameDataFileCRCCheck:
|
||||
{
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck\n",__FILE__,__FUNCTION__);
|
||||
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck;
|
||||
if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck))
|
||||
{
|
||||
int fileIndex = networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex();
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck(vctFileList.size(), fileIndex, vctFileList[fileIndex-1].second, vctFileList[fileIndex-1].first);
|
||||
sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtSynchNetworkGameDataFileGet:
|
||||
{
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileGet\n",__FILE__,__FUNCTION__);
|
||||
|
||||
NetworkMessageSynchNetworkGameDataFileGet networkMessageSynchNetworkGameDataFileGet;
|
||||
if(receiveMessage(&networkMessageSynchNetworkGameDataFileGet))
|
||||
{
|
||||
FileTransferInfo fileInfo;
|
||||
fileInfo.hostType = eServer;
|
||||
//fileInfo.serverIP = this->ip.getString();
|
||||
fileInfo.serverPort = GameConstants::serverPort;
|
||||
fileInfo.fileName = networkMessageSynchNetworkGameDataFileGet.getFileName();
|
||||
|
||||
FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo);
|
||||
fileXferThread->start();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -85,15 +287,38 @@ void ConnectionSlot::update(){
|
|||
throw runtime_error("Unexpected message in connection slot: " + intToStr(networkMessageType));
|
||||
}
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] calling close...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionSlot::close(){
|
||||
void ConnectionSlot::close()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
delete socket;
|
||||
socket= NULL;
|
||||
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
bool ConnectionSlot::getFogOfWar()
|
||||
{
|
||||
return networkGameDataSynchCheckOkFogOfWar;
|
||||
}
|
||||
|
||||
bool ConnectionSlot::hasValidSocketId()
|
||||
{
|
||||
bool result = (socket != NULL && socket->getSocketId() > 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -37,23 +37,30 @@ private:
|
|||
int playerIndex;
|
||||
string name;
|
||||
bool ready;
|
||||
vector<std::pair<string,int32> > vctFileList;
|
||||
bool receivedNetworkGameStatus;
|
||||
|
||||
public:
|
||||
ConnectionSlot(ServerInterface* serverInterface, int playerIndex);
|
||||
~ConnectionSlot();
|
||||
|
||||
void update(bool checkForNewClients);
|
||||
virtual void update();
|
||||
|
||||
void setReady() {ready= true;}
|
||||
const string &getName() const {return name;}
|
||||
bool isReady() const {return ready;}
|
||||
|
||||
protected:
|
||||
virtual Socket* getSocket() {return socket;}
|
||||
virtual Socket* getSocket() const {return socket;}
|
||||
|
||||
private:
|
||||
void close();
|
||||
virtual void close();
|
||||
virtual bool getFogOfWar();
|
||||
|
||||
bool getReceivedNetworkGameStatus() { return receivedNetworkGameStatus; }
|
||||
void setReceivedNetworkGameStatus(bool value) { receivedNetworkGameStatus = value; }
|
||||
|
||||
bool hasValidSocketId();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "platform_util.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
#include <fstream>
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
|
@ -32,6 +33,9 @@ namespace Glest{ namespace Game{
|
|||
|
||||
const int NetworkInterface::readyWaitTimeout= 60000; //1 minute
|
||||
|
||||
bool NetworkInterface::allowGameDataSynchCheck = false;
|
||||
bool NetworkInterface::allowDownloadDataSynch = false;
|
||||
|
||||
|
||||
void NetworkInterface::sendMessage(const NetworkMessage* networkMessage){
|
||||
Socket* socket= getSocket();
|
||||
|
@ -39,31 +43,52 @@ void NetworkInterface::sendMessage(const NetworkMessage* networkMessage){
|
|||
networkMessage->send(socket);
|
||||
}
|
||||
|
||||
NetworkMessageType NetworkInterface::getNextMessageType(){
|
||||
NetworkMessageType NetworkInterface::getNextMessageType(bool checkHasDataFirst)
|
||||
{
|
||||
Socket* socket= getSocket();
|
||||
int8 messageType= nmtInvalid;
|
||||
|
||||
//peek message type
|
||||
if(socket->getDataToRead()>=sizeof(messageType)){
|
||||
socket->peek(&messageType, sizeof(messageType));
|
||||
}
|
||||
if(checkHasDataFirst == false ||
|
||||
(checkHasDataFirst == true &&
|
||||
socket != NULL &&
|
||||
socket->hasDataToRead() == true))
|
||||
{
|
||||
//peek message type
|
||||
int dataSize = socket->getDataToRead();
|
||||
if(dataSize >= sizeof(messageType)){
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() dataSize = %d\n",__FILE__,__FUNCTION__,dataSize);
|
||||
|
||||
//sanity check new message type
|
||||
if(messageType<0 || messageType>=nmtCount){
|
||||
throw runtime_error("Invalid message type: " + intToStr(messageType));
|
||||
}
|
||||
int iPeek = socket->peek(&messageType, sizeof(messageType));
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() iPeek = %d, messageType = %d\n",__FILE__,__FUNCTION__,iPeek,messageType);
|
||||
}
|
||||
|
||||
//sanity check new message type
|
||||
if(messageType<0 || messageType>=nmtCount){
|
||||
throw runtime_error("Invalid message type: " + intToStr(messageType));
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<NetworkMessageType>(messageType);
|
||||
}
|
||||
|
||||
bool NetworkInterface::receiveMessage(NetworkMessage* networkMessage){
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s]\n",__FILE__,__FUNCTION__);
|
||||
|
||||
Socket* socket= getSocket();
|
||||
|
||||
return networkMessage->receive(socket);
|
||||
}
|
||||
|
||||
bool NetworkInterface::isConnected(){
|
||||
return getSocket()!=NULL && getSocket()->isConnected();
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
bool result = (getSocket()!=NULL && getSocket()->isConnected());
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
|
@ -74,4 +99,181 @@ GameNetworkInterface::GameNetworkInterface(){
|
|||
quit= false;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class FileTransferSocketThread
|
||||
// =====================================================
|
||||
|
||||
const int32 SEND_FILE = 0x20;
|
||||
const int32 ACK = 0x47;
|
||||
|
||||
FileTransferSocketThread::FileTransferSocketThread(FileTransferInfo fileInfo)
|
||||
{
|
||||
this->info = fileInfo;
|
||||
this->info.serverPort += 100;
|
||||
}
|
||||
|
||||
void FileTransferSocketThread::execute()
|
||||
{
|
||||
if(info.hostType == eServer)
|
||||
{
|
||||
ServerSocket serverSocket;
|
||||
//serverSocket.setBlock(false);
|
||||
serverSocket.bind(this->info.serverPort);
|
||||
serverSocket.listen(1);
|
||||
Socket *clientSocket = serverSocket.accept();
|
||||
|
||||
char data[513]="";
|
||||
memset(data, 0, 256);
|
||||
|
||||
clientSocket->receive(data,256);
|
||||
if(*data == SEND_FILE)
|
||||
{
|
||||
FileInfo file;
|
||||
|
||||
memcpy(&file, data+1, sizeof(file));
|
||||
|
||||
*data=ACK;
|
||||
clientSocket->send(data,256);
|
||||
|
||||
Checksum checksum;
|
||||
checksum.addFile(file.fileName);
|
||||
file.filecrc = checksum.getSum();
|
||||
|
||||
ifstream infile(file.fileName.c_str(), ios::in | ios::binary | ios::ate);
|
||||
if(infile.is_open() == true)
|
||||
{
|
||||
file.filesize = infile.tellg();
|
||||
infile.seekg (0, ios::beg);
|
||||
|
||||
memset(data, 0, 256);
|
||||
*data=SEND_FILE;
|
||||
memcpy(data+1,&file,sizeof(file));
|
||||
|
||||
clientSocket->send(data,256);
|
||||
clientSocket->receive(data,256);
|
||||
if(*data != ACK)
|
||||
;//transfer error
|
||||
|
||||
int remain=file.filesize % 512 ;
|
||||
int packs=(file.filesize-remain)/512;
|
||||
|
||||
while(packs--)
|
||||
{
|
||||
infile.read(data,512);
|
||||
//if(!ReadFile(file,data,512,&read,NULL))
|
||||
// ; //read error
|
||||
//if(written!=pack)
|
||||
// ; //read error
|
||||
clientSocket->send(data,512);
|
||||
clientSocket->receive(data,256);
|
||||
if(*data!=ACK)
|
||||
;//transfer error
|
||||
}
|
||||
|
||||
infile.read(data,remain);
|
||||
//if(!ReadFile(file,data,remain,&read,NULL))
|
||||
// ; //read error
|
||||
//if(written!=pack)
|
||||
// ; //read error
|
||||
|
||||
clientSocket->send(data,remain);
|
||||
clientSocket->receive(data,256);
|
||||
if(*data!=ACK)
|
||||
;//transfer error
|
||||
|
||||
infile.close();
|
||||
}
|
||||
}
|
||||
|
||||
delete clientSocket;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ip ip(this->info.serverIP);
|
||||
ClientSocket clientSocket;
|
||||
//clientSocket.setBlock(false);
|
||||
clientSocket.connect(this->info.serverIP, this->info.serverPort);
|
||||
|
||||
if(clientSocket.isConnected() == true)
|
||||
{
|
||||
FileInfo file;
|
||||
file.fileName = this->info.fileName;
|
||||
//file.filesize =
|
||||
//file.filecrc = this->info.
|
||||
|
||||
string path = extractDirectoryPathFromFile(file.fileName);
|
||||
createDirectoryPaths(path);
|
||||
ofstream outFile(file.fileName.c_str(), ios_base::binary | ios_base::out);
|
||||
if(outFile.is_open() == true)
|
||||
{
|
||||
char data[513]="";
|
||||
memset(data, 0, 256);
|
||||
*data=SEND_FILE;
|
||||
memcpy(data+1,&file,sizeof(file));
|
||||
|
||||
clientSocket.send(data,256);
|
||||
clientSocket.receive(data,256);
|
||||
if(*data!=ACK)
|
||||
;//transfer error
|
||||
|
||||
clientSocket.receive(data,256);
|
||||
if(*data == SEND_FILE)
|
||||
{
|
||||
memcpy(&file, data+1, sizeof(file));
|
||||
*data=ACK;
|
||||
clientSocket.send(data,256);
|
||||
|
||||
int remain = file.filesize % 512 ;
|
||||
int packs = (file.filesize-remain) / 512;
|
||||
|
||||
while(packs--)
|
||||
{
|
||||
clientSocket.receive(data,512);
|
||||
|
||||
outFile.write(data, 512);
|
||||
if(outFile.bad())
|
||||
{
|
||||
int ii = 0;
|
||||
}
|
||||
//if(!WriteFile(file,data,512,&written,NULL))
|
||||
// ; //write error
|
||||
//if(written != pack)
|
||||
// ; //write error
|
||||
*data=ACK;
|
||||
clientSocket.send(data,256);
|
||||
}
|
||||
clientSocket.receive(data,remain);
|
||||
|
||||
outFile.write(data, remain);
|
||||
if(outFile.bad())
|
||||
{
|
||||
int ii = 0;
|
||||
}
|
||||
|
||||
//if(!WriteFile(file,data,remain,&written,NULL))
|
||||
// ; //write error
|
||||
//if(written!=pack)
|
||||
// ; //write error
|
||||
*data=ACK;
|
||||
clientSocket.send(data,256);
|
||||
|
||||
Checksum checksum;
|
||||
checksum.addFile(file.fileName);
|
||||
int32 crc = checksum.getSum();
|
||||
if(file.filecrc != crc)
|
||||
{
|
||||
int ii = 0;
|
||||
}
|
||||
|
||||
//if(calc_crc(file)!=info.crc)
|
||||
// ; //transfeer error
|
||||
}
|
||||
|
||||
outFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -19,34 +19,82 @@
|
|||
#include "network_message.h"
|
||||
#include "network_types.h"
|
||||
|
||||
#include "game_settings.h"
|
||||
|
||||
#include "thread.h"
|
||||
#include "types.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using Shared::Util::Checksum;
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Platform;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
//class GameSettings;
|
||||
|
||||
// =====================================================
|
||||
// class NetworkInterface
|
||||
// =====================================================
|
||||
|
||||
class NetworkInterface{
|
||||
class NetworkInterface {
|
||||
|
||||
protected:
|
||||
static bool allowGameDataSynchCheck;
|
||||
static bool allowDownloadDataSynch;
|
||||
bool networkGameDataSynchCheckOkMap;
|
||||
bool networkGameDataSynchCheckOkTile;
|
||||
bool networkGameDataSynchCheckOkTech;
|
||||
bool networkGameDataSynchCheckOkFogOfWar;
|
||||
|
||||
string chatText;
|
||||
string chatSender;
|
||||
int chatTeamIndex;
|
||||
|
||||
public:
|
||||
static const int readyWaitTimeout;
|
||||
GameSettings gameSettings;
|
||||
|
||||
public:
|
||||
virtual ~NetworkInterface(){}
|
||||
|
||||
virtual Socket* getSocket()= 0;
|
||||
virtual const Socket* getSocket() const= 0;
|
||||
virtual void close()= 0;
|
||||
|
||||
string getIp() const {return getSocket()->getIp();}
|
||||
string getHostName() const {return getSocket()->getHostName();}
|
||||
|
||||
void sendMessage(const NetworkMessage* networkMessage);
|
||||
NetworkMessageType getNextMessageType();
|
||||
NetworkMessageType getNextMessageType(bool checkHasDataFirst = false);
|
||||
bool receiveMessage(NetworkMessage* networkMessage);
|
||||
|
||||
bool isConnected();
|
||||
|
||||
//virtual void setGameSettings(GameSettings *serverGameSettings) { gameSettings = *serverGameSettings; }
|
||||
const virtual GameSettings * getGameSettings() { return &gameSettings; }
|
||||
|
||||
virtual void setAllowDownloadDataSynch(bool value) { allowDownloadDataSynch = value; }
|
||||
virtual bool getAllowDownloadDataSynch() { return allowDownloadDataSynch; }
|
||||
|
||||
virtual void setAllowGameDataSynchCheck(bool value) { allowGameDataSynchCheck = value; }
|
||||
virtual bool getAllowGameDataSynchCheck() { return allowGameDataSynchCheck; }
|
||||
|
||||
virtual bool getNetworkGameDataSynchCheckOk() { return (networkGameDataSynchCheckOkMap && networkGameDataSynchCheckOkTile && networkGameDataSynchCheckOkTech && networkGameDataSynchCheckOkFogOfWar); }
|
||||
virtual void setNetworkGameDataSynchCheckOkMap(bool value) { networkGameDataSynchCheckOkMap = value; }
|
||||
virtual void setNetworkGameDataSynchCheckOkTile(bool value) { networkGameDataSynchCheckOkTile = value; }
|
||||
virtual void setNetworkGameDataSynchCheckOkTech(bool value) { networkGameDataSynchCheckOkTech = value; }
|
||||
virtual bool getNetworkGameDataSynchCheckOkMap() { return networkGameDataSynchCheckOkMap; }
|
||||
virtual bool getNetworkGameDataSynchCheckOkTile() { return networkGameDataSynchCheckOkTile; }
|
||||
virtual bool getNetworkGameDataSynchCheckOkTech() { return networkGameDataSynchCheckOkTech; }
|
||||
virtual bool getFogOfWar()=0;
|
||||
virtual bool getNetworkGameDataSynchCheckOkFogOfWar() { return networkGameDataSynchCheckOkFogOfWar; }
|
||||
virtual void setNetworkGameDataSynchCheckOkFogOfWar(bool value) { networkGameDataSynchCheckOkFogOfWar = value; }
|
||||
|
||||
const string getChatText() const {return chatText;}
|
||||
const string getChatSender() const {return chatSender;}
|
||||
int getChatTeamIndex() const {return chatTeamIndex;}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
|
@ -64,9 +112,6 @@ protected:
|
|||
Commands requestedCommands; //commands requested by the user
|
||||
Commands pendingCommands; //commands ready to be given
|
||||
bool quit;
|
||||
string chatText;
|
||||
string chatSender;
|
||||
int chatTeamIndex;
|
||||
|
||||
public:
|
||||
GameNetworkInterface();
|
||||
|
@ -79,7 +124,7 @@ public:
|
|||
|
||||
//message sending
|
||||
virtual void sendTextMessage(const string &text, int teamIndex)= 0;
|
||||
virtual void quitGame()=0;
|
||||
virtual void quitGame(bool userManuallyQuit)=0;
|
||||
|
||||
//misc
|
||||
virtual string getNetworkStatus() const= 0;
|
||||
|
@ -90,11 +135,77 @@ public:
|
|||
const NetworkCommand* getPendingCommand(int i) const {return &pendingCommands[i];}
|
||||
void clearPendingCommands() {pendingCommands.clear();}
|
||||
bool getQuit() const {return quit;}
|
||||
const string getChatText() const {return chatText;}
|
||||
const string getChatSender() const {return chatSender;}
|
||||
int getChatTeamIndex() const {return chatTeamIndex;}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class FileTransferSocketThread
|
||||
// =====================================================
|
||||
|
||||
enum FileTransferHostType
|
||||
{
|
||||
eClient,
|
||||
eServer
|
||||
};
|
||||
|
||||
enum FileTransferOperationType
|
||||
{
|
||||
eSend,
|
||||
eReceive
|
||||
};
|
||||
|
||||
class FileTransferInfo
|
||||
{
|
||||
private:
|
||||
|
||||
void CopyAll(const FileTransferInfo &obj)
|
||||
{
|
||||
hostType = obj.hostType;
|
||||
serverIP = obj.serverIP;
|
||||
serverPort = obj.serverPort;
|
||||
opType = obj.opType;
|
||||
fileName = obj.fileName;
|
||||
}
|
||||
|
||||
public:
|
||||
FileTransferInfo()
|
||||
{
|
||||
}
|
||||
FileTransferInfo(const FileTransferInfo &obj)
|
||||
{
|
||||
CopyAll(obj);
|
||||
}
|
||||
FileTransferInfo &operator=(const FileTransferInfo &obj)
|
||||
{
|
||||
CopyAll(obj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileTransferHostType hostType;
|
||||
string serverIP;
|
||||
int32 serverPort;
|
||||
FileTransferOperationType opType;
|
||||
string fileName;
|
||||
};
|
||||
|
||||
class FileInfo
|
||||
{
|
||||
public:
|
||||
string fileName;
|
||||
int64 filesize;
|
||||
int32 filecrc;
|
||||
};
|
||||
|
||||
class FileTransferSocketThread : public Thread
|
||||
{
|
||||
private:
|
||||
FileTransferInfo info;
|
||||
|
||||
public:
|
||||
FileTransferSocketThread(FileTransferInfo fileInfo);
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
#include "checksum.h"
|
||||
#include "map.h"
|
||||
#include "platform_util.h"
|
||||
#include "config.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
@ -30,19 +35,48 @@ namespace Glest{ namespace Game{
|
|||
// class NetworkMessage
|
||||
// =====================================================
|
||||
|
||||
bool NetworkMessage::receive(Socket* socket, void* data, int dataSize){
|
||||
if(socket->getDataToRead()>=dataSize){
|
||||
if(socket->receive(data, dataSize)!=dataSize){
|
||||
throw runtime_error("Error receiving NetworkMessage");
|
||||
bool NetworkMessage::receive(Socket* socket, void* data, int dataSize)
|
||||
{
|
||||
int ipeekdatalen = socket->getDataToRead();
|
||||
|
||||
if(ipeekdatalen >= dataSize)
|
||||
{
|
||||
if(socket->receive(data, dataSize)!=dataSize)
|
||||
{
|
||||
if(socket != NULL && socket->getSocketId() > 0)
|
||||
{
|
||||
throw runtime_error("Error receiving NetworkMessage");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socket has been disconnected\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] dataSize = %d\n",__FILE__,__FUNCTION__,dataSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() returned %d\n",__FILE__,__FUNCTION__,ipeekdatalen);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const{
|
||||
if(socket->send(data, dataSize)!=dataSize){
|
||||
throw runtime_error("Error sending NetworkMessage");
|
||||
void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const
|
||||
{
|
||||
if(socket->send(data, dataSize)!=dataSize)
|
||||
{
|
||||
if(socket != NULL && socket->getSocketId() > 0)
|
||||
{
|
||||
throw runtime_error("Error sending NetworkMessage");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socket has been disconnected\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,12 +204,23 @@ bool NetworkMessageCommandList::addCommand(const NetworkCommand* networkCommand)
|
|||
}
|
||||
|
||||
bool NetworkMessageCommandList::receive(Socket* socket){
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
//return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
|
||||
// read type, commandCount & frame num first.
|
||||
if (!NetworkMessage::receive(socket, &data, networkPacketMsgTypeSize)) {
|
||||
return false;
|
||||
}
|
||||
// read data.commandCount commands.
|
||||
if (data.commandCount) {
|
||||
return NetworkMessage::receive(socket, &data.commands, sizeof(NetworkCommand) * data.commandCount);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetworkMessageCommandList::send(Socket* socket) const{
|
||||
assert(data.messageType==nmtCommandList);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
//NetworkMessage::send(socket, &data, sizeof(data));
|
||||
NetworkMessage::send(socket, &data, networkPacketMsgTypeSize + sizeof(NetworkCommand) * data.commandCount);
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
|
@ -215,4 +260,133 @@ void NetworkMessageQuit::send(Socket* socket) const{
|
|||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageSynchNetworkGameData
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageSynchNetworkGameData::NetworkMessageSynchNetworkGameData(const GameSettings *gameSettings)
|
||||
{
|
||||
data.messageType= nmtSynchNetworkGameData;
|
||||
|
||||
data.map = gameSettings->getMap();
|
||||
data.tileset = gameSettings->getTileset();
|
||||
data.tech = gameSettings->getTech();
|
||||
|
||||
//Checksum checksum;
|
||||
//tileset
|
||||
//string file = "tilesets/" + gameSettings->getTileset() + "/" + gameSettings->getTileset() + ".xml";
|
||||
//checksum.addFile(file);
|
||||
// models
|
||||
// sounds
|
||||
// textures
|
||||
//data.tilesetCRC = checksum.getSum();
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.tilesetCRC);
|
||||
data.tilesetCRC = getFolderTreeContentsCheckSumRecursively("tilesets/" + gameSettings->getTileset() + "/*", "xml", NULL);
|
||||
|
||||
//tech, load before map because of resources
|
||||
//checksum = Checksum();
|
||||
//file = "techs/" + gameSettings->getTech() + "/" + gameSettings->getTech() + ".xml";
|
||||
//checksum.addFile(file);
|
||||
// factions
|
||||
// resources
|
||||
//data.techCRC = checksum.getSum();
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.techCRC);
|
||||
data.techCRC = getFolderTreeContentsCheckSumRecursively("techs/" + gameSettings->getTech() + "/*", "xml", NULL);
|
||||
|
||||
//map
|
||||
Checksum checksum;
|
||||
string file = Map::getMapPath(gameSettings->getMap());
|
||||
checksum.addFile(file);
|
||||
data.mapCRC = checksum.getSum();
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.mapCRC);
|
||||
|
||||
data.hasFogOfWar = Config::getInstance().getBool("FogOfWar");;
|
||||
}
|
||||
|
||||
bool NetworkMessageSynchNetworkGameData::receive(Socket* socket)
|
||||
{
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageSynchNetworkGameData::send(Socket* socket) const
|
||||
{
|
||||
assert(data.messageType==nmtSynchNetworkGameData);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageSynchNetworkGameDataStatus
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageSynchNetworkGameDataStatus::NetworkMessageSynchNetworkGameDataStatus(int32 mapCRC, int32 tilesetCRC, int32 techCRC, int8 hasFogOfWar)
|
||||
{
|
||||
data.messageType= nmtSynchNetworkGameDataStatus;
|
||||
|
||||
data.tilesetCRC = tilesetCRC;
|
||||
data.techCRC = techCRC;
|
||||
data.mapCRC = mapCRC;
|
||||
|
||||
data.hasFogOfWar = hasFogOfWar;
|
||||
}
|
||||
|
||||
bool NetworkMessageSynchNetworkGameDataStatus::receive(Socket* socket)
|
||||
{
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageSynchNetworkGameDataStatus::send(Socket* socket) const
|
||||
{
|
||||
assert(data.messageType==nmtSynchNetworkGameDataStatus);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageSynchNetworkGameDataFileCRCCheck
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck::NetworkMessageSynchNetworkGameDataFileCRCCheck(int32 totalFileCount, int32 fileIndex, int32 fileCRC, const string fileName)
|
||||
{
|
||||
data.messageType= nmtSynchNetworkGameDataFileCRCCheck;
|
||||
|
||||
data.totalFileCount = totalFileCount;
|
||||
data.fileIndex = fileIndex;
|
||||
data.fileCRC = fileCRC;
|
||||
data.fileName = fileName;
|
||||
}
|
||||
|
||||
bool NetworkMessageSynchNetworkGameDataFileCRCCheck::receive(Socket* socket)
|
||||
{
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageSynchNetworkGameDataFileCRCCheck::send(Socket* socket) const
|
||||
{
|
||||
assert(data.messageType==nmtSynchNetworkGameDataFileCRCCheck);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageSynchNetworkGameDataFileGet
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageSynchNetworkGameDataFileGet::NetworkMessageSynchNetworkGameDataFileGet(const string fileName)
|
||||
{
|
||||
data.messageType= nmtSynchNetworkGameDataFileGet;
|
||||
|
||||
data.fileName = fileName;
|
||||
}
|
||||
|
||||
bool NetworkMessageSynchNetworkGameDataFileGet::receive(Socket* socket)
|
||||
{
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageSynchNetworkGameDataFileGet::send(Socket* socket) const
|
||||
{
|
||||
assert(data.messageType==nmtSynchNetworkGameDataFileGet);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -33,10 +33,16 @@ enum NetworkMessageType{
|
|||
nmtCommandList,
|
||||
nmtText,
|
||||
nmtQuit,
|
||||
nmtSynchNetworkGameData,
|
||||
nmtSynchNetworkGameDataStatus,
|
||||
nmtSynchNetworkGameDataFileCRCCheck,
|
||||
nmtSynchNetworkGameDataFileGet,
|
||||
|
||||
nmtCount
|
||||
};
|
||||
|
||||
const int32 networkPacketMsgTypeSize = 6;
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessage
|
||||
// =====================================================
|
||||
|
@ -163,6 +169,7 @@ public:
|
|||
// Message to order a commands to several units
|
||||
// =====================================================
|
||||
|
||||
#pragma pack(push, 1)
|
||||
class NetworkMessageCommandList: public NetworkMessage{
|
||||
private:
|
||||
static const int maxCommandCount= 16*4;
|
||||
|
@ -191,6 +198,7 @@ public:
|
|||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageText
|
||||
|
@ -247,6 +255,164 @@ public:
|
|||
virtual void send(Socket* socket) const;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageSynchNetworkGameData
|
||||
//
|
||||
// Message sent at the beggining of a network game
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageSynchNetworkGameData: public NetworkMessage{
|
||||
|
||||
private:
|
||||
|
||||
static const int maxStringSize= 256;
|
||||
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
|
||||
NetworkString<maxStringSize> map;
|
||||
NetworkString<maxStringSize> tileset;
|
||||
NetworkString<maxStringSize> tech;
|
||||
|
||||
int32 mapCRC;
|
||||
int32 tilesetCRC;
|
||||
int32 techCRC;
|
||||
int8 hasFogOfWar;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageSynchNetworkGameData() {};
|
||||
NetworkMessageSynchNetworkGameData(const GameSettings *gameSettings);
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
|
||||
string getMap() const {return data.map.getString();}
|
||||
string getTileset() const {return data.tileset.getString();}
|
||||
string getTech() const {return data.tech.getString();}
|
||||
|
||||
int32 getMapCRC() const {return data.mapCRC;}
|
||||
int32 getTilesetCRC() const {return data.tilesetCRC;}
|
||||
int32 getTechCRC() const {return data.techCRC;}
|
||||
|
||||
int8 getFogOfWar() const { return data.hasFogOfWar; }
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageSynchNetworkGameDataStatus
|
||||
//
|
||||
// Message sent at the beggining of a network game
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageSynchNetworkGameDataStatus: public NetworkMessage{
|
||||
|
||||
private:
|
||||
|
||||
static const int maxStringSize= 256;
|
||||
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
|
||||
int32 mapCRC;
|
||||
int32 tilesetCRC;
|
||||
int32 techCRC;
|
||||
|
||||
int8 hasFogOfWar;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageSynchNetworkGameDataStatus() {};
|
||||
NetworkMessageSynchNetworkGameDataStatus(int32 mapCRC, int32 tilesetCRC, int32 techCRC, int8 hasFogOfWar);
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
|
||||
int32 getMapCRC() const {return data.mapCRC;}
|
||||
int32 getTilesetCRC() const {return data.tilesetCRC;}
|
||||
int32 getTechCRC() const {return data.techCRC;}
|
||||
|
||||
int8 getFogOfWar() const { return data.hasFogOfWar; }
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageSynchNetworkGameDataFileCRCCheck
|
||||
//
|
||||
// Message sent at the beggining of a network game
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageSynchNetworkGameDataFileCRCCheck: public NetworkMessage{
|
||||
|
||||
private:
|
||||
|
||||
static const int maxStringSize= 256;
|
||||
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
|
||||
int32 totalFileCount;
|
||||
int32 fileIndex;
|
||||
int32 fileCRC;
|
||||
NetworkString<maxStringSize> fileName;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck() {};
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck(int32 totalFileCount, int32 fileIndex, int32 fileCRC, const string fileName);
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
|
||||
int32 getTotalFileCount() const {return data.totalFileCount;}
|
||||
int32 getFileIndex() const {return data.fileIndex;}
|
||||
int32 getFileCRC() const {return data.fileCRC;}
|
||||
string getFileName() const {return data.fileName.getString();}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageSynchNetworkGameDataFileGet
|
||||
//
|
||||
// Message sent at the beggining of a network game
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageSynchNetworkGameDataFileGet: public NetworkMessage{
|
||||
|
||||
private:
|
||||
|
||||
static const int maxStringSize= 256;
|
||||
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
|
||||
NetworkString<maxStringSize> fileName;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageSynchNetworkGameDataFileGet() {};
|
||||
NetworkMessageSynchNetworkGameDataFileGet(const string fileName);
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
|
||||
string getFileName() const {return data.fileName.getString();}
|
||||
};
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,6 +50,7 @@ enum NetworkCommandType{
|
|||
nctSetMeetingPoint
|
||||
};
|
||||
|
||||
#pragma pack(push, 2)
|
||||
class NetworkCommand{
|
||||
private:
|
||||
int16 networkCommandType;
|
||||
|
@ -71,6 +72,7 @@ public:
|
|||
int getUnitTypeId() const {return unitTypeId;}
|
||||
int getTargetId() const {return targetId;}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
}}//end namespace
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "lang.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
#include "logger.h"
|
||||
#include <time.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Platform;
|
||||
|
@ -32,6 +34,9 @@ namespace Glest{ namespace Game{
|
|||
// =====================================================
|
||||
|
||||
ServerInterface::ServerInterface(){
|
||||
gameHasBeenInitiated = false;
|
||||
gameSettingsUpdateCount = 0;
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
slots[i]= NULL;
|
||||
}
|
||||
|
@ -40,23 +45,39 @@ ServerInterface::ServerInterface(){
|
|||
}
|
||||
|
||||
ServerInterface::~ServerInterface(){
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
delete slots[i];
|
||||
}
|
||||
|
||||
close();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ServerInterface::addSlot(int playerIndex){
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
|
||||
|
||||
delete slots[playerIndex];
|
||||
slots[playerIndex]= new ConnectionSlot(this, playerIndex);
|
||||
updateListen();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ServerInterface::removeSlot(int playerIndex){
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
delete slots[playerIndex];
|
||||
slots[playerIndex]= NULL;
|
||||
updateListen();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
ConnectionSlot* ServerInterface::getSlot(int playerIndex){
|
||||
|
@ -74,38 +95,132 @@ int ServerInterface::getConnectedSlotCount(){
|
|||
return connectedSlotCount;
|
||||
}
|
||||
|
||||
void ServerInterface::update(){
|
||||
|
||||
void ServerInterface::update()
|
||||
{
|
||||
std::map<int,bool> socketTriggeredList;
|
||||
//update all slots
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
if(slots[i]!= NULL){
|
||||
slots[i]->update();
|
||||
for(int i= 0; i < GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL &&
|
||||
slots[i]->getSocket()->getSocketId() > 0)
|
||||
{
|
||||
socketTriggeredList[connectionSlot->getSocket()->getSocketId()] = false;
|
||||
}
|
||||
}
|
||||
|
||||
//process text messages
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0)
|
||||
{
|
||||
if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList.size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
|
||||
|
||||
if(connectionSlot!= NULL){
|
||||
if(connectionSlot->isConnected()){
|
||||
if(connectionSlot->getNextMessageType()==nmtText){
|
||||
NetworkMessageText networkMessageText;
|
||||
if(connectionSlot->receiveMessage(&networkMessageText)){
|
||||
broadcastMessage(&networkMessageText, i);
|
||||
chatText= networkMessageText.getText();
|
||||
chatSender= networkMessageText.getSender();
|
||||
chatTeamIndex= networkMessageText.getTeamIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool hasData = Socket::hasDataToRead(socketTriggeredList);
|
||||
|
||||
if(hasData && Socket::enableDebugText) printf("In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
|
||||
|
||||
if(gameHasBeenInitiated == false || hasData == true)
|
||||
{
|
||||
//if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
|
||||
|
||||
//std::vector<TeamMessageData> vctTeamMessages;
|
||||
|
||||
//update all slots
|
||||
bool checkForNewClients = true;
|
||||
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() == false ||
|
||||
(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))
|
||||
{
|
||||
if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList[i] = %i\n",__FILE__,__FUNCTION__,(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] ? 1 : 0));
|
||||
|
||||
if(connectionSlot->isConnected())
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] calling slots[i]->update() for slot = %d socketId = %d\n",
|
||||
__FILE__,__FUNCTION__,i,connectionSlot->getSocket()->getSocketId());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(gameHasBeenInitiated && Socket::enableDebugText) printf("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)
|
||||
{
|
||||
checkForNewClients = false;
|
||||
}
|
||||
|
||||
if(connectionSlot != NULL &&
|
||||
//connectionSlot->isConnected() == true &&
|
||||
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);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] #1 about to broadcast nmtText chatText [%s] chatSender [%s] chatTeamIndex = %d for SlotIndex# %d\n",__FILE__,__FUNCTION__,chatText.c_str(),chatSender.c_str(),chatTeamIndex,i);
|
||||
|
||||
NetworkMessageText networkMessageText(chatText,chatSender,chatTeamIndex);
|
||||
broadcastMessage(&networkMessageText, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//process text messages
|
||||
if(chatText.empty() == true)
|
||||
{
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
|
||||
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)
|
||||
{
|
||||
if(connectionSlot->getSocket() != NULL && Socket::enableDebugText) printf("In [%s::%s] calling connectionSlot->getNextMessageType() for slots[i]->getSocket()->getSocketId() = %d\n",
|
||||
__FILE__,__FUNCTION__,connectionSlot->getSocket()->getSocketId());
|
||||
|
||||
if(connectionSlot->getNextMessageType() == nmtText)
|
||||
{
|
||||
NetworkMessageText networkMessageText;
|
||||
if(connectionSlot->receiveMessage(&networkMessageText))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] #2 about to broadcast nmtText msg for SlotIndex# %d\n",__FILE__,__FUNCTION__,i);
|
||||
|
||||
broadcastMessage(&networkMessageText, i);
|
||||
chatText= networkMessageText.getText();
|
||||
chatSender= networkMessageText.getSender();
|
||||
chatTeamIndex= networkMessageText.getTeamIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerInterface::updateKeyframe(int frameCount){
|
||||
|
@ -129,50 +244,99 @@ void ServerInterface::updateKeyframe(int frameCount){
|
|||
|
||||
void ServerInterface::waitUntilReady(Checksum* checksum){
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s] START\n",__FUNCTION__);
|
||||
|
||||
Logger &logger= Logger::getInstance();
|
||||
gameHasBeenInitiated = true;
|
||||
|
||||
Chrono chrono;
|
||||
bool allReady= false;
|
||||
|
||||
chrono.start();
|
||||
|
||||
//wait until we get a ready message from all clients
|
||||
while(!allReady){
|
||||
|
||||
while(allReady == false)
|
||||
{
|
||||
vector<string> waitingForHosts;
|
||||
allReady= true;
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(connectionSlot!=NULL){
|
||||
if(!connectionSlot->isReady()){
|
||||
NetworkMessageType networkMessageType= connectionSlot->getNextMessageType();
|
||||
if(connectionSlot != NULL && connectionSlot->isConnected() == true)
|
||||
{
|
||||
if(connectionSlot->isReady() == false)
|
||||
{
|
||||
NetworkMessageType networkMessageType= connectionSlot->getNextMessageType(true);
|
||||
NetworkMessageReady networkMessageReady;
|
||||
|
||||
if(networkMessageType==nmtReady && connectionSlot->receiveMessage(&networkMessageReady)){
|
||||
if(networkMessageType == nmtReady &&
|
||||
connectionSlot->receiveMessage(&networkMessageReady))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s] networkMessageType==nmtReady\n",__FUNCTION__);
|
||||
|
||||
connectionSlot->setReady();
|
||||
}
|
||||
else if(networkMessageType!=nmtInvalid){
|
||||
else if(networkMessageType != nmtInvalid)
|
||||
{
|
||||
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
|
||||
}
|
||||
|
||||
waitingForHosts.push_back(connectionSlot->getHostName());
|
||||
|
||||
allReady= false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for timeout
|
||||
if(chrono.getMillis()>readyWaitTimeout){
|
||||
throw runtime_error("Timeout waiting for clients");
|
||||
if(allReady == false)
|
||||
{
|
||||
if(chrono.getMillis() > readyWaitTimeout)
|
||||
{
|
||||
throw runtime_error("Timeout waiting for clients");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(chrono.getMillis() % 1000 == 0)
|
||||
{
|
||||
string waitForHosts = "";
|
||||
for(int i = 0; i < waitingForHosts.size(); i++)
|
||||
{
|
||||
if(waitForHosts != "")
|
||||
{
|
||||
waitForHosts += ", ";
|
||||
}
|
||||
waitForHosts += waitingForHosts[i];
|
||||
}
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Waiting for network: %d of %d max seconds (waiting for: %s)",int(chrono.getMillis() / 1000),int(readyWaitTimeout / 1000),waitForHosts.c_str());
|
||||
logger.add(szBuf, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//send ready message after, so clients start delayed
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
NetworkMessageReady networkMessageReady(checksum->getSum());
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(connectionSlot!=NULL){
|
||||
// FOR TESTING ONLY - delay to see the client count up while waiting
|
||||
//sleep(5000);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s] PART B (telling client we are ready!\n",__FUNCTION__);
|
||||
|
||||
//send ready message after, so clients start delayed
|
||||
for(int i= 0; i < GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
NetworkMessageReady networkMessageReady(checksum->getSum());
|
||||
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
if(connectionSlot!=NULL)
|
||||
{
|
||||
connectionSlot->sendMessage(&networkMessageReady);
|
||||
}
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s] END\n",__FUNCTION__);
|
||||
}
|
||||
|
||||
void ServerInterface::sendTextMessage(const string &text, int teamIndex){
|
||||
|
@ -180,7 +344,15 @@ void ServerInterface::sendTextMessage(const string &text, int teamIndex){
|
|||
broadcastMessage(&networkMessageText);
|
||||
}
|
||||
|
||||
void ServerInterface::quitGame(){
|
||||
void ServerInterface::quitGame(bool userManuallyQuit)
|
||||
{
|
||||
if(userManuallyQuit == true)
|
||||
{
|
||||
string sQuitText = getHostName() + " has chosen to leave the game!";
|
||||
NetworkMessageText networkMessageText(sQuitText,getHostName(),-1);
|
||||
broadcastMessage(&networkMessageText, -1);
|
||||
}
|
||||
|
||||
NetworkMessageQuit networkMessageQuit;
|
||||
broadcastMessage(&networkMessageQuit);
|
||||
}
|
||||
|
@ -196,7 +368,8 @@ string ServerInterface::getNetworkStatus() const{
|
|||
|
||||
if(connectionSlot!= NULL){
|
||||
if(connectionSlot->isConnected()){
|
||||
str+= connectionSlot->getName();
|
||||
|
||||
str+= connectionSlot->getName();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -209,31 +382,96 @@ string ServerInterface::getNetworkStatus() const{
|
|||
return str;
|
||||
}
|
||||
|
||||
void ServerInterface::launchGame(const GameSettings* gameSettings){
|
||||
NetworkMessageLaunch networkMessageLaunch(gameSettings);
|
||||
broadcastMessage(&networkMessageLaunch);
|
||||
bool ServerInterface::launchGame(const GameSettings* gameSettings){
|
||||
|
||||
bool bOkToStart = true;
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
ConnectionSlot *connectionSlot= slots[i];
|
||||
if(connectionSlot != NULL &&
|
||||
connectionSlot->getAllowDownloadDataSynch() == true &&
|
||||
connectionSlot->isConnected())
|
||||
{
|
||||
if(connectionSlot->getNetworkGameDataSynchCheckOk() == false)
|
||||
{
|
||||
bOkToStart = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bOkToStart == true)
|
||||
{
|
||||
NetworkMessageLaunch networkMessageLaunch(gameSettings);
|
||||
broadcastMessage(&networkMessageLaunch);
|
||||
}
|
||||
|
||||
return bOkToStart;
|
||||
}
|
||||
|
||||
void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot){
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(i != excludeSlot && connectionSlot != NULL)
|
||||
{
|
||||
if(connectionSlot->isConnected())
|
||||
{
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
|
||||
connectionSlot->sendMessage(networkMessage);
|
||||
}
|
||||
else if(gameHasBeenInitiated == true)
|
||||
{
|
||||
|
||||
if(Socket::enableDebugText) printf("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)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
|
||||
removeSlot(i);
|
||||
}
|
||||
}
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot){
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(i!= excludeSlot && connectionSlot!= NULL){
|
||||
if(connectionSlot->isConnected()){
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
|
||||
|
||||
connectionSlot->sendMessage(networkMessage);
|
||||
}
|
||||
else{
|
||||
removeSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ServerInterface::updateListen(){
|
||||
void ServerInterface::updateListen()
|
||||
{
|
||||
int openSlotCount= 0;
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
if(slots[i]!= NULL && !slots[i]->isConnected()){
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
if(slots[i] != NULL && slots[i]->isConnected() == false)
|
||||
{
|
||||
++openSlotCount;
|
||||
}
|
||||
}
|
||||
|
@ -241,4 +479,92 @@ void ServerInterface::updateListen(){
|
|||
serverSocket.listen(openSlotCount);
|
||||
}
|
||||
|
||||
void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START gameSettingsUpdateCount = %d\n",__FILE__,__FUNCTION__,gameSettingsUpdateCount);
|
||||
|
||||
if(getAllowGameDataSynchCheck() == true)
|
||||
{
|
||||
if(waitForClientAck == true && gameSettingsUpdateCount > 0)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Waiting for client acks #1\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStart = time(NULL);
|
||||
bool gotAckFromAllClients = false;
|
||||
while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5)
|
||||
{
|
||||
gotAckFromAllClients = true;
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
ConnectionSlot *connectionSlot = slots[i];
|
||||
if(connectionSlot != NULL && connectionSlot->isConnected())
|
||||
{
|
||||
if(connectionSlot->getReceivedNetworkGameStatus() == false)
|
||||
{
|
||||
gotAckFromAllClients = false;
|
||||
}
|
||||
|
||||
connectionSlot->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
ConnectionSlot *connectionSlot = slots[i];
|
||||
if(connectionSlot != NULL && connectionSlot->isConnected())
|
||||
{
|
||||
connectionSlot->setReceivedNetworkGameStatus(false);
|
||||
}
|
||||
}
|
||||
|
||||
gameSettings = *serverGameSettings;
|
||||
|
||||
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(getGameSettings());
|
||||
broadcastMessageToConnectedClients(&networkMessageSynchNetworkGameData);
|
||||
|
||||
if(waitForClientAck == true)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Waiting for client acks #2\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStart = time(NULL);
|
||||
bool gotAckFromAllClients = false;
|
||||
while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5)
|
||||
{
|
||||
gotAckFromAllClients = true;
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
ConnectionSlot *connectionSlot = slots[i];
|
||||
if(connectionSlot != NULL && connectionSlot->isConnected())
|
||||
{
|
||||
if(connectionSlot->getReceivedNetworkGameStatus() == false)
|
||||
{
|
||||
gotAckFromAllClients = false;
|
||||
}
|
||||
|
||||
connectionSlot->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gameSettingsUpdateCount++;
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
void ServerInterface::close()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
//serverSocket = ServerSocket();
|
||||
}
|
||||
|
||||
bool ServerInterface::getFogOfWar()
|
||||
{
|
||||
return Config::getInstance().getBool("FogOfWar");
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -28,10 +28,21 @@ namespace Glest{ namespace Game{
|
|||
// class ServerInterface
|
||||
// =====================================================
|
||||
|
||||
typedef struct
|
||||
{
|
||||
string chatText;
|
||||
string chatSender;
|
||||
int chatTeamIndex;
|
||||
int sourceTeamIndex;
|
||||
|
||||
} TeamMessageData;
|
||||
|
||||
class ServerInterface: public GameNetworkInterface{
|
||||
private:
|
||||
ConnectionSlot* slots[GameConstants::maxPlayers];
|
||||
ServerSocket serverSocket;
|
||||
bool gameHasBeenInitiated;
|
||||
int gameSettingsUpdateCount;
|
||||
|
||||
public:
|
||||
ServerInterface();
|
||||
|
@ -39,6 +50,7 @@ public:
|
|||
|
||||
virtual Socket* getSocket() {return &serverSocket;}
|
||||
virtual const Socket* getSocket() const {return &serverSocket;}
|
||||
virtual void close();
|
||||
|
||||
//message processing
|
||||
virtual void update();
|
||||
|
@ -48,7 +60,7 @@ public:
|
|||
|
||||
// message sending
|
||||
virtual void sendTextMessage(const string &text, int teamIndex);
|
||||
virtual void quitGame();
|
||||
virtual void quitGame(bool userManuallyQuit);
|
||||
|
||||
//misc
|
||||
virtual string getNetworkStatus() const;
|
||||
|
@ -59,11 +71,14 @@ public:
|
|||
ConnectionSlot* getSlot(int playerIndex);
|
||||
int getConnectedSlotCount();
|
||||
|
||||
void launchGame(const GameSettings* gameSettings);
|
||||
bool launchGame(const GameSettings* gameSettings);
|
||||
virtual void setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck = false);
|
||||
virtual bool getFogOfWar();
|
||||
|
||||
private:
|
||||
void broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot= -1);
|
||||
void updateListen();
|
||||
void broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot = -1);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
@ -160,10 +160,12 @@ bool Faction::applyCosts(const ProducibleType *p){
|
|||
|
||||
//for each unit cost spend it
|
||||
//pass 2, decrease resources, except negative static costs (ie: farms)
|
||||
for(int i=0; i<p->getCostCount(); ++i){
|
||||
for(int i=0; i<p->getCostCount(); ++i)
|
||||
{
|
||||
const ResourceType *rt= p->getCost(i)->getType();
|
||||
int cost= p->getCost(i)->getAmount();
|
||||
if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){
|
||||
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
|
||||
{
|
||||
incResourceAmount(rt, -(cost));
|
||||
}
|
||||
|
||||
|
@ -172,26 +174,32 @@ bool Faction::applyCosts(const ProducibleType *p){
|
|||
}
|
||||
|
||||
//apply discount (when a morph ends)
|
||||
void Faction::applyDiscount(const ProducibleType *p, int discount){
|
||||
void Faction::applyDiscount(const ProducibleType *p, int discount)
|
||||
{
|
||||
//increase resources
|
||||
for(int i=0; i<p->getCostCount(); ++i){
|
||||
for(int i=0; i<p->getCostCount(); ++i)
|
||||
{
|
||||
const ResourceType *rt= p->getCost(i)->getType();
|
||||
int cost= p->getCost(i)->getAmount();
|
||||
if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){
|
||||
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
|
||||
{
|
||||
incResourceAmount(rt, cost*discount/100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//apply static production (for starting units)
|
||||
void Faction::applyStaticCosts(const ProducibleType *p){
|
||||
|
||||
void Faction::applyStaticCosts(const ProducibleType *p)
|
||||
{
|
||||
//decrease static resources
|
||||
for(int i=0; i<p->getCostCount(); ++i){
|
||||
for(int i=0; i<p->getCostCount(); ++i)
|
||||
{
|
||||
const ResourceType *rt= p->getCost(i)->getType();
|
||||
if(rt->getClass()==rcStatic){
|
||||
if(rt->getClass() == rcStatic)
|
||||
{
|
||||
int cost= p->getCost(i)->getAmount();
|
||||
if(cost>0){
|
||||
if(cost > 0)
|
||||
{
|
||||
incResourceAmount(rt, -cost);
|
||||
}
|
||||
}
|
||||
|
@ -199,14 +207,17 @@ void Faction::applyStaticCosts(const ProducibleType *p){
|
|||
}
|
||||
|
||||
//apply static production (when a mana source is done)
|
||||
void Faction::applyStaticProduction(const ProducibleType *p){
|
||||
|
||||
void Faction::applyStaticProduction(const ProducibleType *p)
|
||||
{
|
||||
//decrease static resources
|
||||
for(int i=0; i<p->getCostCount(); ++i){
|
||||
for(int i=0; i<p->getCostCount(); ++i)
|
||||
{
|
||||
const ResourceType *rt= p->getCost(i)->getType();
|
||||
if(rt->getClass()==rcStatic){
|
||||
if(rt->getClass() == rcStatic)
|
||||
{
|
||||
int cost= p->getCost(i)->getAmount();
|
||||
if(cost<0){
|
||||
if(cost < 0)
|
||||
{
|
||||
incResourceAmount(rt, -cost);
|
||||
}
|
||||
}
|
||||
|
@ -214,13 +225,15 @@ void Faction::applyStaticProduction(const ProducibleType *p){
|
|||
}
|
||||
|
||||
//deapply all costs except static production (usually when a building is cancelled)
|
||||
void Faction::deApplyCosts(const ProducibleType *p){
|
||||
|
||||
void Faction::deApplyCosts(const ProducibleType *p)
|
||||
{
|
||||
//increase resources
|
||||
for(int i=0; i<p->getCostCount(); ++i){
|
||||
for(int i=0; i<p->getCostCount(); ++i)
|
||||
{
|
||||
const ResourceType *rt= p->getCost(i)->getType();
|
||||
int cost= p->getCost(i)->getAmount();
|
||||
if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){
|
||||
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
|
||||
{
|
||||
incResourceAmount(rt, cost);
|
||||
}
|
||||
|
||||
|
@ -228,27 +241,35 @@ void Faction::deApplyCosts(const ProducibleType *p){
|
|||
}
|
||||
|
||||
//deapply static costs (usually when a unit dies)
|
||||
void Faction::deApplyStaticCosts(const ProducibleType *p){
|
||||
|
||||
void Faction::deApplyStaticCosts(const ProducibleType *p)
|
||||
{
|
||||
//decrease resources
|
||||
for(int i=0; i<p->getCostCount(); ++i){
|
||||
for(int i=0; i<p->getCostCount(); ++i)
|
||||
{
|
||||
const ResourceType *rt= p->getCost(i)->getType();
|
||||
if(rt->getClass()==rcStatic){
|
||||
int cost= p->getCost(i)->getAmount();
|
||||
incResourceAmount(rt, cost);
|
||||
if(rt->getClass() == rcStatic)
|
||||
{
|
||||
if(rt->getRecoup_cost() == true)
|
||||
{
|
||||
int cost= p->getCost(i)->getAmount();
|
||||
incResourceAmount(rt, cost);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//deapply static costs, but not negative costs, for when building gets killed
|
||||
void Faction::deApplyStaticConsumption(const ProducibleType *p){
|
||||
|
||||
void Faction::deApplyStaticConsumption(const ProducibleType *p)
|
||||
{
|
||||
//decrease resources
|
||||
for(int i=0; i<p->getCostCount(); ++i){
|
||||
for(int i=0; i<p->getCostCount(); ++i)
|
||||
{
|
||||
const ResourceType *rt= p->getCost(i)->getType();
|
||||
if(rt->getClass()==rcStatic){
|
||||
if(rt->getClass() == rcStatic)
|
||||
{
|
||||
int cost= p->getCost(i)->getAmount();
|
||||
if(cost>0){
|
||||
if(cost>0)
|
||||
{
|
||||
incResourceAmount(rt, cost);
|
||||
}
|
||||
}
|
||||
|
@ -320,12 +341,16 @@ bool Faction::isAlly(const Faction *faction){
|
|||
|
||||
// ================== misc ==================
|
||||
|
||||
void Faction::incResourceAmount(const ResourceType *rt, int amount){
|
||||
for(int i=0; i<resources.size(); ++i){
|
||||
void Faction::incResourceAmount(const ResourceType *rt, int amount)
|
||||
{
|
||||
for(int i=0; i<resources.size(); ++i)
|
||||
{
|
||||
Resource *r= &resources[i];
|
||||
if(r->getType()==rt){
|
||||
if(r->getType()==rt)
|
||||
{
|
||||
r->setAmount(r->getAmount()+amount);
|
||||
if(r->getType()->getClass()!=rcStatic && r->getAmount()>getStoreAmount(rt)){
|
||||
if(r->getType()->getClass() != rcStatic && r->getAmount()>getStoreAmount(rt))
|
||||
{
|
||||
r->setAmount(getStoreAmount(rt));
|
||||
}
|
||||
return;
|
||||
|
@ -396,11 +421,14 @@ void Faction::removeStore(const UnitType *unitType){
|
|||
limitResourcesToStore();
|
||||
}
|
||||
|
||||
void Faction::limitResourcesToStore(){
|
||||
for(int i=0; i<resources.size(); ++i){
|
||||
void Faction::limitResourcesToStore()
|
||||
{
|
||||
for(int i=0; i<resources.size(); ++i)
|
||||
{
|
||||
Resource *r= &resources[i];
|
||||
Resource *s= &store[i];
|
||||
if(r->getType()->getClass()!=rcStatic && r->getAmount()>s->getAmount()){
|
||||
if(r->getType()->getClass() != rcStatic && r->getAmount()>s->getAmount())
|
||||
{
|
||||
r->setAmount(s->getAmount());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
@ -254,7 +254,7 @@ public:
|
|||
//command related
|
||||
bool anyCommand() const;
|
||||
Command *getCurrCommand() const;
|
||||
uint getCommandSize() const;
|
||||
unsigned int getCommandSize() const;
|
||||
CommandResult giveCommand(Command *command); //give a command
|
||||
CommandResult finishCommand(); //command finished
|
||||
CommandResult cancelCommand(); //cancel canceled
|
||||
|
|
|
@ -33,7 +33,10 @@ void ResourceType::load(const string &dir, Checksum* checksum){
|
|||
string path, str;
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
try{
|
||||
try
|
||||
{
|
||||
recoup_cost = true;
|
||||
|
||||
name= lastDir(dir);
|
||||
|
||||
Logger::getInstance().add("Resource type: "+ formatString(name), true);
|
||||
|
@ -55,44 +58,62 @@ void ResourceType::load(const string &dir, Checksum* checksum){
|
|||
const XmlNode *typeNode= resourceNode->getChild("type");
|
||||
resourceClass= strToRc(typeNode->getAttribute("value")->getRestrictedValue());
|
||||
|
||||
switch(resourceClass){
|
||||
case rcTech:{
|
||||
//model
|
||||
const XmlNode *modelNode= typeNode->getChild("model");
|
||||
string path=dir+"/" + modelNode->getAttribute("path")->getRestrictedValue();
|
||||
switch(resourceClass)
|
||||
{
|
||||
case rcTech:
|
||||
{
|
||||
//model
|
||||
const XmlNode *modelNode= typeNode->getChild("model");
|
||||
string path=dir+"/" + modelNode->getAttribute("path")->getRestrictedValue();
|
||||
|
||||
model= renderer.newModel(rsGame);
|
||||
model->load(path);
|
||||
model= renderer.newModel(rsGame);
|
||||
model->load(path);
|
||||
|
||||
//default resources
|
||||
const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
|
||||
defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
|
||||
//default resources
|
||||
const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
|
||||
defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
|
||||
|
||||
//resource number
|
||||
const XmlNode *resourceNumberNode= typeNode->getChild("resource-number");
|
||||
resourceNumber= resourceNumberNode->getAttribute("value")->getIntValue();
|
||||
//resource number
|
||||
const XmlNode *resourceNumberNode= typeNode->getChild("resource-number");
|
||||
resourceNumber= resourceNumberNode->getAttribute("value")->getIntValue();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case rcTileset:{
|
||||
//resource number
|
||||
const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
|
||||
defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
|
||||
|
||||
//resource number
|
||||
const XmlNode *tilesetObjectNode= typeNode->getChild("tileset-object");
|
||||
tilesetObject= tilesetObjectNode->getAttribute("value")->getIntValue();
|
||||
case rcTileset:
|
||||
{
|
||||
//resource number
|
||||
const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
|
||||
defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
|
||||
|
||||
//resource number
|
||||
const XmlNode *tilesetObjectNode= typeNode->getChild("tileset-object");
|
||||
tilesetObject= tilesetObjectNode->getAttribute("value")->getIntValue();
|
||||
}
|
||||
break;
|
||||
|
||||
case rcConsumable:{
|
||||
//interval
|
||||
const XmlNode *intervalNode= typeNode->getChild("interval");
|
||||
interval= intervalNode->getAttribute("value")->getIntValue();
|
||||
case rcConsumable:
|
||||
{
|
||||
//interval
|
||||
const XmlNode *intervalNode= typeNode->getChild("interval");
|
||||
interval= intervalNode->getAttribute("value")->getIntValue();
|
||||
}
|
||||
break;
|
||||
|
||||
case rcStatic:
|
||||
{
|
||||
//recoup_cost
|
||||
if(typeNode->hasChild("recoup_cost") == true)
|
||||
{
|
||||
const XmlNode *recoup_costNode= typeNode->getChild("recoup_cost");
|
||||
if(recoup_costNode != NULL)
|
||||
{
|
||||
recoup_cost= recoup_costNode->getAttribute("value")->getBoolValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ private:
|
|||
int resourceNumber; //used only if class==rcTech, resource number in the map
|
||||
int interval; //used only if class==rcConsumable
|
||||
int defResPerPatch; //used only if class==rcTileset || class==rcTech
|
||||
bool recoup_cost;
|
||||
|
||||
Model *model;
|
||||
|
||||
public:
|
||||
|
@ -53,6 +55,7 @@ public:
|
|||
int getInterval() const {return interval;}
|
||||
int getDefResPerPatch() const {return defResPerPatch;}
|
||||
const Model *getModel() const {return model;}
|
||||
bool getRecoup_cost() const { return recoup_cost;}
|
||||
|
||||
static ResourceClass strToRc(const string &s);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#include <map>
|
||||
|
||||
using std::string;
|
||||
|
||||
|
@ -57,6 +58,16 @@ public:
|
|||
Socket();
|
||||
~Socket();
|
||||
|
||||
static bool enableDebugText;
|
||||
|
||||
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
|
||||
static bool hasDataToRead(std::map<int,bool> &socketTriggeredList);
|
||||
static bool hasDataToRead(int socket);
|
||||
bool hasDataToRead();
|
||||
void disconnectSocket();
|
||||
|
||||
int getSocketId() const { return sock; }
|
||||
|
||||
int getDataToRead();
|
||||
int send(const void *data, int dataSize);
|
||||
int receive(void *data, int dataSize);
|
||||
|
@ -64,7 +75,7 @@ public:
|
|||
|
||||
void setBlock(bool block);
|
||||
bool isReadable();
|
||||
bool isWritable();
|
||||
bool isWritable(bool waitOnDelayedResponse);
|
||||
bool isConnected();
|
||||
|
||||
string getHostName() const;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <SDL.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "checksum.h"
|
||||
#include <utility>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
@ -25,6 +27,8 @@ using std::exception;
|
|||
|
||||
using Shared::Platform::int64;
|
||||
|
||||
using Shared::Util::Checksum;
|
||||
|
||||
namespace Shared{ namespace Platform{
|
||||
|
||||
// =====================================================
|
||||
|
@ -85,6 +89,10 @@ public:
|
|||
// =====================================================
|
||||
|
||||
void findAll(const string &path, vector<string> &results, bool cutExtension=false);
|
||||
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum);
|
||||
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap);
|
||||
void createDirectoryPaths(string Path);
|
||||
string extractDirectoryPathFromFile(string filename);
|
||||
|
||||
bool changeVideoMode(int resH, int resW, int colorBits, int refreshFrequency);
|
||||
void restoreVideoMode();
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
#include <windows.h>
|
||||
|
||||
#include <gl.h>
|
||||
#include <glu.h>
|
||||
#include <GL\gl.h>
|
||||
#include <GL\glu.h>
|
||||
#include <glprocs.h>
|
||||
|
||||
#include <string>
|
||||
|
|
|
@ -19,12 +19,15 @@
|
|||
#include <stdexcept>
|
||||
|
||||
#include "types.h"
|
||||
#include "checksum.h"
|
||||
#include <utility>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::exception;
|
||||
|
||||
using Shared::Platform::int64;
|
||||
using Shared::Util::Checksum;
|
||||
|
||||
namespace Shared{ namespace Platform{
|
||||
|
||||
|
@ -96,6 +99,10 @@ public:
|
|||
// =====================================================
|
||||
|
||||
void findAll(const string &path, vector<string> &results, bool cutExtension=false);
|
||||
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum);
|
||||
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap);
|
||||
void createDirectoryPaths(string Path);
|
||||
string extractDirectoryPathFromFile(string filename);
|
||||
|
||||
bool changeVideoMode(int resH, int resW, int colorBits, int refreshFrequency);
|
||||
void restoreVideoMode();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <winsock.h>
|
||||
#include <map>
|
||||
|
||||
using std::string;
|
||||
|
||||
|
@ -57,6 +58,16 @@ public:
|
|||
Socket();
|
||||
~Socket();
|
||||
|
||||
static bool enableDebugText;
|
||||
|
||||
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
|
||||
static bool hasDataToRead(std::map<int,bool> &socketTriggeredList);
|
||||
static bool hasDataToRead(int socket);
|
||||
bool hasDataToRead();
|
||||
void disconnectSocket();
|
||||
|
||||
int getSocketId() const { return sock; }
|
||||
|
||||
int getDataToRead();
|
||||
int send(const void *data, int dataSize);
|
||||
int receive(void *data, int dataSize);
|
||||
|
@ -64,7 +75,7 @@ public:
|
|||
|
||||
void setBlock(bool block);
|
||||
bool isReadable();
|
||||
bool isWritable();
|
||||
bool isWritable(bool waitOnDelayedResponse);
|
||||
bool isConnected();
|
||||
|
||||
string getHostName() const;
|
||||
|
|
|
@ -109,6 +109,7 @@ public:
|
|||
XmlAttribute *getAttribute(const string &name) const;
|
||||
XmlNode *getChild(int i) const;
|
||||
XmlNode *getChild(const string &childName, int childIndex=0) const;
|
||||
bool hasChild(const string &childName) const;
|
||||
XmlNode *getParent() const;
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ using namespace Shared::Util;
|
|||
|
||||
namespace Shared{ namespace Platform{
|
||||
|
||||
bool Socket::enableDebugText = true;
|
||||
|
||||
// =====================================================
|
||||
// class Ip
|
||||
// =====================================================
|
||||
|
@ -71,51 +73,307 @@ Socket::Socket(int sock){
|
|||
this->sock= sock;
|
||||
}
|
||||
|
||||
Socket::Socket(){
|
||||
Socket::Socket()
|
||||
{
|
||||
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if(sock<0) {
|
||||
if(sock < 0)
|
||||
{
|
||||
throwException("Error creating socket");
|
||||
}
|
||||
}
|
||||
|
||||
Socket::~Socket() {
|
||||
::close(sock);
|
||||
Socket::~Socket()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
|
||||
disconnectSocket();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
}
|
||||
|
||||
void Socket::disconnectSocket()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
|
||||
if(sock > 0)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] calling shutdown and close for socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
::shutdown(sock,2);
|
||||
::close(sock);
|
||||
sock = -1;
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
}
|
||||
|
||||
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
|
||||
bool Socket::hasDataToRead(std::map<int,bool> &socketTriggeredList)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
if(socketTriggeredList.size() > 0)
|
||||
{
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
|
||||
int imaxsocket = 0;
|
||||
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
|
||||
itermap != socketTriggeredList.end(); itermap++)
|
||||
{
|
||||
int socket = itermap->first;
|
||||
if(socket > 0)
|
||||
{
|
||||
FD_SET(socket, &rfds);
|
||||
imaxsocket = max(socket,imaxsocket);
|
||||
}
|
||||
}
|
||||
|
||||
if(imaxsocket > 0)
|
||||
{
|
||||
/* Wait up to 0 seconds. */
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
|
||||
if(retval < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d errno = %d [%s]",__FILE__,__FUNCTION__,retval,errno,strerror(errno));
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
|
||||
}
|
||||
else if(retval)
|
||||
{
|
||||
bResult = true;
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket);
|
||||
|
||||
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
|
||||
itermap != socketTriggeredList.end(); itermap++)
|
||||
{
|
||||
int socket = itermap->first;
|
||||
if (FD_ISSET(socket, &rfds))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket);
|
||||
|
||||
itermap->second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
itermap->second = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool Socket::hasDataToRead()
|
||||
{
|
||||
return Socket::hasDataToRead(sock) ;
|
||||
}
|
||||
|
||||
bool Socket::hasDataToRead(int socket)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
if(socket > 0)
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(socket, &rfds);
|
||||
|
||||
/* Wait up to 0 seconds. */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int retval = select(socket + 1, &rfds, NULL, NULL, &tv);
|
||||
if(retval)
|
||||
{
|
||||
if (FD_ISSET(socket, &rfds))
|
||||
{
|
||||
bResult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
int Socket::getDataToRead(){
|
||||
unsigned long size;
|
||||
unsigned long size = 0;
|
||||
|
||||
/* ioctl isn't posix, but the following seems to work on all modern
|
||||
* unixes */
|
||||
int err= ioctl(sock, FIONREAD, &size);
|
||||
//fd_set rfds;
|
||||
//struct timeval tv;
|
||||
//int retval;
|
||||
|
||||
if(err < 0 && errno != EAGAIN){
|
||||
throwException("Can not get data to read");
|
||||
}
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
//FD_ZERO(&rfds);
|
||||
//FD_SET(sock, &rfds);
|
||||
|
||||
/* Wait up to 0 seconds. */
|
||||
//tv.tv_sec = 0;
|
||||
//tv.tv_usec = 0;
|
||||
|
||||
//retval = select(sock + 1, &rfds, NULL, NULL, &tv);
|
||||
//if(retval)
|
||||
if(sock > 0)
|
||||
{
|
||||
/* ioctl isn't posix, but the following seems to work on all modern
|
||||
* unixes */
|
||||
int err= ioctl(sock, FIONREAD, &size);
|
||||
|
||||
if(err < 0 && errno != EAGAIN)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d errno = %d [%s]",__FILE__,__FUNCTION__,err,errno,strerror(errno));
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(err == 0)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int>(size);
|
||||
}
|
||||
|
||||
int Socket::send(const void *data, int dataSize) {
|
||||
ssize_t bytesSent= ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
if(bytesSent<0 && errno != EAGAIN) {
|
||||
throwException("error while receiving socket data");
|
||||
ssize_t bytesSent= 0;
|
||||
if(sock > 0)
|
||||
{
|
||||
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
}
|
||||
if(bytesSent < 0 && errno != EAGAIN)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d errno = %d [%s]",__FILE__,__FUNCTION__,bytesSent,errno,strerror(errno));
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(bytesSent < 0 && errno == EAGAIN)
|
||||
{
|
||||
printf("In [%s::%s] #1 EAGAIN during send, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((bytesSent < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isWritable(true) == true)
|
||||
{
|
||||
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
|
||||
printf("In [%s::%s] #2 EAGAIN during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bytesSent <= 0)
|
||||
{
|
||||
int iErr = errno;
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesSent,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent);
|
||||
|
||||
return static_cast<int>(bytesSent);
|
||||
}
|
||||
|
||||
int Socket::receive(void *data, int dataSize) {
|
||||
ssize_t bytesReceived= recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
if(bytesReceived<0 && errno != EAGAIN) {
|
||||
throwException("error while receiving socket data");
|
||||
int Socket::receive(void *data, int dataSize)
|
||||
{
|
||||
ssize_t bytesReceived = 0;
|
||||
|
||||
if(sock > 0)
|
||||
{
|
||||
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
}
|
||||
if(bytesReceived < 0 && errno != EAGAIN)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,errno,strerror(errno));
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(bytesReceived < 0 && errno == EAGAIN)
|
||||
{
|
||||
printf("In [%s::%s] #1 EAGAIN during receive, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((bytesReceived < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isReadable() == true)
|
||||
{
|
||||
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
|
||||
printf("In [%s::%s] #2 EAGAIN during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bytesReceived <= 0)
|
||||
{
|
||||
int iErr = errno;
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
return static_cast<int>(bytesReceived);
|
||||
}
|
||||
|
||||
int Socket::peek(void *data, int dataSize){
|
||||
ssize_t err= recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
if(err<0 && errno != EAGAIN){
|
||||
throwException("Can not receive data");
|
||||
ssize_t err = 0;
|
||||
if(sock > 0)
|
||||
{
|
||||
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
}
|
||||
if(err < 0 && errno != EAGAIN)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,errno,strerror(errno));
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(err < 0 && errno == EAGAIN)
|
||||
{
|
||||
printf("In [%s::%s] #1 EAGAIN during peek, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((err < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isReadable() == true)
|
||||
{
|
||||
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
|
||||
printf("In [%s::%s] #2 EAGAIN during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(err <= 0)
|
||||
{
|
||||
int iErr = errno;
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
return static_cast<int>(err);
|
||||
|
@ -128,49 +386,114 @@ void Socket::setBlock(bool block){
|
|||
}
|
||||
}
|
||||
|
||||
bool Socket::isReadable(){
|
||||
bool Socket::isReadable()
|
||||
{
|
||||
if(sock <= 0) return false;
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec= 0;
|
||||
tv.tv_usec= 10;
|
||||
tv.tv_usec= 1;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int i= select(sock+1, &set, NULL, NULL, &tv);
|
||||
if(i<0){
|
||||
throwException("Error selecting socket");
|
||||
if(i < 0)
|
||||
{
|
||||
//throwException("Error selecting socket");
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
|
||||
printf("%s",szBuf);
|
||||
}
|
||||
return i==1;
|
||||
//return (i == 1 && FD_ISSET(sock, &set));
|
||||
return (i == 1);
|
||||
}
|
||||
|
||||
bool Socket::isWritable(){
|
||||
bool Socket::isWritable(bool waitOnDelayedResponse)
|
||||
{
|
||||
if(sock <= 0) return false;
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec= 0;
|
||||
tv.tv_usec= 10;
|
||||
tv.tv_usec= 1;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int i= select(sock+1, NULL, &set, NULL, &tv);
|
||||
if(i<0){
|
||||
throwException("Error selecting socket");
|
||||
}
|
||||
return i==1;
|
||||
bool result = false;
|
||||
do
|
||||
{
|
||||
int i = select(sock+1, NULL, &set, NULL, &tv);
|
||||
if(i < 0 )
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
|
||||
printf("%s",szBuf);
|
||||
waitOnDelayedResponse = false;
|
||||
|
||||
//throwException("Error selecting socket");
|
||||
}
|
||||
else if(i == 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
|
||||
printf("%s",szBuf);
|
||||
|
||||
if(waitOnDelayedResponse == false)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
} while(waitOnDelayedResponse == true && result == false);
|
||||
|
||||
//return (i == 1 && FD_ISSET(sock, &set));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Socket::isConnected(){
|
||||
|
||||
bool Socket::isConnected()
|
||||
{
|
||||
//if the socket is not writable then it is not conencted
|
||||
if(!isWritable()){
|
||||
if(isWritable(false) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//if the socket is readable it is connected if we can read a byte from it
|
||||
if(isReadable()){
|
||||
if(isReadable())
|
||||
{
|
||||
char tmp;
|
||||
return recv(sock, &tmp, sizeof(tmp), MSG_PEEK) > 0;
|
||||
int err = peek(&tmp, sizeof(tmp));
|
||||
return (err > 0);
|
||||
/*
|
||||
int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK);
|
||||
|
||||
if(err <= 0 && errno != EAGAIN)
|
||||
{
|
||||
int iErr = errno;
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(err <= 0)
|
||||
{
|
||||
int iErr = errno;
|
||||
//disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] #2 DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//otherwise the socket is connected
|
||||
|
@ -215,7 +538,8 @@ void Socket::throwException(const string &str){
|
|||
// class ClientSocket
|
||||
// ===============================================
|
||||
|
||||
void ClientSocket::connect(const Ip &ip, int port){
|
||||
void ClientSocket::connect(const Ip &ip, int port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
|
@ -224,20 +548,23 @@ void ClientSocket::connect(const Ip &ip, int port){
|
|||
addr.sin_port= htons(port);
|
||||
|
||||
int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
|
||||
if(err < 0) {
|
||||
if(err < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]",ip.getString().c_str(),port,err,errno,strerror(errno));
|
||||
sprintf(szBuf,"In [%s::%s] #2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]\n",__FILE__,__FUNCTION__,ip.getString().c_str(),port,err,errno,strerror(errno));
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
|
||||
if (errno == EINPROGRESS) {
|
||||
|
||||
if (errno == EINPROGRESS)
|
||||
{
|
||||
fd_set myset;
|
||||
struct timeval tv;
|
||||
int valopt;
|
||||
socklen_t lon;
|
||||
|
||||
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
|
||||
do {
|
||||
fprintf(stderr, "In [%s::%s] EINPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__);
|
||||
|
||||
do
|
||||
{
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
|
@ -246,41 +573,57 @@ void ClientSocket::connect(const Ip &ip, int port){
|
|||
|
||||
err = select(sock+1, NULL, &myset, NULL, &tv);
|
||||
|
||||
if (err < 0 && errno != EINTR) {
|
||||
sprintf(szBuf, "Error connecting %d - %s\n", errno, strerror(errno));
|
||||
throwException(szBuf);
|
||||
if (err < 0 && errno != EINTR)
|
||||
{
|
||||
sprintf(szBuf, "In [%s::%s] Error connecting %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno));
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
else if (err > 0) {
|
||||
else if (err > 0)
|
||||
{
|
||||
// Socket selected for write
|
||||
lon = sizeof(int);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
|
||||
sprintf(szBuf, "Error in getsockopt() %d - %s\n", errno, strerror(errno));
|
||||
throwException(szBuf);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0)
|
||||
{
|
||||
sprintf(szBuf, "In [%s::%s] Error in getsockopt() %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno));
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
// Check the value returned...
|
||||
if (valopt) {
|
||||
sprintf(szBuf, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt));
|
||||
throwException(szBuf);
|
||||
if (valopt)
|
||||
{
|
||||
sprintf(szBuf, "In [%s::%s] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,valopt, strerror(valopt));
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, errno = %d\n",sock,err,errno);
|
||||
fprintf(stderr, "In [%s::%s] Apparent recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
|
||||
|
||||
break;
|
||||
}
|
||||
else {
|
||||
sprintf(szBuf, "Timeout in select() - Cancelling!\n");
|
||||
throwException(szBuf);
|
||||
else
|
||||
{
|
||||
sprintf(szBuf, "In [%s::%s] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__);
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
if(err < 0)
|
||||
{
|
||||
throwException(szBuf);
|
||||
fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,sock,err,errno,strerror(errno));
|
||||
//throwException(szBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "In [%s::%s] Valid recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, errno = %d\n",sock,err,errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,7 +631,8 @@ void ClientSocket::connect(const Ip &ip, int port){
|
|||
// class ServerSocket
|
||||
// ===============================================
|
||||
|
||||
void ServerSocket::bind(int port){
|
||||
void ServerSocket::bind(int port)
|
||||
{
|
||||
//sockaddr structure
|
||||
sockaddr_in addr;
|
||||
addr.sin_family= AF_INET;
|
||||
|
@ -299,28 +643,43 @@ void ServerSocket::bind(int port){
|
|||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
|
||||
|
||||
int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
|
||||
if(err < 0) {
|
||||
throwException("Error binding socket");
|
||||
if(err < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf, "In [%s::%s] Error binding socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
|
||||
throwException(szBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerSocket::listen(int connectionQueueSize){
|
||||
void ServerSocket::listen(int connectionQueueSize)
|
||||
{
|
||||
int err= ::listen(sock, connectionQueueSize);
|
||||
if(err < 0) {
|
||||
throwException("Error listening socket");
|
||||
if(err < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf, "In [%s::%s] Error listening socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
|
||||
throwException(szBuf);
|
||||
}
|
||||
}
|
||||
|
||||
Socket *ServerSocket::accept(){
|
||||
Socket *ServerSocket::accept()
|
||||
{
|
||||
int newSock= ::accept(sock, NULL, NULL);
|
||||
if(newSock < 0) {
|
||||
if(errno == EAGAIN)
|
||||
return NULL;
|
||||
if(newSock < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
if(Socket::enableDebugText) printf(szBuf, "In [%s::%s] Error accepting socket connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,newSock,errno);
|
||||
|
||||
if(errno == EAGAIN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
throwException(szBuf);
|
||||
|
||||
throwException("Error accepting socket connection");
|
||||
}
|
||||
return new Socket(newSock);
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#include "window.h"
|
||||
#include "noimpl.h"
|
||||
|
||||
#include "checksum.h"
|
||||
#include "socket.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
|
@ -160,6 +164,217 @@ void findAll(const string &path, vector<string> &results, bool cutExtension) {
|
|||
}
|
||||
}
|
||||
|
||||
int isdir(const char *path)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
|
||||
}
|
||||
|
||||
bool EndsWith(const string &str, const string& key)
|
||||
{
|
||||
size_t keylen = key.length();
|
||||
size_t strlen = str.length();
|
||||
|
||||
if(keylen <= strlen)
|
||||
return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//finds all filenames like path and gets their checksum of all files combined
|
||||
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) {
|
||||
|
||||
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
|
||||
|
||||
std::string mypath = path;
|
||||
/** Stupid win32 is searching for all files without extension when *. is
|
||||
* specified as wildcard
|
||||
*/
|
||||
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
|
||||
mypath = mypath.substr(0, mypath.size() - 2);
|
||||
mypath += "*";
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
/*
|
||||
const char* begin = p;
|
||||
for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
if(*p == '/')
|
||||
begin = p+1;
|
||||
}
|
||||
*/
|
||||
|
||||
if(isdir(p) == 0)
|
||||
{
|
||||
bool addFile = true;
|
||||
if(filterFileExt != "")
|
||||
{
|
||||
addFile = EndsWith(p, filterFileExt);
|
||||
}
|
||||
|
||||
if(addFile)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
|
||||
|
||||
checksum.addFile(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
// Look recursively for sub-folders
|
||||
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
/*
|
||||
const char* begin = p;
|
||||
for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
if(*p == '/')
|
||||
begin = p+1;
|
||||
}
|
||||
*/
|
||||
|
||||
getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
return checksum.getSum();
|
||||
}
|
||||
|
||||
//finds all filenames like path and gets the checksum of each file
|
||||
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap) {
|
||||
|
||||
vector<std::pair<string,int32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,int32> >() : *recursiveMap);
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
|
||||
|
||||
std::string mypath = path;
|
||||
/** Stupid win32 is searching for all files without extension when *. is
|
||||
* specified as wildcard
|
||||
*/
|
||||
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
|
||||
mypath = mypath.substr(0, mypath.size() - 2);
|
||||
mypath += "*";
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
/*
|
||||
const char* begin = p;
|
||||
for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
if(*p == '/')
|
||||
begin = p+1;
|
||||
}
|
||||
*/
|
||||
|
||||
if(isdir(p) == 0)
|
||||
{
|
||||
bool addFile = true;
|
||||
if(filterFileExt != "")
|
||||
{
|
||||
addFile = EndsWith(p, filterFileExt);
|
||||
}
|
||||
|
||||
if(addFile)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
|
||||
|
||||
Checksum checksum;
|
||||
checksum.addFile(p);
|
||||
|
||||
checksumFiles.push_back(std::pair<string,int32>(p,checksum.getSum()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
// Look recursively for sub-folders
|
||||
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
/*
|
||||
const char* begin = p;
|
||||
for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
if(*p == '/')
|
||||
begin = p+1;
|
||||
}
|
||||
*/
|
||||
|
||||
checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
return checksumFiles;
|
||||
}
|
||||
|
||||
string extractDirectoryPathFromFile(string filename)
|
||||
{
|
||||
return filename.substr( 0, filename.rfind("/")+1 );
|
||||
}
|
||||
|
||||
void createDirectoryPaths(string Path)
|
||||
{
|
||||
char DirName[256]="";
|
||||
const char *path = Path.c_str();
|
||||
char *dirName = DirName;
|
||||
while(*path)
|
||||
{
|
||||
//if (('\\' == *path) || ('/' == *path))
|
||||
if ('/' == *path)
|
||||
{
|
||||
//if (':' != *(path-1))
|
||||
{
|
||||
mkdir(DirName, S_IRWXO);
|
||||
}
|
||||
}
|
||||
*dirName++ = *path++;
|
||||
*dirName = '\0';
|
||||
}
|
||||
mkdir(DirName, S_IRWXO);
|
||||
}
|
||||
|
||||
bool changeVideoMode(int resW, int resH, int colorBits, int ) {
|
||||
Private::shouldBeFullscreen = true;
|
||||
return true;
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
#include "conversion.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <direct.h>
|
||||
|
||||
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
|
||||
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
@ -195,6 +201,215 @@ void findAll(const string &path, vector<string> &results, bool cutExtension){
|
|||
delete [] cstr;
|
||||
}
|
||||
|
||||
int isdir(const char *path)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
|
||||
}
|
||||
|
||||
bool EndsWith(const string &str, const string& key)
|
||||
{
|
||||
size_t keylen = key.length();
|
||||
size_t strlen = str.length();
|
||||
|
||||
if(keylen <= strlen)
|
||||
return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//finds all filenames like path and gets their checksum of all files combined
|
||||
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) {
|
||||
|
||||
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
|
||||
|
||||
/* MV - PORT THIS to win32
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
|
||||
|
||||
std::string mypath = path;
|
||||
// Stupid win32 is searching for all files without extension when *. is specified as wildcard
|
||||
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
|
||||
mypath = mypath.substr(0, mypath.size() - 2);
|
||||
mypath += "*";
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
//
|
||||
//const char* begin = p;
|
||||
//for( ; *p != 0; ++p) {
|
||||
// // strip the path component
|
||||
// if(*p == '/')
|
||||
// begin = p+1;
|
||||
//}
|
||||
|
||||
|
||||
if(isdir(p) == 0)
|
||||
{
|
||||
bool addFile = true;
|
||||
if(filterFileExt != "")
|
||||
{
|
||||
addFile = EndsWith(p, filterFileExt);
|
||||
}
|
||||
|
||||
if(addFile)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
|
||||
|
||||
checksum.addFile(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
// Look recursively for sub-folders
|
||||
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
//
|
||||
//const char* begin = p;
|
||||
//for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
// if(*p == '/')
|
||||
// begin = p+1;
|
||||
//}
|
||||
|
||||
getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
*/
|
||||
return checksum.getSum();
|
||||
}
|
||||
|
||||
//finds all filenames like path and gets the checksum of each file
|
||||
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap) {
|
||||
|
||||
vector<std::pair<string,int32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,int32> >() : *recursiveMap);
|
||||
|
||||
/* MV - PORT THIS to win32
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
|
||||
|
||||
std::string mypath = path;
|
||||
// Stupid win32 is searching for all files without extension when *. is specified as wildcard
|
||||
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
|
||||
mypath = mypath.substr(0, mypath.size() - 2);
|
||||
mypath += "*";
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
//
|
||||
//const char* begin = p;
|
||||
//for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
// if(*p == '/')
|
||||
// begin = p+1;
|
||||
//}
|
||||
|
||||
|
||||
if(isdir(p) == 0)
|
||||
{
|
||||
bool addFile = true;
|
||||
if(filterFileExt != "")
|
||||
{
|
||||
addFile = EndsWith(p, filterFileExt);
|
||||
}
|
||||
|
||||
if(addFile)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
|
||||
|
||||
Checksum checksum;
|
||||
checksum.addFile(p);
|
||||
|
||||
checksumFiles.push_back(std::pair<string,int32>(p,checksum.getSum()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
// Look recursively for sub-folders
|
||||
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
//
|
||||
//const char* begin = p;
|
||||
//for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
// if(*p == '/')
|
||||
// begin = p+1;
|
||||
//}
|
||||
|
||||
checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
*/
|
||||
return checksumFiles;
|
||||
}
|
||||
|
||||
string extractDirectoryPathFromFile(string filename)
|
||||
{
|
||||
return filename.substr( 0, filename.rfind("/")+1 );
|
||||
}
|
||||
|
||||
void createDirectoryPaths(string Path)
|
||||
{
|
||||
char DirName[256]="";
|
||||
const char *path = Path.c_str();
|
||||
char *dirName = DirName;
|
||||
while(*path)
|
||||
{
|
||||
//if (('\\' == *path) || ('/' == *path))
|
||||
if ('/' == *path)
|
||||
{
|
||||
//if (':' != *(path-1))
|
||||
{
|
||||
_mkdir(DirName);
|
||||
}
|
||||
}
|
||||
*dirName++ = *path++;
|
||||
*dirName = '\0';
|
||||
}
|
||||
_mkdir(DirName);
|
||||
}
|
||||
|
||||
bool changeVideoMode(int resW, int resH, int colorBits, int refreshFrequency){
|
||||
DEVMODE devMode;
|
||||
|
||||
|
|
|
@ -16,12 +16,17 @@
|
|||
#include "conversion.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
#include <time.h>
|
||||
|
||||
#define socklen_t int
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Shared{ namespace Platform{
|
||||
|
||||
bool Socket::enableDebugText = false;
|
||||
|
||||
// =====================================================
|
||||
// class Ip
|
||||
// =====================================================
|
||||
|
@ -85,59 +90,300 @@ Socket::Socket(){
|
|||
}
|
||||
}
|
||||
|
||||
Socket::~Socket(){
|
||||
int err= closesocket(sock);
|
||||
if(err==INVALID_SOCKET){
|
||||
throwException("Error closing socket");
|
||||
}
|
||||
Socket::~Socket()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
|
||||
disconnectSocket();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
}
|
||||
|
||||
void Socket::disconnectSocket()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
|
||||
if(sock > 0)
|
||||
{
|
||||
::shutdown(sock,2);
|
||||
::closesocket(sock);
|
||||
sock = -1;
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
}
|
||||
|
||||
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
|
||||
bool Socket::hasDataToRead(std::map<int,bool> &socketTriggeredList)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
if(socketTriggeredList.size() > 0)
|
||||
{
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
|
||||
int imaxsocket = 0;
|
||||
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
|
||||
itermap != socketTriggeredList.end(); itermap++)
|
||||
{
|
||||
int socket = itermap->first;
|
||||
if(socket > 0)
|
||||
{
|
||||
FD_SET(socket, &rfds);
|
||||
imaxsocket = max(socket,imaxsocket);
|
||||
}
|
||||
}
|
||||
|
||||
if(imaxsocket > 0)
|
||||
{
|
||||
/* Wait up to 0 seconds. */
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
|
||||
if(retval < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,retval,WSAGetLastError());
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
|
||||
}
|
||||
else if(retval)
|
||||
{
|
||||
bResult = true;
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket);
|
||||
|
||||
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
|
||||
itermap != socketTriggeredList.end(); itermap++)
|
||||
{
|
||||
int socket = itermap->first;
|
||||
if (FD_ISSET(socket, &rfds))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket);
|
||||
|
||||
itermap->second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
itermap->second = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool Socket::hasDataToRead()
|
||||
{
|
||||
return Socket::hasDataToRead(sock) ;
|
||||
}
|
||||
|
||||
bool Socket::hasDataToRead(int socket)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
if(socket > 0)
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(socket, &rfds);
|
||||
|
||||
/* Wait up to 0 seconds. */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int retval = select(socket + 1, &rfds, NULL, NULL, &tv);
|
||||
if(retval)
|
||||
{
|
||||
if (FD_ISSET(socket, &rfds))
|
||||
{
|
||||
bResult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
int Socket::getDataToRead(){
|
||||
u_long size;
|
||||
unsigned long size = 0;
|
||||
|
||||
int err= ioctlsocket(sock, FIONREAD, &size);
|
||||
//fd_set rfds;
|
||||
//struct timeval tv;
|
||||
//int retval;
|
||||
|
||||
if(err==SOCKET_ERROR){
|
||||
if(WSAGetLastError()!=WSAEWOULDBLOCK){
|
||||
throwException("Can not get data to read");
|
||||
}
|
||||
}
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
//FD_ZERO(&rfds);
|
||||
//FD_SET(sock, &rfds);
|
||||
|
||||
/* Wait up to 0 seconds. */
|
||||
//tv.tv_sec = 0;
|
||||
//tv.tv_usec = 0;
|
||||
|
||||
//retval = select(sock + 1, &rfds, NULL, NULL, &tv);
|
||||
//if(retval)
|
||||
if(sock > 0)
|
||||
{
|
||||
/* ioctl isn't posix, but the following seems to work on all modern
|
||||
* unixes */
|
||||
int err= ioctlsocket(sock, FIONREAD, &size);
|
||||
|
||||
if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,err,WSAGetLastError());
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(err == 0)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int>(size);
|
||||
}
|
||||
|
||||
int Socket::send(const void *data, int dataSize){
|
||||
int err= ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
if(err==SOCKET_ERROR){
|
||||
if(WSAGetLastError()!=WSAEWOULDBLOCK){
|
||||
throwException("Can not send data");
|
||||
}
|
||||
int Socket::send(const void *data, int dataSize) {
|
||||
int bytesSent= 0;
|
||||
if(sock > 0)
|
||||
{
|
||||
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
}
|
||||
return err;
|
||||
if(bytesSent < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,bytesSent,WSAGetLastError());
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
{
|
||||
printf("In [%s::%s] #1 WSAEWOULDBLOCK during send, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isWritable(true) == true)
|
||||
{
|
||||
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
|
||||
printf("In [%s::%s] #2 WSAEWOULDBLOCK during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bytesSent <= 0)
|
||||
{
|
||||
int iErr = WSAGetLastError();
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesSent,iErr);
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent);
|
||||
|
||||
return static_cast<int>(bytesSent);
|
||||
}
|
||||
|
||||
int Socket::receive(void *data, int dataSize){
|
||||
int err= recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
int Socket::receive(void *data, int dataSize)
|
||||
{
|
||||
int bytesReceived = 0;
|
||||
|
||||
if(err==SOCKET_ERROR){
|
||||
if(WSAGetLastError()!=WSAEWOULDBLOCK){
|
||||
throwException("Can not receive data");
|
||||
}
|
||||
if(sock > 0)
|
||||
{
|
||||
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
}
|
||||
if(bytesReceived < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,WSAGetLastError());
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
{
|
||||
printf("In [%s::%s] #1 WSAEWOULDBLOCK during receive, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isReadable() == true)
|
||||
{
|
||||
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
|
||||
printf("In [%s::%s] #2 WSAEWOULDBLOCK during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
if(bytesReceived <= 0)
|
||||
{
|
||||
int iErr = WSAGetLastError();
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,iErr);
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
return static_cast<int>(bytesReceived);
|
||||
}
|
||||
|
||||
int Socket::peek(void *data, int dataSize){
|
||||
int err= recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
int err = 0;
|
||||
if(sock > 0)
|
||||
{
|
||||
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
}
|
||||
if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,WSAGetLastError());
|
||||
|
||||
if(err==SOCKET_ERROR){
|
||||
if(WSAGetLastError()!=WSAEWOULDBLOCK){
|
||||
throwException("Can not receive data");
|
||||
}
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(err < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
{
|
||||
printf("In [%s::%s] #1 WSAEWOULDBLOCK during peek, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((err < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isReadable() == true)
|
||||
{
|
||||
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
|
||||
printf("In [%s::%s] #2 WSAEWOULDBLOCK during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
if(err <= 0)
|
||||
{
|
||||
int iErr = WSAGetLastError();
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr);
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
return static_cast<int>(err);
|
||||
}
|
||||
|
||||
void Socket::setBlock(bool block){
|
||||
|
@ -149,49 +395,101 @@ void Socket::setBlock(bool block){
|
|||
}
|
||||
}
|
||||
|
||||
bool Socket::isReadable(){
|
||||
bool Socket::isReadable()
|
||||
{
|
||||
if(sock <= 0) return false;
|
||||
|
||||
TIMEVAL tv;
|
||||
tv.tv_sec= 0;
|
||||
tv.tv_usec= 10;
|
||||
tv.tv_usec= 1;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int i= select(0, &set, NULL, NULL, &tv);
|
||||
if(i==SOCKET_ERROR){
|
||||
throwException("Error selecting socket");
|
||||
}
|
||||
return i==1;
|
||||
int i= select(sock+1, &set, NULL, NULL, &tv);
|
||||
if(i==SOCKET_ERROR)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
|
||||
printf("%s",szBuf);
|
||||
}
|
||||
//return (i == 1 && FD_ISSET(sock, &set));
|
||||
return (i == 1);
|
||||
}
|
||||
|
||||
bool Socket::isWritable(){
|
||||
bool Socket::isWritable(bool waitOnDelayedResponse)
|
||||
{
|
||||
if(sock <= 0) return false;
|
||||
|
||||
TIMEVAL tv;
|
||||
tv.tv_sec= 0;
|
||||
tv.tv_usec= 10;
|
||||
tv.tv_usec= 1;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int i= select(0, NULL, &set, NULL, &tv);
|
||||
if(i==SOCKET_ERROR){
|
||||
throwException("Error selecting socket");
|
||||
}
|
||||
return i==1;
|
||||
bool result = false;
|
||||
do
|
||||
{
|
||||
int i= select(sock+1, NULL, &set, NULL, &tv);
|
||||
if(i==SOCKET_ERROR)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
|
||||
printf("%s",szBuf);
|
||||
waitOnDelayedResponse = false;
|
||||
}
|
||||
else if(i == 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
|
||||
printf("%s",szBuf);
|
||||
|
||||
if(waitOnDelayedResponse == false)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
} while(waitOnDelayedResponse == true && result == false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Socket::isConnected(){
|
||||
|
||||
//if the socket is not writable then it is not conencted
|
||||
if(!isWritable()){
|
||||
if(isWritable(false) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//if the socket is readable it is connected if we can read a byte from it
|
||||
if(isReadable()){
|
||||
char tmp;
|
||||
return recv(sock, &tmp, sizeof(tmp), MSG_PEEK) > 0;
|
||||
if(isReadable())
|
||||
{
|
||||
char tmp;
|
||||
int err = peek(&tmp, sizeof(tmp));
|
||||
return (err > 0);
|
||||
/*
|
||||
int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK);
|
||||
|
||||
if(err <= 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
int iErr = WSAGetLastError();
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr);
|
||||
printf("%s",szBuf);
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//otherwise the socket is connected
|
||||
|
@ -235,20 +533,86 @@ void Socket::throwException(const string &str){
|
|||
// class ClientSocket
|
||||
// =====================================================
|
||||
|
||||
void ClientSocket::connect(const Ip &ip, int port){
|
||||
void ClientSocket::connect(const Ip &ip, int port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
addr.sin_family= AF_INET;
|
||||
addr.sin_addr.s_addr= inet_addr(ip.getString().c_str());
|
||||
addr.sin_port= htons(port);
|
||||
|
||||
int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
|
||||
if(err==SOCKET_ERROR){
|
||||
int lastError= WSAGetLastError();
|
||||
if(err < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d WSAGetLastError() = %d",ip.getString().c_str(),port,err,WSAGetLastError());
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
|
||||
if(lastError!=WSAEWOULDBLOCK && lastError!=WSAEALREADY){
|
||||
throwException("Can not connect");
|
||||
}
|
||||
if (WSAGetLastError() == WSAEINPROGRESS) {
|
||||
|
||||
fd_set myset;
|
||||
struct timeval tv;
|
||||
int valopt;
|
||||
socklen_t lon;
|
||||
|
||||
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
|
||||
do {
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&myset);
|
||||
FD_SET(sock, &myset);
|
||||
|
||||
err = select(sock+1, NULL, &myset, NULL, &tv);
|
||||
|
||||
if (err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
sprintf(szBuf, "Error connecting %d\n", WSAGetLastError());
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
else if (err > 0) {
|
||||
// Socket selected for write
|
||||
lon = sizeof(int);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)(&valopt), &lon) < 0)
|
||||
{
|
||||
sprintf(szBuf, "Error in getsockopt() %d\n", WSAGetLastError());
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
// Check the value returned...
|
||||
if (valopt)
|
||||
{
|
||||
sprintf(szBuf, "Error in delayed connection() %d\n", valopt);
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError());
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(szBuf, "Timeout in select() - Cancelling!\n");
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
if(err < 0)
|
||||
{
|
||||
fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,WSAGetLastError());
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -269,6 +269,20 @@ XmlNode *XmlNode::getChild(const string &childName, int i) const{
|
|||
throw runtime_error("Node \""+getName()+"\" doesn't have "+intToStr(i+1)+" children named \""+childName+"\"\n\nTree: "+getTreeString());
|
||||
}
|
||||
|
||||
bool XmlNode::hasChild(const string &childName) const
|
||||
{
|
||||
int count= 0;
|
||||
for(int j = 0; j < children.size(); ++j)
|
||||
{
|
||||
if(children[j]->getName()==childName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
XmlNode *XmlNode::addChild(const string &name){
|
||||
XmlNode *node= new XmlNode(name);
|
||||
children.push_back(node);
|
||||
|
|
Loading…
Reference in New Issue