void CUploadTransferED2K::Close(BOOL bMessage)
{
	if ( m_nState == upsNull )
	{
		if ( m_pClient != NULL ) m_pClient->OnUploadClose();
		m_pClient = NULL;
		return;
	}
	
	if ( m_pBaseFile != NULL && m_pClient->IsOnline() )
	{
		if ( m_nState == upsUploading || m_nState == upsQueued )
		{
			Send( CEDPacket::New( ED2K_C2C_FINISHUPLOAD ) );
		}
		
		CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_FILENOTFOUND );
		pPacket->Write( &m_pED2K, sizeof(MD4) );
		Send( pPacket );
	}
	
	Cleanup();
	
	ASSERT( m_pClient != NULL );
	m_pClient->OnUploadClose();
	m_pClient = NULL;
	
	CUploadTransfer::Close( bMessage );
}
BOOL CUploadTransferED2K::OpenFile()
{
	ASSERT( m_nState == upsRequest || m_nState == upsUploading );
	ASSERT( m_pBaseFile != NULL );
	
	if ( m_pDiskFile != NULL ) return TRUE;
	m_pDiskFile = TransferFiles.Open( m_sFilePath, FALSE, FALSE );
	
	if ( m_pDiskFile != NULL )
	{
		CQuickLock oLock( Library.m_pSection );
		if ( CLibraryFile* pFile = LibraryMaps.LookupFileByPath( m_sFilePath, TRUE, TRUE ) )
		{
			pFile->m_nUploadsToday++;
			pFile->m_nUploadsTotal++;
		}
		
		return TRUE;
	}
	
	theApp.Message( MSG_ERROR, IDS_UPLOAD_CANTOPEN, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );	
	
	CEDPacket* pReply = CEDPacket::New( ED2K_C2C_FILENOTFOUND );
	pReply->Write( &m_pED2K, sizeof(MD4) );
	Send( pReply );
	
	Cleanup();
	Close();
	
	return FALSE;
}
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 CDownloadTransferED2K::SendPrimaryRequest()
{
	ASSERT( m_pClient != NULL );
	const DWORD tNow = GetTickCount();

	//if ( m_pDownload->GetVolumeRemaining() == 0 )
	//{
	//	theApp.Message( MSG_INFO, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
	//	Close( TRI_TRUE );
	//	return FALSE;
	//}

	// This source is current requesting
	SetState( dtsRequesting );

	// Set the 'last requested' time
	m_tRequest = tNow;

	ClearRequests();

	// Send ed2k file request
	CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_FILEREQUEST );
	pPacket->Write( m_pDownload->m_oED2K );

	if ( Settings.eDonkey.ExtendedRequest >= 1 && m_pClient->m_bEmRequest >= 1 )
		m_pClient->WritePartStatus( pPacket, m_pDownload );

	// It's not very accurate
	if ( Settings.eDonkey.ExtendedRequest >= 2 && m_pClient->m_bEmRequest >= 2 )
		pPacket->WriteShortLE( (WORD)m_pDownload->GetED2KCompleteSourceCount() );

	Send( pPacket );

	if ( m_pDownload->m_nSize <= ED2K_PART_SIZE )
	{
		// Don't ask for status - if the client answers, we know the file is complete anyway
	}
	else
	{
		// Send ed2k status request
		pPacket = CEDPacket::New( ED2K_C2C_FILESTATUSREQUEST );
		pPacket->Write( m_pDownload->m_oED2K );
		Send( pPacket );
	}

	if ( m_pDownload->GetSourceCount() < Settings.Downloads.SourcesWanted &&	// We want more sources
		 tNow > m_tSources && tNow > m_tSources + 30 * 60 * 1000 &&				// We have not asked for at least 30 minutes
		 m_pClient->m_bEmule && Network.IsListening() )							// Remote client is eMule compatible and we are accepting packets
	{
		// Set 'last asked for sources' time
		m_tSources = tNow;
		// Send ed2k request for sources packet
		pPacket = CEDPacket::New( ED2K_C2C_REQUESTSOURCES, ED2K_PROTOCOL_EMULE );
		pPacket->Write( m_pDownload->m_oED2K );
		Send( pPacket );
	}

	return TRUE;
}
Example #5
0
// Send a server status request
void CEDClients::RequestServerStatus(IN_ADDR* pHost, WORD nPort)
{
	CEDPacket* pPacket = CEDPacket::New( ED2K_C2SG_SERVERSTATUSREQUEST, ED2K_PROTOCOL_EDONKEY );

	m_nLastServerKey = 0x55AA0000 + GetRandomNum( 0ui16, _UI16_MAX );
	pPacket->WriteLongLE( m_nLastServerKey );
	Datagrams.Send( pHost, nPort + 4, pPacket );
}
Example #6
0
// Send a server status request
void CEDClients::RequestServerStatus(IN_ADDR* pHost, WORD nPort)
{
	CEDPacket* pPacket = CEDPacket::New( ED2K_C2SG_SERVERSTATUSREQUEST, ED2K_PROTOCOL_EDONKEY );

	srand( GetTickCount() );
	m_nLastServerKey = 0x55AA0000 + rand();
	pPacket->WriteLongLE( m_nLastServerKey );
	Datagrams.Send( pHost, nPort + 4, pPacket );
}
Example #7
0
CEDPacket* CEDPacket::ReadBuffer(CBuffer* pBuffer, BYTE nEdProtocol)
{
	ED2K_TCP_HEADER* pHeader = reinterpret_cast<ED2K_TCP_HEADER*>(pBuffer->m_pBuffer);
	if ( pBuffer->m_nLength < sizeof(*pHeader) ) return NULL;
	if ( pHeader->nProtocol != ED2K_PROTOCOL_EDONKEY &&
		 pHeader->nProtocol != ED2K_PROTOCOL_EMULE &&
		 pHeader->nProtocol != ED2K_PROTOCOL_PACKED ) return NULL;
	if ( pBuffer->m_nLength < sizeof(*pHeader) + pHeader->nLength - 1 ) return NULL;
	CEDPacket* pPacket = CEDPacket::New( pHeader );
	pBuffer->Remove( sizeof(*pHeader) + pHeader->nLength - 1 );
	if ( pPacket->InflateOrRelease( nEdProtocol ) ) return NULL;
	return pPacket;
}
BOOL CUploadTransferED2K::OnReask()
{
	if ( m_nState != upsQueued ) return FALSE;
	
	int nPosition = UploadQueues.GetPosition( this, TRUE );
	if ( nPosition < 0 ) return FALSE;
	
	CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_UDP_REASKACK, ED2K_PROTOCOL_EMULE );
	pPacket->WriteShortLE( nPosition );
	Datagrams.Send( &m_pClient->m_pHost.sin_addr, m_pClient->m_nUDP, pPacket );
	
	m_tRequest = GetTickCount();
	
	return TRUE;
}
BOOL CDownloadTransferED2K::RunQueued(DWORD tNow)
{
	ASSERT( m_pClient != NULL );
	ASSERT( m_nState == dtsQueued );
	
	if ( Settings.Downloads.QueueLimit > 0 && m_nQueuePos > Settings.Downloads.QueueLimit )
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUE_HUGE,
			(LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName(), m_nQueuePos );
		Close( TRI_FALSE );
		return FALSE;
	}
	else if ( m_pClient->m_bConnected == FALSE && tNow > m_tRanking && tNow - m_tRanking > Settings.eDonkey.ReAskTime * 1000 + 20000 )
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUE_TIMEOUT,
			(LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
		Close( TRI_UNKNOWN );
		return FALSE;
	}
	else if ( !( CEDPacket::IsLowID( m_pSource->m_pAddress.S_un.S_addr ) || m_pSource->m_bPushOnly ) &&
				/*!Network.IsFirewalled(CHECK_BOTH)*/!Network.IsFirewalled(CHECK_UDP) && m_pClient->m_nUDP > 0 && ! m_bUDP && tNow > m_tRequest && // Temp disable
				tNow - m_tRequest > Settings.eDonkey.ReAskTime * 1000 - 20000 )
	{
		CEDPacket* pPing = CEDPacket::New( ED2K_C2C_UDP_REASKFILEPING, ED2K_PROTOCOL_EMULE );
		pPing->Write( m_pDownload->m_oED2K );
		Datagrams.Send( &m_pClient->m_pHost.sin_addr, m_pClient->m_nUDP, pPing );
		m_bUDP = TRUE;
		//m_tRequest = GetTickCount();
	}
	else if ( tNow > m_tRequest && tNow - m_tRequest > Settings.eDonkey.ReAskTime * 1000 )
	{
		m_tRequest = GetTickCount();
		
		if ( m_pClient->IsOnline() )
		{
			return OnConnected();
		}
		else
		{
			m_pClient->Connect();
		}
	}
	
	return TRUE;
}
BOOL CDownloadTransferED2K::SendSecondaryRequest()
{
	ASSERT( m_pClient != NULL );
	ASSERT( m_nState > dtsConnecting );
	// ASSERT( m_nState == dtsRequesting || m_nState == dtsHashset );

	if ( ! m_pDownload->PrepareFile() )
	{
		Close( TRI_TRUE );
		return FALSE;
	}

	if ( m_bHashset == FALSE && m_pDownload->NeedHashset() )
	{
		CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_HASHSETREQUEST );
		pPacket->Write( m_pDownload->m_oED2K );
		Send( pPacket );

		SetState( dtsHashset );
		m_pClient->m_mInput.tLast = GetTickCount();
	}
	else if ( m_pSource->HasUsefulRanges() )
	{
		CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_QUEUEREQUEST );
		pPacket->Write( m_pDownload->m_oED2K );
		Send( pPacket );

		SetState( dtsEnqueue );
		m_tRequest = GetTickCount();
	}
	else
	{
		m_pSource->m_tAttempt = GetTickCount() + Settings.eDonkey.ReAskTime * 500;
		m_pSource->SetAvailableRanges( NULL );
		theApp.Message( MSG_INFO, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
		Close( TRI_TRUE );
		return FALSE;
	}

	ClearRequests();

	return TRUE;
}
BOOL CUploadTransferED2K::CheckRanking()
{
	DWORD tNow = GetTickCount();
	int nPosition = UploadQueues.GetPosition( this, TRUE );
	
	if ( nPosition < 0 )
	{	
		// Invalid queue position, or queue deleted. Drop client and exit.
		Cleanup();
		Close( TRUE );
		return FALSE;
	}
	
	// Update 'ranking checked' timer
	m_tRankingCheck = tNow;

	// If queue ranking hasn't changed, don't bother sending an update
	// Note: if a rank was requested by the remote client, then m_nRanking will be set to -1.
	if ( m_nRanking == nPosition ) return TRUE;	

	
	if ( nPosition == 0 )
	{	
		//Ready to start uploading

		if ( m_pClient->IsOnline() )
		{
			if ( m_nState != upsUploading )
			{
				m_nState = upsRequest;
				Send( CEDPacket::New( ED2K_C2C_STARTUPLOAD ) );
			}
		}
		else
		{
			m_nState = upsConnecting;
			m_pClient->Connect();
		}

		// Update the 'request sent' timer
		m_tRequest = m_tRankingCheck;

		// Update the 'ranking sent' variables
		m_nRanking = nPosition;
		m_tRankingSent = tNow;
	}
	else if ( m_pClient->IsOnline() )
	{	
		//Upload is queued

		// Check if we should send a ranking packet- If we have not sent one in a while, or one was requested
		if ( ( tNow > m_tRankingSent && tNow - m_tRankingSent >= Settings.eDonkey.QueueRankThrottle ) ||
			 (  m_nRanking == -1 ) )
			 
		{
			// Send a queue rank packet
			CSingleLock pLock( &UploadQueues.m_pSection, TRUE );
			
			if ( UploadQueues.Check( m_pQueue ) )
			{
				theApp.Message( MSG_DEFAULT, IDS_UPLOAD_QUEUED, (LPCTSTR)m_sFileName,
					(LPCTSTR)m_sAddress, nPosition, m_pQueue->GetQueuedCount(),
					(LPCTSTR)m_pQueue->m_sName );
			}
			
			pLock.Unlock();
			
			m_nState = upsQueued;
			
			if ( m_pClient->m_bEmule )
			{	//eMule queue ranking
				CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_QUEUERANKING, ED2K_PROTOCOL_EMULE );
				pPacket->WriteShortLE( nPosition );
				pPacket->WriteShortLE( 0 );
				pPacket->WriteLongLE( 0 );
				pPacket->WriteLongLE( 0 );
				Send( pPacket );
			}
			else
			{	//older eDonkey style
				CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_QUEUERANK );
				pPacket->WriteLongLE( nPosition );
				Send( pPacket );
			}

			// Update the 'ranking sent' variables
			m_nRanking = nPosition;
			m_tRankingSent = tNow;
		}
	}
	
	return TRUE;
}
BOOL CUploadTransferED2K::DispatchNextChunk()
{
	ASSERT( m_nState == upsUploading );
	if ( !m_pDiskFile ) return FALSE;
	ASSERT( m_nLength < SIZE_UNKNOWN );
	ASSERT( m_nPosition < m_nLength );
	
	QWORD nChunk = m_nLength - m_nPosition;
	nChunk = min( nChunk, QWORD(Settings.eDonkey.FrameSize) );
	
#if 0
	// Use packet form
	
	CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_SENDINGPART );
	pPacket->Write( &m_pED2K, sizeof(MD4) );
	pPacket->WriteLongLE( m_nOffset + m_nPosition );
	pPacket->WriteLongLE( m_nOffset + m_nPosition + nChunk );
	
	m_pDiskFile->Read( m_nFileBase + m_nOffset + m_nPosition, pPacket->GetWritePointer( nChunk ), nChunk, &nChunk );
	// SetFilePointer( hFile, m_nFileBase + m_nOffset + m_nPosition, NULL, FILE_BEGIN );
	// ReadFile( hFile, pPacket->WriteGetPointer( nChunk ), nChunk, &nChunk, NULL );
	
	if ( nChunk == 0 )
	{
		pPacket->Release();
		return FALSE;
	}
	
	pPacket->m_nLength = sizeof(MD4) + 8 + nChunk;
	
	Send( pPacket );
	
