From bc725454fd5b25bcd3a913ac0946fef84df7d110 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Fri, 2 Apr 2010 02:33:32 +0000 Subject: [PATCH] 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 --- source/glest_game/menu/main_menu.h | 121 ++++++ .../glest_game/menu/menu_state_join_game.cpp | 67 +++- source/glest_game/menu/menu_state_join_game.h | 9 +- .../glest_game/network/client_interface.cpp | 11 +- source/glest_game/network/client_interface.h | 3 +- .../include/platform/posix/socket.h | 46 ++- .../sources/platform/posix/socket.cpp | 366 ++++++++++++------ 7 files changed, 475 insertions(+), 148 deletions(-) create mode 100644 source/glest_game/menu/main_menu.h diff --git a/source/glest_game/menu/main_menu.h b/source/glest_game/menu/main_menu.h new file mode 100644 index 000000000..3b3ab8ba8 --- /dev/null +++ b/source/glest_game/menu/main_menu.h @@ -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 diff --git a/source/glest_game/menu/menu_state_join_game.cpp b/source/glest_game/menu/menu_state_join_game.cpp index f0f32ebce..2d4c26b5f 100644 --- a/source/glest_game/menu/menu_state_join_game.cpp +++ b/source/glest_game/menu/menu_state_join_game.cpp @@ -52,12 +52,15 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool servers.load(serversSavedFile); //buttons - buttonReturn.init(325, 300, 125); + buttonReturn.init(300, 300, 125); buttonReturn.setText(lang.get("Return")); - buttonConnect.init(475, 300, 125); + buttonConnect.init(450, 300, 125); buttonConnect.setText(lang.get("Connect")); + buttonAutoFindServers.init(595, 300, 125); + buttonAutoFindServers.setText(lang.get("FindLANGames")); + //server type label labelServerType.init(330, 460); labelServerType.setText(lang.get("ServerType") + ":"); @@ -104,6 +107,31 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool chatManager.init(&console, -1); } +MenuStateJoinGame::~MenuStateJoinGame() { + NetworkManager &networkManager= NetworkManager::getInstance(); + ClientInterface* clientInterface= networkManager.getClientInterface(); + clientInterface->stopServerDiscovery(); +} + +void MenuStateJoinGame::DiscoveredServers(std::vector serverList) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + if(serverList.size() > 0) { + string bestIPMatch = ""; + std::vector 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) { @@ -165,6 +193,20 @@ void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton) 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__); } @@ -172,6 +214,7 @@ void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton) void MenuStateJoinGame::mouseMove(int x, int y, const MouseState *ms){ buttonReturn.mouseMove(x, y); buttonConnect.mouseMove(x, y); + buttonAutoFindServers.mouseMove(x, y); listBoxServerType.mouseMove(x, y); //hide-show options depending on the selection @@ -192,6 +235,7 @@ void MenuStateJoinGame::render(){ renderer.renderLabel(&labelStatus); renderer.renderLabel(&labelInfo); renderer.renderButton(&buttonConnect); + renderer.renderButton(&buttonAutoFindServers); renderer.renderListBox(&listBoxServerType); if(listBoxServerType.getSelectedItemIndex()==newServerIndex){ @@ -353,25 +397,6 @@ void MenuStateJoinGame::keyDown(char key){ labelServerIp.setText(text); } - else if(key== 'A') { - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - - string bestIPMatch = ""; - std::vector serverList = clientInterface->discoverServers(); - if(serverList.size() > 0) { - std::vector 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 { diff --git a/source/glest_game/menu/menu_state_join_game.h b/source/glest_game/menu/menu_state_join_game.h index b381ca335..e9565f991 100644 --- a/source/glest_game/menu/menu_state_join_game.h +++ b/source/glest_game/menu/menu_state_join_game.h @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2005 Martiņo Figueroa +// Copyright (C) 2001-2005 Martio Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published @@ -15,6 +15,8 @@ #include "properties.h" #include "main_menu.h" #include "chat_manager.h" +#include +#include using Shared::Util::Properties; @@ -26,7 +28,7 @@ class NetworkMessageIntro; // class MenuStateJoinGame // =============================== -class MenuStateJoinGame: public MenuState{ +class MenuStateJoinGame: public MenuState, public DiscoveredServersInterface { private: static const int newServerIndex; static const string serverFileName; @@ -34,6 +36,7 @@ private: private: GraphicButton buttonReturn; GraphicButton buttonConnect; + GraphicButton buttonAutoFindServers; GraphicLabel labelServer; GraphicLabel labelServerType; GraphicLabel labelServerIp; @@ -53,6 +56,7 @@ private: public: MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool connect= false, Ip serverIp= Ip()); + virtual ~MenuStateJoinGame(); void mouseClick(int x, int y, MouseButton mouseButton); void mouseMove(int x, int y, const MouseState *mouseState); @@ -63,6 +67,7 @@ public: private: void connectToServer(); + virtual void DiscoveredServers(std::vector serverList); }; }}//end namespace diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index 06e6cb33b..4c4dfa2c5 100755 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -560,14 +560,19 @@ void ClientInterface::close() clientSocket= NULL; } -std::vector ClientInterface::discoverServers() { +void ClientInterface::discoverServers(DiscoveredServersInterface *cb) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - std::vector serverList = ClientSocket::discoverServers(); + ClientSocket::discoverServers(cb); 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__); } /* diff --git a/source/glest_game/network/client_interface.h b/source/glest_game/network/client_interface.h index 920a4ab01..ef2c68b9e 100644 --- a/source/glest_game/network/client_interface.h +++ b/source/glest_game/network/client_interface.h @@ -76,7 +76,8 @@ public: void connect(const Ip &ip, int port); void reset(); - std::vector discoverServers(); + void discoverServers(DiscoveredServersInterface *cb); + void stopServerDiscovery(); private: void waitForMessage(); diff --git a/source/shared_lib/include/platform/posix/socket.h b/source/shared_lib/include/platform/posix/socket.h index 3fc478fc5..970459bdc 100644 --- a/source/shared_lib/include/platform/posix/socket.h +++ b/source/shared_lib/include/platform/posix/socket.h @@ -30,6 +30,15 @@ using std::string; 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 serverList) = 0; +}; + // ===================================================== // class IP // ===================================================== @@ -80,6 +89,8 @@ public: int peek(void *data, int dataSize); void setBlock(bool block); + static void setBlock(bool block, int socket); + bool isReadable(); bool isWritable(bool waitOnDelayedResponse); bool isConnected(); @@ -91,15 +102,46 @@ protected: 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: public Socket{ public: - void connect(const Ip &ip, int port); + ClientSocket(); + virtual ~ClientSocket(); - static std::vector 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 diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index 0e097ffb6..a4885c62f 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -33,6 +33,7 @@ using namespace Shared::Util; namespace Shared{ namespace Platform{ int Socket::broadcast_portno = 61357; +BroadCastClientSocketThread *ClientSocket::broadCastClientThread = NULL; // ===================================================== // class Ip @@ -430,7 +431,11 @@ int Socket::peek(void *data, int dataSize){ } 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){ throwException("Error setting I/O mode for socket"); } @@ -602,6 +607,64 @@ void Socket::throwException(const string &str){ // 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) { sockaddr_in addr; @@ -695,16 +758,83 @@ void ClientSocket::connect(const Ip &ip, int port) } //======================================================================= -// Function : discovery_response_thread -// in : none -// return : none -// Description: To be forked in its own thread to listen and respond to broadcasts from +// Function : discovery response thread +// Description: Runs in its own thread to listen for broadcasts from // other servers // -std::vector ClientSocket::discoverServers() { +BroadCastClientSocketThread::BroadCastClientSocketThread(DiscoveredServersInterface *cb) { 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 +// +void BroadCastClientSocketThread::execute() { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + std::vector foundServers; short port; // The port for the broadcast. @@ -739,30 +869,62 @@ std::vector ClientSocket::discoverServers() { } else { 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 tokens; - Tokenize(buff,tokens,":"); - for(int idx = 1; idx < tokens.size(); idx++) { - foundServers.push_back(tokens[idx]); + Socket::setBlock(false, bcfd); + + setRunningStatus(true); + 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 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__); - 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. char buff[1024]; // Buffers the data to be broadcasted. 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 hostent* myhostent; char * ptr; // some transient vars @@ -973,116 +1134,83 @@ void BroadCastSocketThread::execute() { // get only the first host IP address std::vector ipList = Socket::getLocalIPAddressList(); - /* - strcpy(subnetmask, ipList[0].c_str()); - ptr = &subnetmask[0]; - len = strlen(ptr); + port = htons( Socket::getBroadCastPort() ); - // substitute the address with class C subnet mask x.x.x.255 - for(i=len;i>0;i--) { - if(ptr[i] == '.') { - strcpy(&ptr[i+1],"255"); - break; - } - } - */ + // Create the broadcast socket + memset( &bcLocal, 0, sizeof( struct sockaddr_in)); + bcLocal.sin_family = AF_INET; + bcLocal.sin_addr.s_addr = htonl( INADDR_BROADCAST ); + 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( (tbcaddr = inet_addr( subnetmask )) == INADDR_NONE ) - //{ - // SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Badly formatted BC address: %d\n", errno); - //exit(-1); - //} - //else - { - port = htons( Socket::getBroadCastPort() ); + // If there is an error, report it and terminate. + if( bcfd <= 0 ) { + 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 { - // Create the broadcast socket - memset( &bcLocal, 0, sizeof( struct sockaddr_in)); - bcLocal.sin_family = AF_INET; - bcLocal.sin_addr.s_addr = htonl( INADDR_BROADCAST ); - 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 ); + // Record the broadcast address of the receiver. + bcaddr.sin_family = AF_INET; + bcaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);//tbcaddr; + bcaddr.sin_port = port; - // If there is an error, report it and terminate. - if( bcfd <= 0 ) { - 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 { + setRunningStatus(true); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Server thread is running\n"); - //int val = 1; - //setsockopt(bcfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - //if(::bind(bcfd, (struct sockaddr *) &bcLocal, sizeof(struct sockaddr_in)) < 0) { - // SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Could not bind address to BC socket.: %d\n", errno); - //exit(-1); - //} - //else + 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++ ) { - // Record the broadcast address of the receiver. - bcaddr.sin_family = AF_INET; - bcaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);//tbcaddr; - bcaddr.sin_port = port; - - 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) { + time_t elapsed = time(NULL); + // Broadcast the packet to the subnet + if( sendto( bcfd, buff, sizeof(buff) + 1, 0 , (struct sockaddr *)&bcaddr, sizeof(struct sockaddr_in) ) != sizeof(buff) + 1 ) { - if(difftime(time(NULL),elapsed) >= 1) { - time_t elapsed = time(NULL); - // 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 + 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__); } - catch(const exception &ex) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); - setRunningStatus(false); + if(getQuitStatus() == true) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + break; } - 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"); + sleep( 100 ); // send out broadcast every 1 seconds } + 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__); }