Added a new menu item in join menu and added a threaded callback system for clients when searching for servers so that the UI doesn't wait for responses

This commit is contained in:
Mark Vejvoda
2010-04-02 02:33:32 +00:00
parent d4e645424a
commit bc725454fd
7 changed files with 475 additions and 148 deletions

View File

@@ -0,0 +1,121 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martio Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifndef _GLEST_GAME_MAINMENU_H_
#define _GLEST_GAME_MAINMENU_H_
#include "lang.h"
#include "console.h"
#include "vec.h"
#include "world.h"
#include "program.h"
#include "components.h"
#include "menu_background.h"
#include "game_settings.h"
namespace Glest{ namespace Game{
//misc consts
struct MapInfo{
Vec2i size;
int players;
string desc;
};
struct ScenarioInfo
{
int difficulty;
ControlType factionControls[GameConstants::maxPlayers];
int teams[GameConstants::maxPlayers];
string factionTypeNames[GameConstants::maxPlayers];
string mapName;
string tilesetName;
string techTreeName;
bool defaultUnits;
bool defaultResources;
bool defaultVictoryConditions;
string desc;
};
class MenuState;
// =====================================================
// class MainMenu
//
/// Main menu ProgramState
// =====================================================
class MainMenu: public ProgramState{
private:
//up
Program *program;
//shared
GameSettings gameSettings;
MenuBackground menuBackground;
MenuState *state;
//shared
int mouseX, mouseY;
int mouse2dAnim;
int fps, lastFps;
public:
MainMenu(Program *program);
~MainMenu();
MenuBackground *getMenuBackground() {return &menuBackground;}
virtual void render();
virtual void update();
virtual void tick();
virtual void init();
virtual void mouseMove(int x, int y, const MouseState *mouseState);
virtual void mouseDownLeft(int x, int y);
virtual void mouseDownRight(int x, int y);
virtual void keyDown(char key);
virtual void keyPress(char key);
void setState(MenuState *state);
};
// ===============================
// class MenuState
// ===============================
class MenuState {
protected:
Program *program;
MainMenu *mainMenu;
Camera camera;
public:
MenuState(Program *program, MainMenu *mainMenu, const string &stateName);
virtual ~MenuState(){};
virtual void mouseClick(int x, int y, MouseButton mouseButton)=0;
virtual void mouseMove(int x, int y, const MouseState *mouseState)=0;
virtual void render()=0;
virtual void update(){};
virtual void keyDown(char key){};
virtual void keyPress(char c){};
const Camera *getCamera() const {return &camera;}
};
}}//end namespace
#endif

View File

