Index: ghost/ghost.cpp =================================================================== --- ghost/ghost.cpp (revision 600) +++ 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 600) +++ ghost/ghost.h (working copy) @@ -134,6 +134,8 @@ bool m_TCPNoDelay; // config value: use Nagle's algorithm or not uint32_t m_MatchMakingMethod; // config value: the matchmaking method uint32_t m_MapGameType; // config value: the MapGameType overwrite (aka: refresh hack) + CTCPServer *m_GameBroadcastersListener; // listening socket for game broadcasters + vector m_GameBroadcasters;// vector of sockets that broadcast the games CGHost( CConfig *CFG ); ~CGHost( );