BOOL CUploadTransferED2K::Request(MD4* pMD4)
{
	BOOL bSame = ( m_bED2K && m_pED2K == *pMD4 );
	
	Cleanup( ! bSame );
	
	CSingleLock oLock( &Library.m_pSection, TRUE );
	if ( CLibraryFile* pFile = LibraryMaps.LookupFileByED2K( pMD4, TRUE, TRUE ) )
	{
		// Send comments if necessary
		if ( m_pClient ) m_pClient->SendCommentsPacket( pFile->m_nRating, pFile->m_sComments );

		RequestComplete( pFile );
		oLock.Unlock();
	}
	else
	{
		oLock.Unlock();
		if ( CDownload* pFile = Downloads.FindByED2K( pMD4, TRUE ) )
		{
			RequestPartial( pFile );
		}
		else
		{
			UploadQueues.Dequeue( this );
			
			theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress,
				(LPCTSTR)CED2K::HashToString( pMD4, TRUE ) );	
			
			CEDPacket* pReply = CEDPacket::New( ED2K_C2C_FILENOTFOUND );
			pReply->Write( pMD4, sizeof(MD4) );
			Send( pReply );
			
			Close();
			return FALSE;
		}
	}
	
	if ( UploadQueues.GetPosition( this, FALSE ) < 0 && ! UploadQueues.Enqueue( this ) )
	{
		theApp.Message( MSG_ERROR, IDS_UPLOAD_BUSY_QUEUE,
			(LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress, _T("ED2K") );	
		
		CEDPacket* pReply = CEDPacket::New( ED2K_C2C_FILENOTFOUND );
		pReply->Write( pMD4, sizeof(MD4) );
		Send( pReply );
		
		Close();
		return FALSE;
	}
	
	AllocateBaseFile();
	
	theApp.Message( MSG_SYSTEM, IDS_UPLOAD_FILE,
		(LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
	
	m_nRanking = -1;
	return CheckRanking();
}
BOOL CUploadTransferED2K::OnConnected()
{
	if ( m_nState != upsConnecting ) return TRUE;
	
	m_tRequest = GetTickCount();
	m_nRanking = -1;
	
	m_pClient->m_mOutput.pLimit = &m_nBandwidth;
	
	return CheckRanking();
}
BOOL CUploadTransferDC::OnRun()
{
	if ( ! CUploadTransfer::OnRun() )
		return FALSE;

	const DWORD tNow = GetTickCount();

	switch ( m_nState )
	{
	case upsReady:
	case upsRequest:
		if ( tNow > m_tRequest + Settings.Connection.TimeoutHandshake )
		{
			Close( IDS_UPLOAD_REQUEST_TIMEOUT );
			return FALSE;
		}
		break;

	case upsQueued:
		if ( tNow > m_tRequest + Settings.DC.DequeueTime )
		{
			Close( IDS_UPLOAD_QUEUE_TIMEOUT );
			return FALSE;
		}
		if ( tNow > m_tRankingCheck + 5 * 1000 )	// Re-check every 5 seconds
			return CheckRanking();
		break;

	case upsUploading:
	case upsResponse:
	case upsBrowse:
	case upsTigerTree:
		if ( tNow > m_mOutput.tLast + Settings.Connection.TimeoutTraffic )
		{
			Close( IDS_UPLOAD_TRAFFIC_TIMEOUT );
			return FALSE;
		}
		break;

	//default:
	//	;
	}

	return TRUE;
}
void CUploadTransferED2K::OnQueueKick()
{
	m_nRanking = -1;
	
	if ( m_nState == upsRequest || m_nState == upsUploading )
	{
		if ( UploadQueues.GetPosition( this, TRUE ) == 0 ) return;
		
		if ( m_pBaseFile != NULL && m_pClient->IsOnline() )
		{
			Send( CEDPacket::New( ED2K_C2C_FINISHUPLOAD ) );
		}
		
		Cleanup( FALSE );
	}
	else
	{
		CheckRanking();
	}
}
BOOL CUploadTransferED2K::OnRunEx(DWORD tNow)
{
	// Limit per-source packet rate
	if ( tNow - m_tLastRun < Settings.eDonkey.SourceThrottle ) return FALSE;
	m_tLastRun = tNow;


	if ( m_nState == upsQueued )
	{
		if ( m_pClient->IsOnline() == FALSE && tNow > m_tRequest &&
			 tNow - m_tRequest >= Settings.eDonkey.DequeueTime * 1000 )
		{
			theApp.Message( MSG_ERROR, IDS_UPLOAD_QUEUE_TIMEOUT, (LPCTSTR)m_sAddress );
			Close();
			return FALSE;
		}
		else 
		{
			DWORD nCheckThrottle;	// Throttle for how often ED2K clients have queue rank checked
			if ( m_nRanking <= 2 ) nCheckThrottle = 2 * 1000;
			else if ( m_nRanking < 10 ) nCheckThrottle = 15 * 1000;
			else if ( m_nRanking < 50 ) nCheckThrottle = 1 * 60 * 1000;
			else if ( m_nRanking < 200 ) nCheckThrottle = 4 * 60 * 1000;
			else nCheckThrottle = 8 * 60 * 1000;

			if ( tNow > m_tRankingCheck && tNow - m_tRankingCheck >= nCheckThrottle )	
			{	
				// Check the queue rank. Start upload or send rank update if required.
				if ( ! CheckRanking() ) return FALSE;
			}
		}
	}
	else if ( m_nState == upsUploading )
	{
		if ( ! ServeRequests() ) return FALSE;
		
		if ( tNow > m_pClient->m_mOutput.tLast &&
			 tNow - m_pClient->m_mOutput.tLast > Settings.Connection.TimeoutTraffic * 3 )
		{
			theApp.Message( MSG_ERROR, IDS_UPLOAD_TRAFFIC_TIMEOUT, (LPCTSTR)m_sAddress );
			Close();
			return FALSE;
		}
	}
	else if ( m_nState == upsReady || m_nState == upsRequest )
	{
		if ( tNow > m_tRequest && tNow - m_tRequest > Settings.Connection.TimeoutHandshake )
		{
			theApp.Message( MSG_ERROR, IDS_UPLOAD_REQUEST_TIMEOUT, (LPCTSTR)m_sAddress );
			Close();
			return FALSE;
		}
	}
	else if ( m_nState == upsConnecting )
	{
		if ( tNow > m_tRequest && tNow - m_tRequest > Settings.Connection.TimeoutConnect + Settings.Connection.TimeoutHandshake + 10000 )
		{
			Close( TRUE );
			return FALSE;
		}
	}
	
	return CUploadTransfer::OnRun();
}