@@ -52,12 +52,15 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool
servers.load(serversSavedFile); servers.load(serversSavedFile);
//buttons //buttons
buttonReturn.init(325, 300, 125); buttonReturn.init(300, 300, 125);
buttonReturn.setText(lang.get("Return")); buttonReturn.setText(lang.get("Return"));
buttonConnect.init(475, 300, 125); buttonConnect.init(450, 300, 125);
buttonConnect.setText(lang.get("Connect")); buttonConnect.setText(lang.get("Connect"));
buttonAutoFindServers.init(595, 300, 125);
buttonAutoFindServers.setText(lang.get("FindLANGames"));
//server type label //server type label
labelServerType.init(330, 460); labelServerType.init(330, 460);
labelServerType.setText(lang.get("ServerType") + ":"); labelServerType.setText(lang.get("ServerType") + ":");
@@ -104,6 +107,31 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool
chatManager.init(&console, -1); chatManager.init(&console, -1);
} }
MenuStateJoinGame::~MenuStateJoinGame() {
NetworkManager &networkManager= NetworkManager::getInstance();
ClientInterface* clientInterface= networkManager.getClientInterface();
clientInterface->stopServerDiscovery();
}
void MenuStateJoinGame::DiscoveredServers(std::vector<string> serverList) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(serverList.size() > 0) {
string bestIPMatch = "";
std::vector<std::string> localIPList = Socket::getLocalIPAddressList();
for(int idx = 0; idx < serverList.size(); idx++) {
bestIPMatch = serverList[idx];
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] bestIPMatch = [%s] localIPList[0] = [%s]\n",__FILE__,__FUNCTION__,__LINE__,bestIPMatch.c_str(),localIPList[0].c_str());
if(strncmp(localIPList[0].c_str(),serverList[idx].c_str(),4) == 0) {
break;
}
}
labelServerIp.setText(bestIPMatch);
connectToServer();
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton) void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton)
{ {
@@ -165,6 +193,20 @@ void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton)
connectToServer(); connectToServer();
} }
} }
else if(buttonAutoFindServers.mouseClick(x, y)) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
ClientInterface* clientInterface= networkManager.getClientInterface();
soundRenderer.playFx(coreData.getClickSoundA());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// Triggers a thread which calls back into MenuStateJoinGame::DiscoveredServers
// with the results
clientInterface->discoverServers(this);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] END\n",__FILE__,__FUNCTION__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
} }
@@ -172,6 +214,7 @@ void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton)
void MenuStateJoinGame::mouseMove(int x, int y, const MouseState *ms){ void MenuStateJoinGame::mouseMove(int x, int y, const MouseState *ms){
buttonReturn.mouseMove(x, y); buttonReturn.mouseMove(x, y);
buttonConnect.mouseMove(x, y); buttonConnect.mouseMove(x, y);
buttonAutoFindServers.mouseMove(x, y);
listBoxServerType.mouseMove(x, y); listBoxServerType.mouseMove(x, y);
//hide-show options depending on the selection //hide-show options depending on the selection
@@ -192,6 +235,7 @@ void MenuStateJoinGame::render(){
renderer.renderLabel(&labelStatus); renderer.renderLabel(&labelStatus);
renderer.renderLabel(&labelInfo); renderer.renderLabel(&labelInfo);
renderer.renderButton(&buttonConnect); renderer.renderButton(&buttonConnect);
renderer.renderButton(&buttonAutoFindServers);
renderer.renderListBox(&listBoxServerType); renderer.renderListBox(&listBoxServerType);
if(listBoxServerType.getSelectedItemIndex()==newServerIndex){ if(listBoxServerType.getSelectedItemIndex()==newServerIndex){
@@ -353,25 +397,6 @@ void MenuStateJoinGame::keyDown(char key){
labelServerIp.setText(text); labelServerIp.setText(text);
} }
else if(key== 'A') {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
string bestIPMatch = "";
std::vector<string> serverList = clientInterface->discoverServers();
if(serverList.size() > 0) {
std::vector<std::string> localIPList = Socket::getLocalIPAddressList();
for(int idx = 0; idx < serverList.size(); idx++) {
bestIPMatch = serverList[idx];
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] bestIPMatch = [%s] localIPList[0] = [%s]\n",__FILE__,__FUNCTION__,__LINE__,bestIPMatch.c_str(),localIPList[0].c_str());
if(strncmp(localIPList[0].c_str(),serverList[idx].c_str(),4) == 0) {
break;
}
}
labelServerIp.setText(bestIPMatch);
connectToServer();
}
}
} }
else else
{ {

View File

@@ -1,7 +1,7 @@
// ============================================================== // ==============================================================
// This file is part of Glest (www.glest.org) // This file is part of Glest (www.glest.org)
// //
// Copyright (C) 2001-2005 Marti<EFBFBD>o Figueroa // Copyright (C) 2001-2005 Martio Figueroa
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published
@@ -15,6 +15,8 @@
#include "properties.h" #include "properties.h"
#include "main_menu.h" #include "main_menu.h"
#include "chat_manager.h" #include "chat_manager.h"
#include <vector>
#include <string>
using Shared::Util::Properties; using Shared::Util::Properties;
@@ -26,7 +28,7 @@ class NetworkMessageIntro;
// class MenuStateJoinGame // class MenuStateJoinGame
// =============================== // ===============================
class MenuStateJoinGame: public MenuState{ class MenuStateJoinGame: public MenuState, public DiscoveredServersInterface {
private: private:
static const int newServerIndex; static const int newServerIndex;
static const string serverFileName; static const string serverFileName;
@@ -34,6 +36,7 @@ private:
private: private:
GraphicButton buttonReturn; GraphicButton buttonReturn;
GraphicButton buttonConnect; GraphicButton buttonConnect;
GraphicButton buttonAutoFindServers;
GraphicLabel labelServer; GraphicLabel labelServer;
GraphicLabel labelServerType; GraphicLabel labelServerType;
GraphicLabel labelServerIp; GraphicLabel labelServerIp;
@@ -53,6 +56,7 @@ private:
public: public:
MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool connect= false, Ip serverIp= Ip()); MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool connect= false, Ip serverIp= Ip());
virtual ~MenuStateJoinGame();
void mouseClick(int x, int y, MouseButton mouseButton); void mouseClick(int x, int y, MouseButton mouseButton);
void mouseMove(int x, int y, const MouseState *mouseState); void mouseMove(int x, int y, const MouseState *mouseState);
@@ -63,6 +67,7 @@ public:
private: private:
void connectToServer(); void connectToServer();
virtual void DiscoveredServers(std::vector<string> serverList);
}; };
}}//end namespace }}//end namespace

