BOOL CDownloadTransferED2K::OnFileReqAnswer(CEDPacket* /*pPacket*/)
{
	if ( m_pDownload->m_nSize <= ED2K_PART_SIZE )
	{
		delete [] m_pAvailable;
		m_pAvailable = new BYTE[ 1 ];
		m_pAvailable[ 0 ] = TRUE;
		m_pSource->m_oAvailable.insert( m_pSource->m_oAvailable.end(), Fragments::Fragment( 0, m_pDownload->m_nSize ) );
		SendSecondaryRequest();
	}
	// Not really interested
	return TRUE;
}
BOOL CDownloadTransferED2K::OnHashsetAnswer(CEDPacket* pPacket)
{
	if ( m_nState != dtsHashset ) return TRUE;
	
    if ( pPacket->GetRemaining() < Hashes::Ed2kHash::byteCount + 2 )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		Close( TRI_FALSE );
		return FALSE;
	}

    Hashes::Ed2kHash oED2K;
	pPacket->Read( oED2K );
	
	if ( validAndUnequal( oED2K, m_pDownload->m_oED2K ) )
	{
		return TRUE;	// Hack
//		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_ERROR, (LPCTSTR)m_sAddress );
//		Close( TRI_FALSE );
//		return FALSE;
	}
	
	m_bHashset = TRUE;
	
	DWORD nBlocks = pPacket->ReadShortLE();
	bool bNullBlock = ( m_pDownload->m_nSize % ED2K_PART_SIZE == 0 && m_pDownload->m_nSize );
	QWORD nBlocksFromSize = ( m_pDownload->m_nSize + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE;

	if ( bNullBlock )
		nBlocksFromSize++;
	
	if ( nBlocks == 0 ) nBlocks = 1;
	
	if ( nBlocks != nBlocksFromSize )
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_ERROR, (LPCTSTR)m_sAddress );
	}
	else if ( m_pDownload->SetHashset(	pPacket->m_pBuffer + pPacket->m_nPosition,
										pPacket->GetRemaining() ) )
	{
		return SendSecondaryRequest();
	}
	
	Close( TRI_FALSE );
	return FALSE;
}
BOOL CDownloadTransferED2K::OnFileStatus(CEDPacket* pPacket)
{
	if ( m_nState <= dtsConnecting )
		return TRUE;

	if ( pPacket->GetRemaining() < Hashes::Ed2kHash::byteCount + 2 )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		Close( TRI_FALSE );
		return FALSE;
	}

	Hashes::Ed2kHash oED2K;
	pPacket->Read( oED2K );

	if ( validAndUnequal( oED2K, m_pDownload->m_oED2K ) )
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH, (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
		return TRUE;
	}

	DWORD nBlocks = pPacket->ReadShortLE();

	if ( nBlocks == (DWORD)( ( m_pDownload->m_nSize + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE ) )
	{
		m_pSource->m_oAvailable.clear();

		delete [] m_pAvailable;
		m_pAvailable = new BYTE[ nBlocks ];
		ZeroMemory( m_pAvailable, nBlocks );

		for ( DWORD nBlock = 0 ; nBlock < nBlocks && pPacket->GetRemaining() ; )
		{
			BYTE nByte = pPacket->ReadByte();

			for ( int nBit = 0 ; nBit < 8 && nBlock < nBlocks ; nBit++, nBlock++ )
			{
				if ( nByte & ( 1 << nBit ) )
				{
					QWORD nFrom = ED2K_PART_SIZE * nBlock;
					QWORD nTo = nFrom + ED2K_PART_SIZE;
					nTo = min( nTo, m_pDownload->m_nSize );

					m_pSource->m_oAvailable.insert( m_pSource->m_oAvailable.end(), Fragments::Fragment( nFrom, nTo ) );
					m_pAvailable[ nBlock ] = TRUE;
				}
			}
		}
	}
	else if ( nBlocks == 0 )
	{
		m_pSource->m_oAvailable.clear();

		delete [] m_pAvailable;
		m_pAvailable = NULL;
	}
	else
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		Close( TRI_FALSE );
		return FALSE;
	}

	SendSecondaryRequest();

	return TRUE;
}