Example #1
0
bool CUrlClient::SendHttpBlockRequests()
{
	USES_CONVERSION;
	m_dwLastBlockReceived = ::GetTickCount();
	if (reqfile == NULL)
		throw CString(_T("Failed to send block requests - No 'reqfile' attached"));

	CreateBlockRequests(PARTSIZE / EMBLOCKSIZE);
	if (m_PendingBlocks_list.IsEmpty()){
//==> Extended Failed/Success Statistic by NetF [shadow2004]
#ifdef FSSTATS
		SetDownloadState(DS_NONEEDEDPARTS, REASON_NoNeededParts);
#else
		SetDownloadState(DS_NONEEDEDPARTS);
#endif
//<== Extended Failed/Success Statistic by NetF [shadow2004]
        SwapToAnotherFile(_T("A4AF for NNP file. UrlClient::SendHttpBlockRequests()"), true, false, false, NULL, true, true);
		return false;
	}
	
	POSITION pos = m_PendingBlocks_list.GetHeadPosition();
	Pending_Block_Struct* pending = m_PendingBlocks_list.GetNext(pos);
	m_uReqStart = pending->block->StartOffset;
	m_uReqEnd = pending->block->EndOffset;
	bool bMergeBlocks = true;
	while (pos)
	{
		POSITION posLast = pos;
		pending = m_PendingBlocks_list.GetNext(pos);
		if (bMergeBlocks && pending->block->StartOffset == m_uReqEnd + 1)
			m_uReqEnd = pending->block->EndOffset;
		else
		{
			bMergeBlocks = false;
			reqfile->RemoveBlockFromList(pending->block->StartOffset, pending->block->EndOffset);
			delete pending->block;
			delete pending;
			m_PendingBlocks_list.RemoveAt(posLast);
		}
	}

	m_nUrlStartPos = m_uReqStart;

	CStringA strHttpRequest;
	strHttpRequest.AppendFormat("GET %s HTTP/1.0\r\n", m_strUrlPath);
	strHttpRequest.AppendFormat("Accept: */*\r\n");
	strHttpRequest.AppendFormat("Range: bytes=%u-%u\r\n", m_uReqStart, m_uReqEnd);
	strHttpRequest.AppendFormat("Connection: Keep-Alive\r\n");
	strHttpRequest.AppendFormat("Host: %s\r\n", T2CA(m_strHost));
	strHttpRequest.AppendFormat("\r\n");

	if (thePrefs.GetDebugClientTCPLevel() > 0)
		Debug(_T("Sending HTTP request:\n%hs"), strHttpRequest);
	CRawPacket* pHttpPacket = new CRawPacket(strHttpRequest);
	theStats.AddUpDataOverheadFileRequest(pHttpPacket->size);
	socket->SendPacket(pHttpPacket);
	STATIC_DOWNCAST(CHttpClientDownSocket, socket)->SetHttpState(HttpStateRecvExpected);
	return true;
}
Example #2
0
bool CUpDownClient::SendPeerCacheFileRequest()
{
	if (GetDownloadState() == DS_ONQUEUE){
		ASSERT( m_ePeerCacheDownState == PCDS_NONE );
		ASSERT( m_pPCDownSocket == NULL );
	}
	else if (GetDownloadState() == DS_DOWNLOADING){
		ASSERT( m_ePeerCacheDownState == PCDS_NONE );
		ASSERT( m_pPCDownSocket == NULL );
	}
	else{
		ASSERT(0);
	}

	if (!SupportPeerCache() || socket == NULL){
		ASSERT(0);
		return false;
	}

	m_uPeerCacheDownloadPushId = GetRandomUInt32();

	CSafeMemFile data(128);
	data.WriteUInt8(PCPCK_VERSION);
	data.WriteUInt8(PCOP_REQ);
	data.WriteUInt8(5);
	CTag tagCacheIP(PCTAG_CACHEIP, theApp.m_pPeerCache->GetCacheIP());
	tagCacheIP.WriteNewEd2kTag(&data);
	CTag tagPushId(PCTAG_PUSHID, m_uPeerCacheDownloadPushId);
	tagPushId.WriteNewEd2kTag(&data);
	CTag tagFileId(PCTAG_FILEID, (uchar*)reqfile->GetFileHash());
	tagFileId.WriteNewEd2kTag(&data);
	CTag tagPublicIP(PCTAG_PUBLICIP, theApp.GetPublicIP());
	tagPublicIP.WriteNewEd2kTag(&data);
	CTag tagCachePort(PCTAG_CACHEPORT, theApp.m_pPeerCache->GetCachePort());
	tagCachePort.WriteNewEd2kTag(&data);

	if (thePrefs.GetDebugClientTCPLevel() > 0){
		DebugSend("OP__PeerCacheQuery", this, reqfile->GetFileHash());
		Debug(_T("  CacheIP=%s  PushId=%u  PublicIP=%s  FileId=%s\n"), ipstr(tagCacheIP.GetInt()), tagPushId.GetInt(), ipstr(tagPublicIP.GetInt()), md4str(tagFileId.GetHash()));
	}

	Packet* pEd2kPacket = new Packet(&data, OP_EMULEPROT, OP_PEERCACHE_QUERY);
	theStats.AddUpDataOverheadFileRequest(pEd2kPacket->size);
	socket->SendPacket(pEd2kPacket);
	SetDownloadState(DS_DOWNLOADING);
	m_dwLastBlockReceived = ::GetTickCount();
	SetPeerCacheDownState(PCDS_WAIT_CLIENT_REPLY);
	return true;
}
nsresult
nsDownload::Cancel()
{
    // Don't cancel if download is already finished or canceled
    if (GetDownloadState() == FINISHED || GetDownloadState() == CANCELED)
        return NS_OK;

    nsresult rv = mCancelable->Cancel(NS_BINDING_ABORTED);
    if (NS_FAILED(rv))
        return rv;

    SetDownloadState(CANCELED);

    nsCAutoString path;
    rv = GetFilePathUTF8(mTarget, path);
    if (NS_FAILED(rv))
        return rv;
    mDownloadManager->DownloadEnded(path, nsnull);

    // Dump the temp file.  This should really be done when the transfer
    // is cancelled, but there are other cancellation causes that shouldn't
    // remove this. We need to improve those bits.
    if (mTempFile) {
        PRBool exists;
        mTempFile->Exists(&exists);
        if (exists)
            mTempFile->Remove(PR_FALSE);
    }

    // if there's a progress dialog open for the item,
    // we have to notify it that we're cancelling
    nsCOMPtr<nsIObserver> observer = do_QueryInterface(GetDialog());
    if (observer) {
        rv = observer->Observe(static_cast<nsIDownload*>(this), "oncancel", nsnull);
    }

    return rv;
}
Example #4
0
bool CUrlClient::ProcessHttpDownResponse(const CStringAArray& astrHeaders)
{
	if (reqfile == NULL)
		throw CString(_T("Failed to process received HTTP data block - No 'reqfile' attached"));
	if (astrHeaders.GetCount() == 0)
		throw CString(_T("Unexpected HTTP response - No headers available"));

	const CStringA& rstrHdr = astrHeaders.GetAt(0);
	UINT uHttpMajVer, uHttpMinVer, uHttpStatusCode;
	if (sscanf(rstrHdr, "HTTP/%u.%u %u", &uHttpMajVer, &uHttpMinVer, &uHttpStatusCode) != 3){
		CString strError;
		strError.Format(_T("Unexpected HTTP response: \"%hs\""), rstrHdr);
		throw strError;
	}
	if (uHttpMajVer != 1 || (uHttpMinVer != 0 && uHttpMinVer != 1)){
		CString strError;
		strError.Format(_T("Unexpected HTTP version: \"%hs\""), rstrHdr);
		throw strError;
	}
	bool bExpectData = uHttpStatusCode == HTTP_STATUS_OK || uHttpStatusCode == HTTP_STATUS_PARTIAL_CONTENT;
	bool bRedirection = uHttpStatusCode == HTTP_STATUS_MOVED || uHttpStatusCode == HTTP_STATUS_REDIRECT;
	if (!bExpectData && !bRedirection){
		CString strError;
		strError.Format(_T("Unexpected HTTP status code \"%u\""), uHttpStatusCode);
		throw strError;
	}

	bool bNewLocation = false;
	bool bValidContentRange = false;
	for (int i = 1; i < astrHeaders.GetCount(); i++)
	{
		const CStringA& rstrHdr = astrHeaders.GetAt(i);
		if (bExpectData && strnicmp(rstrHdr, "Content-Length:", 15) == 0)
		{
			UINT uContentLength = atoi((LPCSTR)rstrHdr + 15);
			if (uContentLength != m_uReqEnd - m_uReqStart + 1){
				if (uContentLength != reqfile->GetFileSize()){ // tolerate this case only
					CString strError;
					strError.Format(_T("Unexpected HTTP header field \"%hs\""), rstrHdr);
					throw strError;
				}
				TRACE("+++ Unexpected HTTP header field \"%s\"\n", rstrHdr);
			}
		}
		else if (bExpectData && strnicmp(rstrHdr, "Content-Range:", 14) == 0)
		{
			DWORD dwStart = 0, dwEnd = 0, dwLen = 0;
			if (sscanf((LPCSTR)rstrHdr + 14," bytes %u - %u / %u", &dwStart, &dwEnd, &dwLen) != 3){
				CString strError;
				strError.Format(_T("Unexpected HTTP header field \"%hs\""), rstrHdr);
				throw strError;
			}

			if (dwStart != m_uReqStart || dwEnd != m_uReqEnd || dwLen != reqfile->GetFileSize()){
				CString strError;
				strError.Format(_T("Unexpected HTTP header field \"%hs\""), rstrHdr);
				throw strError;
			}
			bValidContentRange = true;
		}
		else if (strnicmp(rstrHdr, "Server:", 7) == 0)
		{
			if (m_strClientSoftware.IsEmpty())
				m_strClientSoftware = rstrHdr.Mid(7).Trim();
		}
		else if (bRedirection && strnicmp(rstrHdr, "Location:", 9) == 0)
		{
			CString strLocation(rstrHdr.Mid(9).Trim());
			if (!SetUrl(strLocation)){
				CString strError;
				strError.Format(_T("Failed to process HTTP redirection URL \"%s\""), strLocation);
				throw strError;
			}
			bNewLocation = true;
		}
	}

	if (bNewLocation)
	{
		m_iRedirected++;
		if (m_iRedirected >= 3)
			throw CString(_T("Max. HTTP redirection count exceeded"));

		// the tricky part
		socket->Safe_Delete();		// mark our parent object for getting deleted!
		if (!TryToConnect(true))	// replace our parent object with a new one
			throw CString(_T("Failed to connect to redirected URL"));
		return false;				// tell our old parent object (which was marked as to get deleted 
									// and which is no longer attached to us) to disconnect.
	}

	if (!bValidContentRange){
		if (thePrefs.GetDebugClientTCPLevel() <= 0)
			DebugHttpHeaders(astrHeaders);
		CString strError;
		strError.Format(_T("Unexpected HTTP response - No valid HTTP content range found"));
		throw strError;
	}

	SetDownloadState(DS_DOWNLOADING);
	return true;
}
Example #5
0
bool CUpDownClient::SendHttpBlockRequests()
{
	USES_CONVERSION;
	ASSERT( GetDownloadState() == DS_DOWNLOADING );
	ASSERT( m_ePeerCacheDownState == PCDS_WAIT_CLIENT_REPLY || m_ePeerCacheDownState == PCDS_DOWNLOADING );

	m_bPeerCacheDownHit = false;
	m_dwLastBlockReceived = ::GetTickCount();
	if (reqfile == NULL)
		throw CString(_T("Failed to send block requests - No 'reqfile' attached"));

	CreateBlockRequests(1);
	if (m_PendingBlocks_list.IsEmpty()){
		if (m_pPCDownSocket != NULL){
			m_pPCDownSocket->Safe_Delete();
			ASSERT( m_pPCDownSocket == NULL );
			SetPeerCacheDownState(PCDS_NONE);
		}
		SetDownloadState(DS_NONEEDEDPARTS);
        SwapToAnotherFile(_T("A4AF for NNP file. CUpDownClient::SendHttpBlockRequests()"), true, false, false, NULL, true, true);
		return false;
	}

	// PeerCache does not support persistant HTTP connections
	if (m_pPCDownSocket != NULL)
	{
		m_pPCDownSocket->Safe_Delete();
		ASSERT( m_pPCDownSocket == NULL );
		SetPeerCacheDownState(PCDS_NONE);
		return SendPeerCacheFileRequest();
	}

	ASSERT( m_pPCDownSocket == NULL );
	m_pPCDownSocket = new CPeerCacheDownSocket(this);
	m_pPCDownSocket->SetTimeOut(GetPeerCacheSocketDownloadTimeout());
	if (!m_pPCDownSocket->Create()){
		m_pPCDownSocket->Safe_Delete();
		ASSERT( m_pPCDownSocket == NULL );
		return false;
	}

	ASSERT( !m_pPCDownSocket->IsConnected() );
	SOCKADDR_IN sockAddr = {0};
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_port = htons( theApp.m_pPeerCache->GetCachePort() );
	sockAddr.sin_addr.S_un.S_addr = theApp.m_pPeerCache->GetCacheIP();
	//Try to always tell the socket to WaitForOnConnect before you call Connect.
	m_pPCDownSocket->WaitForOnConnect();
	m_pPCDownSocket->Connect((SOCKADDR*)&sockAddr, sizeof sockAddr);

	POSITION pos = m_PendingBlocks_list.GetHeadPosition();
	Pending_Block_Struct* pending = m_PendingBlocks_list.GetNext(pos);
	ASSERT( pending->block->StartOffset <= pending->block->EndOffset );

	m_uReqStart = pending->block->StartOffset;
	m_uReqEnd = pending->block->EndOffset;
	m_nUrlStartPos = (uint64)-1;

	CStringA strPCRequest;
	strPCRequest.AppendFormat("GET http://%s/.ed2khash=%s HTTP/1.0\r\n", ipstrA(m_uPeerCacheRemoteIP), md4strA(reqfile->GetFileHash()));
	strPCRequest.AppendFormat("X-ED2K-PushId: %u\r\n", m_uPeerCacheDownloadPushId);
	strPCRequest.AppendFormat("Range: bytes=%I64u-%I64u\r\n", m_uReqStart, m_uReqEnd);
	strPCRequest.AppendFormat("User-Agent: eMule/%s\r\n", T2CA(theApp.m_strCurVersionLong));
	strPCRequest.AppendFormat("X-Network: eDonkey,Kademlia\r\n");
	strPCRequest.AppendFormat("\r\n");

	if (thePrefs.GetDebugClientTCPLevel() > 0){
		DebugSend("PeerCache-GET", this, reqfile->GetFileHash());
		Debug(_T("  %hs\n"), strPCRequest);
	}
	CRawPacket* pHttpPacket = new CRawPacket(strPCRequest);
	theStats.AddUpDataOverheadFileRequest(pHttpPacket->size);
	m_pPCDownSocket->SendPacket(pHttpPacket);
	m_pPCDownSocket->SetHttpState(HttpStateRecvExpected);
	SetPeerCacheDownState(PCDS_WAIT_CACHE_REPLY);
	return true;
}