View File

@@ -560,14 +560,19 @@ void ClientInterface::close()
clientSocket= NULL; clientSocket= NULL;
} }
std::vector<string> ClientInterface::discoverServers() { void ClientInterface::discoverServers(DiscoveredServersInterface *cb) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
std::vector<string> serverList = ClientSocket::discoverServers(); ClientSocket::discoverServers(cb);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void ClientInterface::stopServerDiscovery() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
return serverList; ClientSocket::stopBroadCastClientThread();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
/* /*

View File

@@ -76,7 +76,8 @@ public:
void connect(const Ip &ip, int port); void connect(const Ip &ip, int port);
void reset(); void reset();
std::vector<string> discoverServers(); void discoverServers(DiscoveredServersInterface *cb);
void stopServerDiscovery();
private: private:
void waitForMessage(); void waitForMessage();

View File

@@ -30,6 +30,15 @@ using std::string;
namespace Shared{ namespace Platform{ namespace Shared{ namespace Platform{
//
// This interface describes the methods a callback object must implement
// when signalled with detected servers
//
class DiscoveredServersInterface {
public:
virtual void DiscoveredServers(std::vector<string> serverList) = 0;
};
// ===================================================== // =====================================================
// class IP // class IP
// ===================================================== // =====================================================
@@ -80,6 +89,8 @@ public:
int peek(void *data, int dataSize); int peek(void *data, int dataSize);
void setBlock(bool block); void setBlock(bool block);
static void setBlock(bool block, int socket);
bool isReadable(); bool isReadable();
bool isWritable(bool waitOnDelayedResponse); bool isWritable(bool waitOnDelayedResponse);
bool isConnected(); bool isConnected();
@@ -91,15 +102,46 @@ protected:
static void throwException(const string &str); static void throwException(const string &str);
}; };
class BroadCastClientSocketThread : public Thread
{
private:
Mutex mutexRunning;
Mutex mutexQuit;
bool quit;
bool running;
DiscoveredServersInterface *discoveredServersCB;
void setRunningStatus(bool value);
void setQuitStatus(bool value);
public:
BroadCastClientSocketThread(DiscoveredServersInterface *cb);
virtual void execute();
void signalQuit();
bool getQuitStatus();
bool getRunningStatus();
};
// ===================================================== // =====================================================
// class ClientSocket // class ClientSocket
// ===================================================== // =====================================================
class ClientSocket: public Socket{ class ClientSocket: public Socket{
public: public:
void connect(const Ip &ip, int port); ClientSocket();
virtual ~ClientSocket();
static std::vector<string> discoverServers(); void connect(const Ip &ip, int port);
static void discoverServers(DiscoveredServersInterface *cb);
static void stopBroadCastClientThread();
protected:
static BroadCastClientSocketThread *broadCastClientThread;
static void startBroadCastClientThread(DiscoveredServersInterface *cb);
}; };
class BroadCastSocketThread : public Thread class BroadCastSocketThread : public Thread

View File

@@ -33,6 +33,7 @@ using namespace Shared::Util;
namespace Shared{ namespace Platform{ namespace Shared{ namespace Platform{
int Socket::broadcast_portno = 61357; int Socket::broadcast_portno = 61357;
BroadCastClientSocketThread *ClientSocket::broadCastClientThread = NULL;
// ===================================================== // =====================================================
// class Ip // class Ip
@@ -430,7 +431,11 @@ int Socket::peek(void *data, int dataSize){
} }
void Socket::setBlock(bool block){ void Socket::setBlock(bool block){
int err= fcntl(sock, F_SETFL, block ? 0 : O_NONBLOCK); setBlock(block,this->sock);
}
void Socket::setBlock(bool block, int socket){
int err= fcntl(socket, F_SETFL, block ? 0 : O_NONBLOCK);
if(err<0){ if(err<0){
throwException("Error setting I/O mode for socket"); throwException("Error setting I/O mode for socket");
} }
@@ -602,6 +607,64 @@ void Socket::throwException(const string &str){
// class ClientSocket // class ClientSocket
// =============================================== // ===============================================
ClientSocket::ClientSocket() : Socket() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//broadCastClientThread = NULL;
stopBroadCastClientThread();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
ClientSocket::~ClientSocket() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
stopBroadCastClientThread();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void ClientSocket::stopBroadCastClientThread() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(broadCastClientThread != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
broadCastClientThread->signalQuit();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 5; ) {
if(broadCastClientThread->getRunningStatus() == false) {
break;
}
sleep(100);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete broadCastClientThread;
broadCastClientThread = NULL;
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void ClientSocket::startBroadCastClientThread(DiscoveredServersInterface *cb) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
ClientSocket::stopBroadCastClientThread();
broadCastClientThread = new BroadCastClientSocketThread(cb);
broadCastClientThread->start();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void ClientSocket::discoverServers(DiscoveredServersInterface *cb) {
ClientSocket::startBroadCastClientThread(cb);
}
void ClientSocket::connect(const Ip &ip, int port) void ClientSocket::connect(const Ip &ip, int port)
{ {
sockaddr_in addr; sockaddr_in addr;
@@ -695,16 +758,83 @@ void ClientSocket::connect(const Ip &ip, int port)
} }
//======================================================================= //=======================================================================
// Function : discovery_response_thread // Function : discovery response thread
// in : none // Description: Runs in its own thread to listen for broadcasts from
// return : none
// Description: To be forked in its own thread to listen and respond to broadcasts from
// other servers // other servers
// //
std::vector<string> ClientSocket::discoverServers() { BroadCastClientSocketThread::BroadCastClientSocketThread(DiscoveredServersInterface *cb) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
setQuitStatus(false);
setRunningStatus(false);
discoveredServersCB = cb;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void BroadCastClientSocketThread::signalQuit() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
setQuitStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void BroadCastClientSocketThread::setQuitStatus(bool value) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
mutexQuit.p();
quit = value;
mutexQuit.v();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
bool BroadCastClientSocketThread::getQuitStatus() {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
bool retval = false;
mutexQuit.p();
retval = quit;
mutexQuit.v();
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
return retval;
}
bool BroadCastClientSocketThread::getRunningStatus() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
bool retval = false;
mutexRunning.p();
retval = running;
mutexRunning.v();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] running = %d\n",__FILE__,__FUNCTION__,__LINE__,retval);
return retval;
}
void BroadCastClientSocketThread::setRunningStatus(bool value) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] value = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
mutexRunning.p();
running = value;
mutexRunning.v();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] running = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
}
//=======================================================================
// Function : broadcast thread
// Description: Runs in its own thread to send out a broadcast to the local network
// the current broadcast message is <myhostname:my.ip.address.dotted>
//
void BroadCastClientSocketThread::execute() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
std::vector<string> foundServers; std::vector<string> foundServers;
short port; // The port for the broadcast. short port; // The port for the broadcast.
@@ -739,30 +869,62 @@ std::vector<string> ClientSocket::discoverServers() {
} }
else { else {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// Keep getting packets forever.
for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 3; )
{
alen = sizeof(struct sockaddr);
if( (nb = recvfrom(bcfd, buff, 10024, 0, (struct sockaddr *) &bcSender, &alen)) <= 0 )
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"recvfrom failed: %d\n", errno);
//exit(-1);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"broadcast message received: [%s] from: [%s]\n", buff,inet_ntoa(bcSender.sin_addr) );
vector<string> tokens; Socket::setBlock(false, bcfd);
Tokenize(buff,tokens,":");
for(int idx = 1; idx < tokens.size(); idx++) { setRunningStatus(true);
foundServers.push_back(tokens[idx]); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is running\n");
try
{
// Keep getting packets forever.
for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 5; )
{
alen = sizeof(struct sockaddr);
if( (nb = recvfrom(bcfd, buff, 10024, 0, (struct sockaddr *) &bcSender, &alen)) <= 0 )
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"recvfrom failed: %d\n", errno);
//exit(-1);
}
else {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"broadcast message received: [%s] from: [%s]\n", buff,inet_ntoa(bcSender.sin_addr) );
vector<string> tokens;
Tokenize(buff,tokens,":");
for(int idx = 1; idx < tokens.size(); idx++) {
foundServers.push_back(tokens[idx]);
}
break;
}
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
sleep( 100 ); // send out broadcast every 1 seconds
} }
break;
} }
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
setRunningStatus(false);
}
catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(false);
}
setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is exiting\n");
} }
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
return foundServers; // Here we callback into the implementer class
if(discoveredServersCB != NULL) {
discoveredServersCB->DiscoveredServers(foundServers);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
// =============================================== // ===============================================
@@ -960,7 +1122,6 @@ void BroadCastSocketThread::execute() {
int pn; // The number of the packet broadcasted. int pn; // The number of the packet broadcasted.
char buff[1024]; // Buffers the data to be broadcasted. char buff[1024]; // Buffers the data to be broadcasted.
char myhostname[100]; // hostname of local machine char myhostname[100]; // hostname of local machine
//char subnetmask[100]; // Subnet mask to broadcast to
struct in_addr myaddr; // My host address in net format struct in_addr myaddr; // My host address in net format
struct hostent* myhostent; struct hostent* myhostent;
char * ptr; // some transient vars char * ptr; // some transient vars
@@ -973,116 +1134,83 @@ void BroadCastSocketThread::execute() {
// get only the first host IP address // get only the first host IP address
std::vector<std::string> ipList = Socket::getLocalIPAddressList(); std::vector<std::string> ipList = Socket::getLocalIPAddressList();
/* port = htons( Socket::getBroadCastPort() );
strcpy(subnetmask, ipList[0].c_str());
ptr = &subnetmask[0];
len = strlen(ptr);
// substitute the address with class C subnet mask x.x.x.255 // Create the broadcast socket
for(i=len;i>0;i--) { memset( &bcLocal, 0, sizeof( struct sockaddr_in));
if(ptr[i] == '.') { bcLocal.sin_family = AF_INET;
strcpy(&ptr[i+1],"255"); bcLocal.sin_addr.s_addr = htonl( INADDR_BROADCAST );
break; bcLocal.sin_port = port; // We are letting the OS fill in the port number for the local machine.
} bcfd = socket( AF_INET, SOCK_DGRAM, 0 );
}
*/
// Convert the broadcast address from dot notation to a broadcast address. // If there is an error, report it and terminate.
//if( (tbcaddr = inet_addr( subnetmask )) == INADDR_NONE ) if( bcfd <= 0 ) {
//{ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Unable to allocate broadcast socket.: %d\n", errno);
// SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Badly formatted BC address: %d\n", errno); //exit(-1);
//exit(-1); }
//} // Mark the socket for broadcast.
//else else if( setsockopt( bcfd, SOL_SOCKET, SO_BROADCAST, (const char *) &one, sizeof( int ) ) < 0 ) {
{ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Could not set socket to broadcast.: %d\n", errno);
port = htons( Socket::getBroadCastPort() ); //exit(-1);
}
// Bind the address to the broadcast socket.
else {
// Create the broadcast socket // Record the broadcast address of the receiver.
memset( &bcLocal, 0, sizeof( struct sockaddr_in)); bcaddr.sin_family = AF_INET;
bcLocal.sin_family = AF_INET; bcaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);//tbcaddr;
bcLocal.sin_addr.s_addr = htonl( INADDR_BROADCAST ); bcaddr.sin_port = port;
bcLocal.sin_port = port; // We are letting the OS fill in the port number for the local machine.
bcfd = socket( AF_INET, SOCK_DGRAM, 0 );
// If there is an error, report it and terminate. setRunningStatus(true);
if( bcfd <= 0 ) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Server thread is running\n");
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Unable to allocate broadcast socket.: %d\n", errno);
//exit(-1);
}
// Mark the socket for broadcast.
else if( setsockopt( bcfd, SOL_SOCKET, SO_BROADCAST, (const char *) &one, sizeof( int ) ) < 0 ) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Could not set socket to broadcast.: %d\n", errno);
//exit(-1);
}
// Bind the address to the broadcast socket.
else {
//int val = 1; SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//setsockopt(bcfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
//if(::bind(bcfd, (struct sockaddr *) &bcLocal, sizeof(struct sockaddr_in)) < 0) { try {
// SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Could not bind address to BC socket.: %d\n", errno); // Send this machine's host name and address in hostname:n.n.n.n format
//exit(-1); sprintf(buff,"%s",myhostname);
//} for(int idx = 0; idx < ipList.size(); idx++) {
//else sprintf(buff,"%s:%s",buff,ipList[idx].c_str());
}
time_t elapsed = 0;
for( pn = 1; ; pn++ )
{ {
// Record the broadcast address of the receiver. if(difftime(time(NULL),elapsed) >= 1) {
bcaddr.sin_family = AF_INET; time_t elapsed = time(NULL);
bcaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);//tbcaddr; // Broadcast the packet to the subnet
bcaddr.sin_port = port; if( sendto( bcfd, buff, sizeof(buff) + 1, 0 , (struct sockaddr *)&bcaddr, sizeof(struct sockaddr_in) ) != sizeof(buff) + 1 )
setRunningStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is running\n");
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
try {
// Send this machine's host name and address in hostname:n.n.n.n format
sprintf(buff,"%s",myhostname);
for(int idx = 0; idx < ipList.size(); idx++) {
sprintf(buff,"%s:%s",buff,ipList[idx].c_str());
}
time_t elapsed = 0;
for( pn = 1; ; pn++ )
{ {
if(difftime(time(NULL),elapsed) >= 1) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Sendto error: %d\n", errno);
time_t elapsed = time(NULL); //exit(-1);
// Broadcast the packet to the subnet
if( sendto( bcfd, buff, sizeof(buff) + 1, 0 , (struct sockaddr *)&bcaddr, sizeof(struct sockaddr_in) ) != sizeof(buff) + 1 )
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Sendto error: %d\n", errno);
//exit(-1);
}
else {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting to [%s] the message: [%s]\n",subnetmask,buff);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting on port [%d] the message: [%s]\n",Socket::getBroadCastPort(),buff);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
sleep( 100 ); // send out broadcast every 1 seconds
} }
else {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting to [%s] the message: [%s]\n",subnetmask,buff);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcasting on port [%d] the message: [%s]\n",Socket::getBroadCastPort(),buff);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
catch(const exception &ex) { if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(false); break;
} }
catch(...) { sleep( 100 ); // send out broadcast every 1 seconds
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(false);
}
setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is exiting\n");
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
} catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
setRunningStatus(false);
}
catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(false);
}
setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is exiting\n");
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }