Exemple #1
0
bool CGamePlayer :: Update( void *fd )
{
    // wait 4 seconds after joining before sending the /whois or /w
    // if we send the /whois too early battle.net may not have caught up with where the player is and return erroneous results

    if( m_WhoisShouldBeSent && !m_Spoofed && !m_WhoisSent && !m_JoinedRealm.empty( ) && GetTime( ) - m_JoinTime >= 4 )
    {
        // todotodo: we could get kicked from battle.net for sending a command with invalid characters, do some basic checking

        for( vector<CBNET *> :: iterator i = m_Game->m_OHBot->m_BNETs.begin( ); i != m_Game->m_OHBot->m_BNETs.end( ); ++i )
        {
            if( (*i)->GetServer( ) == m_JoinedRealm )
            {
                if( m_Game->GetGameState( ) == GAME_PUBLIC )
                {
                    if( (*i)->GetPasswordHashType( ) == "pvpgn" )
                        (*i)->QueueChatCommand( "/whereis " + m_Name );
                    else
                        (*i)->QueueChatCommand( "/whois " + m_Name );
                }
                else if( m_Game->GetGameState( ) == GAME_PRIVATE )
                    (*i)->QueueChatCommand( m_Game->m_OHBot->m_Language->SpoofCheckByReplying( ), m_Name, true );
            }
        }

        m_WhoisSent = true;
    }

    // check for socket timeouts
    // if we don't receive anything from a player for 30 seconds we can assume they've dropped
    // this works because in the lobby we send pings every 5 seconds and expect a response to each one
    // and in the game the Warcraft 3 client sends keepalives frequently (at least once per second it looks like)

    if( m_Socket && GetTime( ) - m_Socket->GetLastRecv( ) >= 30 )
        m_Game->EventPlayerDisconnectTimedOut( this );

    // make sure we're not waiting too long for the first MAPSIZE packet

    /*    	if( m_ConnectionState == 1 && GetTicks( ) - m_ConnectionTime > 5000 && !m_Game->GetGameLoaded() && !m_Game->GetGameLoading() )
        {
            Log->Info( "[DENY] Kicking player: MAPSIZE not received within five seconds" );
            m_DeleteMe = true;
                SetLeftReason( "MAPSIZE not received within five seconds" );
                SetLeftCode( PLAYERLEAVE_LOBBY );
                m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
            }
    */
    // disconnect if the player is downloading too slowly

    // make this a bit dynamically, first 10 KB/s is a bit too low, increasing to 100KB/s
    //decreasing the checktime to 5 seconds
    // adding an actual playercheck how many players are ingame, if there less than 1 open slots we deny users with a download rate under 500KB/s
    if( m_DownloadStarted && !m_DownloadFinished && !m_Game->GetGameLoaded() && !m_Game->GetGameLoading() && GetLastMapPartSent( ) > 0 && m_Game->m_OHBot->m_KickSlowDownloader )
    {
        uint32_t downloadingTime = GetTicks( ) - m_StartedDownloadingTicks;

        if( downloadingTime > 5000 && m_Level < 1)
        {
            if( GetLastMapPartAcked( ) / downloadingTime < 500 && m_Game->GetSlotsOccupied( ) <= 1 )
            {
                m_DeleteMe = true;
                SetLeftReason( "download speed too low" );
                SetLeftCode( PLAYERLEAVE_LOBBY );
                m_Game->SendAllChat( m_Game->m_OHBot->m_Language->UserWasKickedForSlowDownloadRate( m_Name ) );
                m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
            }
            else if( GetLastMapPartAcked( ) / downloadingTime < 100 )
            {
                m_DeleteMe = true;
                SetLeftReason( "download speed too low" );
                SetLeftCode( PLAYERLEAVE_LOBBY );
                m_Game->SendAllChat( m_Game->m_OHBot->m_Language->UserWasKickedForSlowDownloadRate( m_Name ) );
                m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
            }
        }
    }

    // unmute player
    if( GetMuted( ) && m_MutedAuto && GetTicks( ) - m_MutedTicks > 30000  )
    {
        SetMuted( false );
        m_Game->SendChat( m_PID, "["+m_Game->m_OHBot->m_BotManagerName+"] "+m_Game->m_OHBot->m_Language->UserWasAutomaticallyUnmuted( ) );
        m_MuteMessages.clear( );
    }

    // GProxy++ acks

    if( m_Game->m_OHBot->IsMode( BOT_MODE_GPROXY ) && m_GProxy && GetTime( ) - m_LastGProxyAckTime >= 10 )
    {
        if( m_Socket )
            m_Socket->PutBytes( m_Game->m_OHBot->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) );

        m_LastGProxyAckTime = GetTime( );
    }

    // base class update

    CPotentialPlayer :: Update( fd );
    bool Deleting;

    if( m_GProxy && m_Game->GetGameLoaded( ) )
        Deleting = m_DeleteMe || m_Error;
    else
        Deleting = m_DeleteMe || m_Error || m_Socket->HasError( ) || !m_Socket->GetConnected( );

    // try to find out why we're requesting deletion
    // in cases other than the ones covered here m_LeftReason should have been set when m_DeleteMe was set

    if( m_Error )
    {
        m_Game->EventPlayerDisconnectPlayerError( this );
        m_Socket->Reset( );
        return Deleting;
    }

    if( m_Socket )
    {
        if( m_Socket->HasError( ) )
        {
            m_Game->EventPlayerDisconnectSocketError( this );
            m_Socket->Reset( );
        }
        else if( !m_Socket->GetConnected( ) )
        {
            m_Game->EventPlayerDisconnectConnectionClosed( this );
            m_Socket->Reset( );
        }
    }

    return Deleting;
}
bool CGamePlayer :: Update( void *fd )
{
	// wait 4 seconds after joining before sending the /whois or /w
	// if we send the /whois too early battle.net may not have caught up with where the player is and return erroneous results

	if( m_WhoisShouldBeSent && !m_Spoofed && !m_WhoisSent && !m_JoinedRealm.empty( ) && GetTime( ) - m_JoinTime >= 4 )
	{
		// todotodo: we could get kicked from battle.net for sending a command with invalid characters, do some basic checking

		// check if we have this ip in our spoofed cached ip list
		bool isspoofed = m_Game->m_GHost->IsSpoofedIP(GetName(), GetExternalIPString());

		if (isspoofed)
		{
			CONSOLE_Print("[OPT] Player "+GetName()+" is in the cached spoof checked list");
			m_Game->AddToSpoofed(m_Game->m_Server, GetName(), false);
		}

		if (!isspoofed && GetExternalIPString()!="127.0.0.1")
		for( vector<CBNET *> :: iterator i = m_Game->m_GHost->m_BNETs.begin( ); i != m_Game->m_GHost->m_BNETs.end( ); i++ )
		{
			if( (*i)->GetServer( ) == m_JoinedRealm )
			{
				if( m_Game->GetGameState( ) == GAME_PUBLIC )
				{
					if ((*i)->GetWhereis() || (*i)->GetPasswordHashType( ) == "pvpgn" )
						(*i)->QueueChatCommand( "/whereis " + m_Name );
					else
						(*i)->QueueChatCommand( "/whois " + m_Name );
				}
				else if( m_Game->GetGameState( ) == GAME_PRIVATE )
					(*i)->QueueChatCommand( m_Game->m_GHost->m_Language->SpoofCheckByReplying( ), m_Name, true );
			}
		}

		m_WhoisSent = true;
	}

	// check for socket timeouts
	// if we don't receive anything from a player for 30 seconds we can assume they've dropped
	// this works because in the lobby we send pings every 5 seconds and expect a response to each one
	// and in the game the Warcraft 3 client sends keepalives frequently (at least once per second it looks like)

	if( m_Socket && GetTime( ) - m_Socket->GetLastRecv( ) >= 30 )
		m_Game->EventPlayerDisconnectTimedOut( this );
	// make sure we're not waiting too long for the first MAPSIZE packet
	
	if( m_ConnectionState == 1 && GetTicks( ) - m_ConnectionTime > m_Game->m_GHost->m_DenyMaxMapsizeTime && !m_Game->GetGameLoaded() && !m_Game->GetGameLoading() )
	{
		CONSOLE_Print( "[DENY] Kicking player: MAPSIZE not received within a few seconds" );
		m_DeleteMe = true;
		SetLeftReason( "MAPSIZE not received within a few seconds" );
		SetLeftCode( PLAYERLEAVE_LOBBY );
		m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
		m_Game->m_GHost->DenyIP( GetExternalIPString( ), m_Game->m_GHost->m_DenyMapsizeDuration, "MAPSIZE not received within a few seconds" );
	}
	
	// disconnect if the player is downloading too slowly
	
	if( m_DownloadStarted && !m_DownloadFinished && !m_Game->GetGameLoaded() && !m_Game->GetGameLoading() && GetLastMapPartSent( ) != 0 )
	{
		uint32_t downloadingTime = GetTicks( ) - m_StartedDownloadingTicks;
		uint32_t Seconds = downloadingTime / 1000;
		uint32_t Rate = GetLastMapPartSent( ) / 1024; // Rate in miliseconds
		if (Seconds>0)
			Rate /= Seconds;
		
		if(!(m_Game->IsSafe(GetName()) || m_Game->IsAdmin(GetName()) || m_Game->IsRootAdmin(GetName()) || m_Game->IsOwner(GetName()) )){			
		//	uint32_t iRate = (uint32_t)Rate;
			if ( m_Game->m_GHost->m_DLRateLimit != 0 )
			if ( GetLastMapPartSent( ) <= 102400 )
			if ( 0 < Rate && Rate < m_Game->m_GHost->m_DLRateLimit ){
				m_Game->DelTempOwner( GetName() );
				m_Game->SendAllChat( m_Game->m_GHost->m_Language->KickMsgForSlowDL( GetName( ) , UTIL_ToString( Rate ), UTIL_ToString(m_Game->m_GHost->m_DLRateLimit) ) );							
				m_Game->m_GHost->m_Callables.push_back( m_Game->m_GHost->m_DB->ThreadedBanAdd( GetJoinedRealm( ), GetName( ), GetExternalIPString(), m_Game->GetGameName( ), "AUTOBAN", "Slow internet", 1, 0 ));
				if ( m_Game->m_GHost->m_BlacklistSlowDLder && !m_Game->IsBlacklisted(m_Game->GetBannedNames( ),GetName( )) )
					m_Game->AddBannedNames(GetName( ));
				m_DeleteMe = true;				
				SetLeftReason( "kicked for downloading too slowly " + UTIL_ToString( Rate ) + " KB/s" );				
				SetLeftCode( PLAYERLEAVE_LOBBY );
				m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
			}
			
			if( downloadingTime > m_Game->m_GHost->m_DenyMaxDownloadTime )
			{
				m_Game->DelTempOwner( GetName() );
				m_Game->SendAllChat( m_Game->m_GHost->m_Language->KickMsgForSlowDL( GetName( ),"","" ) );
				m_DeleteMe = true;
				SetLeftReason( "download time is too long" );
				SetLeftCode( PLAYERLEAVE_LOBBY );
				m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
				m_Game->m_GHost->DenyIP( GetExternalIPString( ), m_Game->m_GHost->m_DenyDownloadDuration, "("+ GetName( ) +") rejected because download time is too long" );
			}
		}
	}
	
	// unmute player
	if( GetMuted( ) && ( GetTicks( ) - m_MutedTicks > 60000 || ( m_MutedAuto && GetTicks( ) - m_MutedTicks > 15000 ) ) )
	{
		SetMuted( false );
		m_Game->SendAllChat( "[" + m_Name + "] has been automatically unmuted. (Don't spam or you'll be muted again!)" );
		m_MuteMessages.clear( );
	}

	// GProxy++ acks

	if( m_GProxy && GetTime( ) - m_LastGProxyAckTime >= 10 )
	{
		if( m_Socket )
			m_Socket->PutBytes( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) );

		m_LastGProxyAckTime = GetTime( );
	}

	// base class update

	CPotentialPlayer :: Update( fd );
	bool Deleting;

	if( m_GProxy && m_Game->GetGameLoaded( ) )
		Deleting = m_DeleteMe || m_Error;
	else
		Deleting = m_DeleteMe || m_Error || m_Socket->HasError( ) || !m_Socket->GetConnected( );

	// try to find out why we're requesting deletion
	// in cases other than the ones covered here m_LeftReason should have been set when m_DeleteMe was set

	if( m_Error ){
		m_Game->m_GHost->DenyIP( GetExternalIPString( ), 180000, "player error" );
		m_Game->EventPlayerDisconnectPlayerError( this );
		m_Socket->Reset( );
		return Deleting;
	}
	if( m_Socket )
	{
		if( m_Socket->HasError( ) ){
			m_Game->EventPlayerDisconnectSocketError( this );
			if( !m_GProxy )
				m_Game->m_GHost->DenyIP( GetExternalIPString( ), 20000, "socket error" );
		}
		else if( !m_Socket->GetConnected( ) ){
			m_Game->EventPlayerDisconnectConnectionClosed( this );
			if( !m_GProxy )
				m_Game->m_GHost->DenyIP( GetExternalIPString( ), 30000, "connection closed" );
		}
	}

	return Deleting;
}