#else
	// Raw write
	
	CBuffer* pBuffer = m_pClient->m_pOutput;
	pBuffer->EnsureBuffer( sizeof(ED2K_PART_HEADER) + (DWORD)nChunk );
	
	ED2K_PART_HEADER* pHeader = (ED2K_PART_HEADER*)( pBuffer->m_pBuffer + pBuffer->m_nLength );
	
	if ( ! m_pDiskFile->Read( m_nFileBase + m_nOffset + m_nPosition, &pHeader[1], nChunk, &nChunk ) ) return FALSE;
	// SetFilePointer( hFile, m_nFileBase + m_nOffset + m_nPosition, NULL, FILE_BEGIN );
	// ReadFile( hFile, &pHeader[1], nChunk, &nChunk, NULL );
	if ( nChunk == 0 ) return FALSE;
	
	pHeader->nProtocol	= ED2K_PROTOCOL_EDONKEY;
	pHeader->nType		= ED2K_C2C_SENDINGPART;
	pHeader->nLength	= 1 + sizeof(MD4) + 8 + (DWORD)nChunk;
	pHeader->pMD4		= m_pED2K;
	pHeader->nOffset1	= (DWORD)( m_nOffset + m_nPosition );
	pHeader->nOffset2	= (DWORD)( m_nOffset + m_nPosition + nChunk );
	
	pBuffer->m_nLength += sizeof(ED2K_PART_HEADER) + (DWORD)nChunk;
	m_pClient->Send( NULL );
	
