Index: ghost/game_base.cpp =================================================================== --- ghost/game_base.cpp (revision 580) +++ ghost/game_base.cpp (working copy) @@ -388,12 +388,13 @@ // we also broadcast the game to the local network every 5 seconds so we hijack this timer for our nefarious purposes // however we only want to broadcast if the countdown hasn't started - // see the !sendlan code later in this file for some more information about how this works - // todotodo: should we send a game cancel message somewhere? we'll need to implement a host counter for it to work - - if( !m_CountDownStarted ) - { - // construct a fixed host counter which will be used to identify players from this "realm" (i.e. LAN) + // see the !sendlan code later in this file for some more information about how this works + // todotodo: should we send a game cancel message somewhere? we'll need to implement a host counter for it to work + + + if( !m_CountDownStarted ) + { + // construct a fixed host counter which will be used to identify players from this "realm" (i.e. LAN) // the fixed host counter's 4 most significant bits will contain a 4 bit ID (0-15) // the rest of the fixed host counter will contain the 28 least significant bits of the actual host counter // since we're destroying 4 bits of information here the actual host counter should not be greater than 2^28 which is a reasonable assumption Index: ghost/ghost.cpp =================================================================== --- ghost/ghost.cpp (revision 580) +++ ghost/ghost.cpp (working copy) @@ -677,12 +677,20 @@ if( m_AdminGamePort == m_HostPort ) CONSOLE_Print( "[GHOST] warning - admingame_port and bot_hostport are set to the same value, you won't be able to host any games" ); } - else - m_AdminGame = NULL; - - if( m_BNETs.empty( ) && !m_AdminGame ) - CONSOLE_Print( "[GHOST] warning - no battle.net connections found and no admin game created" ); - + else + m_AdminGame = NULL; + + // create the listening socket for broadcasters; + + int Port = CFG->GetInt("bot_broadcasters_port", 6969 ); + m_GameBroadcastersListener = new CTCPServer( ); + m_GameBroadcastersListener->Listen( string( ),Port ); + CONSOLE_Print( "[GHOST] Listening for game broadcasters on port [" + UTIL_ToString( Port ) +"]" ); + + + if( m_BNETs.empty( ) && !m_AdminGame ) + CONSOLE_Print( "[GHOST] warning - no battle.net connections found and no admin game created" ); + #ifdef GHOST_MYSQL CONSOLE_Print( "[GHOST] GHost++ Version " + m_Version + " (with MySQL support)" ); #else @@ -881,9 +889,23 @@ { (*i)->SetFD( &fd, &send_fd, &nfds ); ++NumFDs; - } - - // before we call select we need to determine how long to block for + } + // 6. the Game Broadcasters + for(vector::iterator i = m_GameBroadcasters.begin( ); i!= m_GameBroadcasters.end( ); i++ ) + { + if ( (*i)->GetConnected( ) && !(*i)->HasError( ) ) + { + (*i)->SetFD( &fd, &send_fd, &nfds ); + NumFDs++; + } + } + + // 7. the listener for game broadcasters + m_GameBroadcastersListener->SetFD( &fd, &send_fd,&nfds ); + NumFDs++; + + + // before we call select we need to determine how long to block for // previously we just blocked for a maximum of the passed usecBlock microseconds // however, in an effort to make game updates happen closer to the desired latency setting we now use a dynamic block interval // note: we still use the passed usecBlock as a hard maximum @@ -1170,12 +1192,37 @@ } } - m_LastAutoHostTime = GetTime( ); - } - - return m_Exiting || AdminExit || BNETExit; -} - + m_LastAutoHostTime = GetTime( ); + } + + CTCPSocket *NewSocket = m_GameBroadcastersListener->Accept( &fd ); + if ( NewSocket ) + { + m_GameBroadcasters.push_back( NewSocket ); + CONSOLE_Print("[GHOST] Game Broadcaster [" + NewSocket->GetIPString( ) +"] connected" ); + //BYTEARRAY info; + // UTIL_AppendByteArray( info, m_AdminGamePort,false ); + //UTIL_AppendByteArray( info, m_HostPort, false ); + //NewSocket->PutBytes( info ); + } + for(vector::iterator i = m_GameBroadcasters.begin( ); i!= m_GameBroadcasters.end( ); ) + { + if ( (*i)->HasError( ) || !(*i)->GetConnected( ) ) + { + CONSOLE_Print("[GHOST] Game Broadcaster [" + (*i)->GetIPString( ) +"] disconnected"); + delete *i; + i = m_GameBroadcasters.erase( i ); + continue; + } + //(*i)->DoRecv( &fd ); + (*i)->DoSend( &send_fd ); + i++; + } + + + return m_Exiting || AdminExit || BNETExit; +} + void CGHost :: EventBNETConnecting( CBNET *bnet ) { if( m_AdminGame ) Index: ghost/ghost.h =================================================================== --- ghost/ghost.h (revision 580) +++ ghost/ghost.h (working copy) @@ -130,13 +130,15 @@ string m_AdminGameMap; // config value: the admin game map config to use unsigned char m_LANWar3Version; // config value: LAN warcraft 3 version uint32_t m_ReplayWar3Version; // config value: replay warcraft 3 version (for saving replays) - uint32_t m_ReplayBuildNumber; // config value: replay build number (for saving replays) - bool m_TCPNoDelay; // config value: use Nagle's algorithm or not - uint32_t m_MatchMakingMethod; // config value: the matchmaking method + uint32_t m_ReplayBuildNumber; // config value: replay build number (for saving replays) + bool m_TCPNoDelay; // config value: use Nagle's algorithm or not + uint32_t m_MatchMakingMethod; // config value: the matchmaking method + CTCPServer *m_GameBroadcastersListener; // listening socket for game broadcasters + vector m_GameBroadcasters;// vector of sockets that broadcast the games + + CGHost( CConfig *CFG ); + ~CGHost( ); - CGHost( CConfig *CFG ); - ~CGHost( ); - // processing functions bool Update( long usecBlock );