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; }
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; }
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; }
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; }