#endif
	
	m_nPosition += nChunk;
	m_nUploaded += nChunk;
	Statistics.Current.Uploads.Volume += ( nChunk / 1024 );
	
	return TRUE;
}
bool CDownloadTransferED2K::SendFragmentRequests()
{
	ASSUME_LOCK( Transfers.m_pSection );

	ASSERT( m_pClient != NULL );

	if ( m_nState != dtsDownloading ) return TRUE;

	if ( m_oRequested.size() >= (int)Settings.eDonkey.RequestPipe ) return TRUE;

	Fragments::List oPossible( m_pDownload->GetEmptyFragmentList() );

	if ( ! m_pClient->m_bEmLargeFile && ( m_pDownload->m_nSize & 0xffffffff00000000 ) )
	{
		Fragments::Fragment Selected( 0x100000000, m_pDownload->m_nSize - 1 );
		oPossible.erase( Selected );
	}

	if ( ! m_pDownload->m_bTorrentEndgame )
	{
		for ( CDownloadTransfer* pTransfer = m_pDownload->GetFirstTransfer() ;
			pTransfer && ! oPossible.empty() ; pTransfer = pTransfer->m_pDlNext )
		{
			pTransfer->SubtractRequested( oPossible );
		}
	}

	typedef std::map< QWORD, Fragments::Fragment > _TRequest;
	typedef _TRequest::iterator _TRequestIndex;
	_TRequest oRequesting;
	while ( m_oRequested.size() < (int)Settings.eDonkey.RequestPipe )
	{
		QWORD nOffset, nLength;

		if ( SelectFragment( oPossible, nOffset, nLength, m_pDownload->m_bTorrentEndgame ) )
		{
			ChunkifyRequest( &nOffset, &nLength, Settings.eDonkey.RequestSize, FALSE );

			Fragments::Fragment Selected( nOffset, nOffset + nLength );
			oPossible.erase( Selected );

			m_oRequested.push_back( Selected );

			oRequesting.insert( _TRequest::value_type(nOffset, Selected) );
		}
		else
		{
			break;
		}
	}

	while ( ! oRequesting.empty() )
	{
		DWORD nCount = 0;
		QWORD nOffsetBegin[3] = {0,0,0}, nOffsetEnd[3] = {0,0,0};
		bool  bI64Offset = false;

		while ( nCount < 3 && ! oRequesting.empty() )
		{
			_TRequestIndex iIndex = oRequesting.begin();
			nOffsetBegin[nCount] = QWORD((*iIndex).second.begin());
			nOffsetEnd[nCount] = QWORD((*iIndex).second.end());
			bI64Offset |= ( ( ( nOffsetBegin[nCount] & 0xffffffff00000000 ) ) ||
							( ( nOffsetEnd[nCount] & 0xffffffff00000000 ) ) );
			oRequesting.erase(iIndex);
			nCount++;
		}

		if ( bI64Offset )
		{
			CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_REQUESTPARTS, ED2K_PROTOCOL_EMULE );
			pPacket->Write( m_pDownload->m_oED2K );

			// This commented-out code is for BigEndian, only needed when ported to different platform.
			//pPacket->WriteLongLE( (DWORD)( nOffsetBegin[0] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( ( nOffsetBegin[0] & 0xffffffff00000000 ) >> 32 ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetBegin[1] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( ( nOffsetBegin[1] & 0xffffffff00000000 ) >> 32 ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetBegin[2] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( ( nOffsetBegin[2] & 0xffffffff00000000 ) >> 32 ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetEnd[0] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( ( nOffsetEnd[0] & 0xffffffff00000000 ) >> 32 ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetEnd[1] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( ( nOffsetEnd[1] & 0xffffffff00000000 ) >> 32 ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetEnd[2] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( ( nOffsetEnd[2] & 0xffffffff00000000 ) >> 32 ) );

			// If little Endian, no need to use above code
			pPacket->Write( &nOffsetBegin[0], 8 );
			pPacket->Write( &nOffsetBegin[1], 8 );
			pPacket->Write( &nOffsetBegin[2], 8 );
			pPacket->Write( &nOffsetEnd[0], 8 );
			pPacket->Write( &nOffsetEnd[1], 8 );
			pPacket->Write( &nOffsetEnd[2], 8 );
			Send( pPacket );
		}
		else
		{
			CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_REQUESTPARTS );
			pPacket->Write( m_pDownload->m_oED2K );

			// This commented-out code is for BigEndian, only needed when ported to different platform.
			//pPacket->WriteLongLE( (DWORD)( nOffsetBegin[0] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetBegin[1] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetBegin[2] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetEnd[0] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetEnd[1] & 0x00000000ffffffff ) );
			//pPacket->WriteLongLE( (DWORD)( nOffsetEnd[2] & 0x00000000ffffffff ) );

			pPacket->Write( &nOffsetBegin[0], 4 );
			pPacket->Write( &nOffsetBegin[1], 4 );
			pPacket->Write( &nOffsetBegin[2], 4 );
			pPacket->Write( &nOffsetEnd[0], 4 );
			pPacket->Write( &nOffsetEnd[1], 4 );
			pPacket->Write( &nOffsetEnd[2], 4 );
			Send( pPacket );
		}

		while ( nCount-- )
		{
			int nType = ( m_nDownloaded == 0 || ( nOffsetBegin[nCount] % ED2K_PART_SIZE ) == 0 )
				? MSG_INFO : MSG_DEBUG;

			theApp.Message( (WORD)nType, IDS_DOWNLOAD_FRAGMENT_REQUEST,
				nOffsetBegin[nCount], nOffsetEnd[nCount], (LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress );
		}
	}

	// If there are no more possible chunks to request, and endgame is available but not active
	if ( oPossible.empty() && Settings.eDonkey.Endgame && ! m_pDownload->m_bTorrentEndgame )
	{
		// And the file is at least 100MB, with less than 1MB to go
		if ( ( m_pDownload->GetVolumeComplete() > 100*1024*1024 ) &&
			 ( m_pDownload->GetVolumeRemaining() <  1*1024*1024 ) )
		{
			// Then activate endgame
			m_pDownload->m_bTorrentEndgame = true;
			theApp.Message( MSG_DEBUG, _T("Activating endgame for ed2k transfer %s"), m_pDownload->m_sName );
		}
	}

	if ( ! m_oRequested.empty() )
		return true;

	Send( CEDPacket::New( ED2K_C2C_QUEUERELEASE ) );

	theApp.Message( MSG_INFO, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
	Close( TRI_TRUE );

	return false;
}
Example #14
0
BOOL CDownloadTransferED2K::SendPrimaryRequest()
{
	ASSERT( m_pClient != NULL );
	DWORD tNow = GetTickCount();
	
	/*
	if ( m_pDownload->GetVolumeRemaining() == 0 )
	{
		theApp.Message( MSG_INFO, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
		Close( TRI_TRUE );
		return FALSE;
	}
	*/

	//This source is current requesting
	SetState( dtsRequesting );

	//Set the 'last requested' time
	m_tRequest	= tNow;		

	ClearRequests();
	
	//Send ed2k file request
	CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_FILEREQUEST );
	pPacket->Write( m_pDownload->m_oED2K );

	if ( Settings.eDonkey.ExtendedRequest >= 1 && m_pClient->m_bEmRequest >= 1 )
	{
		m_pClient->WritePartStatus( pPacket, m_pDownload );
	}

	//It's not very accurate
	if ( Settings.eDonkey.ExtendedRequest >= 2 && m_pClient->m_bEmRequest >= 2 ) 
	{
		pPacket->WriteShortLE( (WORD) m_pDownload->GetED2KCompleteSourceCount() );
	}

	Send( pPacket );
	
	if ( m_pDownload->m_nSize <= ED2K_PART_SIZE )
	{
		// Don't ask for status - if the client answers, we know the file is complete anyway
	}
	else
	{
		//Send ed2k status request
		pPacket = CEDPacket::New( ED2K_C2C_FILESTATUSREQUEST );
		pPacket->Write( m_pDownload->m_oED2K );
		Send( pPacket );
	}
	
	// TODO: Add new option "SourceExchangePeriod" (default: 10 minutes) like BitTorrent has
	if ( ( m_pDownload->GetSourceCount() < Settings.Downloads.SourcesWanted ) &&
		 ( tNow >= m_tSourceRequest + 10 * 60 * 1000 ) &&
		 m_pClient->m_bEmule )
	{
		// Set 'last asked for sources' time
		m_tSourceRequest = tNow;
		// Send ed2k request for sources packet
		pPacket = CEDPacket::New( ED2K_C2C_REQUESTSOURCES, ED2K_PROTOCOL_EMULE );
		pPacket->Write( m_pDownload->m_oED2K );
		Send( pPacket );
	}
	
	return TRUE;
}