From 8f66d1ac2bc2aaf49433385da2d063df901c151a Mon Sep 17 00:00:00 2001 From: "cbiesinger%web.de" Date: Wed, 16 Jun 2004 19:51:21 +0000 Subject: [PATCH] bug 243974 can't download files larger than 4 GB Also changes nsIResumableChannel to have a resumeAt function, that does not open the channel immediately, and changes its size parameter to a 64 bit integer r=darin sr=bryner git-svn-id: svn://10.0.0.236/trunk@157978 18797224-902f-48f8-a5cc-f745e15eee43 --- .../base/public/nsIResumableChannel.idl | 36 ++++++++------- .../base/public/nsIResumableEntityID.idl | 2 +- mozilla/netwerk/base/public/nsNetError.h | 10 +++- mozilla/netwerk/base/public/nsNetUtil.h | 2 +- .../netwerk/base/src/nsInputStreamPump.cpp | 17 ++++--- mozilla/netwerk/base/src/nsInputStreamPump.h | 5 +- .../netwerk/base/src/nsResumableEntityID.cpp | 14 +++--- .../netwerk/base/src/nsResumableEntityID.h | 2 +- .../netwerk/protocol/ftp/src/nsFTPChannel.cpp | 21 +++++++-- .../netwerk/protocol/ftp/src/nsFTPChannel.h | 3 ++ .../ftp/src/nsFtpConnectionThread.cpp | 18 ++++---- .../protocol/ftp/src/nsFtpConnectionThread.h | 2 +- .../protocol/ftp/src/nsFtpProtocolHandler.cpp | 1 - .../protocol/http/src/nsHttpChannel.cpp | 46 +++++++++++-------- .../netwerk/protocol/http/src/nsHttpChannel.h | 5 +- .../protocol/http/src/nsHttpResponseHead.cpp | 18 +++++--- .../protocol/http/src/nsHttpResponseHead.h | 10 ++-- .../protocol/http/src/nsHttpTransaction.cpp | 16 +++---- .../protocol/http/src/nsHttpTransaction.h | 5 +- .../converters/nsMultiMixedConv.cpp | 5 +- mozilla/netwerk/test/TestProtocols.cpp | 30 ++++++------ mozilla/xpcom/io/nsPipe3.cpp | 7 +-- 22 files changed, 159 insertions(+), 116 deletions(-) diff --git a/mozilla/netwerk/base/public/nsIResumableChannel.idl b/mozilla/netwerk/base/public/nsIResumableChannel.idl index 027cf51488f..3da479ef9f5 100644 --- a/mozilla/netwerk/base/public/nsIResumableChannel.idl +++ b/mozilla/netwerk/base/public/nsIResumableChannel.idl @@ -42,27 +42,29 @@ interface nsIResumableEntityID; [scriptable, uuid(87cccd68-1dd2-11b2-8b66-cbf10a1b6438)] interface nsIResumableChannel : nsISupports { /** - * Open this channel, and read starting at the specified offset. - * @param listener - As for asyncOpen - * @param ctxt - As for asyncOpen - * @param startPos - the starting offset, in bytes, to use to download - * @param info - information about the file, to match before obtaining - * the file. Pass null to use anything. - * OnStartRequest wil have a status of NS_ERROR_NOT_RESUMABLE if the file - * cannot be resumed, eg because the server doesn't support this, or the - * nsIFileInfo doesn't match. This error may be occur even if startPos - * is 0, so that the front end can warn the user. + * Prepare this channel for resuming. The request will not start until + * asyncOpen or open is called. Calling resumeAt after open or asyncOpen + * has been called has undefined behaviour. * - * The request given to the nsIStreamListener will be QIable to - * nsIResumableInfo + * @param startPos the starting offset, in bytes, to use to download + * @param entityID information about the file, to match before obtaining + * the file. Pass null to use anything. + * + * During OnStartRequest, this channel will have a status of + * NS_ERROR_NOT_RESUMABLE if the file cannot be resumed, eg because the + * server doesn't support this. This error may occur even if startPos + * is 0, so that the front end can warn the user. + * Similarly, the status of this channel during OnStartRequest may be + * NS_ERROR_ENTITY_CHANGED, which indicates that the entity has changed, + * as indicated by a changed entityID. + * In both of these cases, no OnDataAvailable will be called, and + * OnStopRequest will immediately follow with the same status code. */ - void asyncOpenAt(in nsIStreamListener listener, - in nsISupports ctxt, - in unsigned long startPos, - in nsIResumableEntityID entityID); + void resumeAt(in unsigned long long startPos, + in nsIResumableEntityID entityID); /** - * The nsIResumableEntityID for this uri. Available after OnStartRequest + * The nsIResumableEntityID for this URI. Available after OnStartRequest. * If this attribute is null, then this load is not resumable. */ readonly attribute nsIResumableEntityID entityID; diff --git a/mozilla/netwerk/base/public/nsIResumableEntityID.idl b/mozilla/netwerk/base/public/nsIResumableEntityID.idl index 5bfa704b188..84cc5f06016 100644 --- a/mozilla/netwerk/base/public/nsIResumableEntityID.idl +++ b/mozilla/netwerk/base/public/nsIResumableEntityID.idl @@ -46,7 +46,7 @@ interface nsIResumableEntityID : nsISupports { * Size of the entity. * @throw NS_ERROR_NOT_AVAILABLE if the size is not known. */ - attribute unsigned long size; + attribute unsigned long long size; /** * An opaque, but human-readable ASCII string specifying the date when the diff --git a/mozilla/netwerk/base/public/nsNetError.h b/mozilla/netwerk/base/public/nsNetError.h index 755f67e08b0..1987225442a 100644 --- a/mozilla/netwerk/base/public/nsNetError.h +++ b/mozilla/netwerk/base/public/nsNetError.h @@ -200,11 +200,19 @@ /** - * XXX document me + * This request is not resumable, but it was tried to resume it, or to + * request resume-specific data. */ #define NS_ERROR_NOT_RESUMABLE \ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 25) +/** + * It was attempted to resume the request, but the entity has changed in the + * meantime. + */ +#define NS_ERROR_ENTITY_CHANGED \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 32) + /** * The request failed as a result of a detected redirection loop. */ diff --git a/mozilla/netwerk/base/public/nsNetUtil.h b/mozilla/netwerk/base/public/nsNetUtil.h index f386c7507f0..311906c99de 100644 --- a/mozilla/netwerk/base/public/nsNetUtil.h +++ b/mozilla/netwerk/base/public/nsNetUtil.h @@ -618,7 +618,7 @@ NS_GetURLSpecFromFile(nsIFile *aFile, inline nsresult NS_NewResumableEntityID(nsIResumableEntityID **aRes, - PRUint32 size, + PRUint64 size, const nsACString &lastModified, const nsACString &entityTag) { diff --git a/mozilla/netwerk/base/src/nsInputStreamPump.cpp b/mozilla/netwerk/base/src/nsInputStreamPump.cpp index ded1c8c4480..853784dfca8 100644 --- a/mozilla/netwerk/base/src/nsInputStreamPump.cpp +++ b/mozilla/netwerk/base/src/nsInputStreamPump.cpp @@ -65,7 +65,7 @@ static PRLogModuleInfo *gStreamPumpLog = nsnull; nsInputStreamPump::nsInputStreamPump() : mState(STATE_IDLE) , mStreamOffset(0) - , mStreamLength(PR_UINT32_MAX) + , mStreamLength(LL_MaxInt()) , mStatus(NS_OK) , mSuspendCount(0) , mLoadFlags(LOAD_NORMAL) @@ -220,8 +220,9 @@ nsInputStreamPump::Init(nsIInputStream *stream, { NS_ENSURE_TRUE(mState == STATE_IDLE, NS_ERROR_IN_PROGRESS); - mStreamOffset = (PRUint32) streamPos; - mStreamLength = (PRUint32) streamLen; + mStreamOffset = streamPos; + if (streamLen >= 0) + mStreamLength = streamLen; mStream = stream; mSegSize = segsize; mSegCount = segcount; @@ -256,7 +257,7 @@ nsInputStreamPump::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) // stream case, the stream transport service will take care of seeking // for us. // - if (mAsyncStream && (mStreamOffset != PR_UINT32_MAX)) { + if (mAsyncStream && (mStreamOffset != nsInt64(-1))) { nsCOMPtr seekable = do_QueryInterface(mStream); if (seekable) seekable->Seek(nsISeekableStream::NS_SEEK_SET, mStreamOffset); @@ -406,7 +407,7 @@ nsInputStreamPump::OnStateTransfer() } else if (NS_SUCCEEDED(rv) && avail) { // figure out how much data to report (XXX detect overflow??) - if (avail + mStreamOffset > mStreamLength) + if (nsInt64(avail) + mStreamOffset > mStreamLength) avail = mStreamLength - mStreamOffset; if (avail) { @@ -430,7 +431,7 @@ nsInputStreamPump::OnStateTransfer() if (seekable) seekable->Tell(&offsetBefore); - LOG((" calling OnDataAvailable [offset=%u count=%u]\n", mStreamOffset, avail)); + LOG((" calling OnDataAvailable [offset=%lld count=%u]\n", PRInt64(mStreamOffset), avail)); rv = mListener->OnDataAvailable(this, mListenerContext, mAsyncStream, mStreamOffset, avail); // don't enter this code if ODA failed or called Cancel @@ -443,9 +444,7 @@ nsInputStreamPump::OnStateTransfer() nsInt64 offsetAfter64 = offsetAfter; if (offsetAfter64 > offsetBefore64) { nsInt64 offsetDelta = offsetAfter64 - offsetBefore64; - const nsInt64 maxUint32 = PR_UINT32_MAX; - NS_ASSERTION(offsetDelta < maxUint32, "offset overflows PRUint32"); - mStreamOffset += (PRUint32) offsetDelta; + mStreamOffset += offsetDelta; } else if (mSuspendCount == 0) { // diff --git a/mozilla/netwerk/base/src/nsInputStreamPump.h b/mozilla/netwerk/base/src/nsInputStreamPump.h index 8aa9fd73aa0..9530097b59d 100644 --- a/mozilla/netwerk/base/src/nsInputStreamPump.h +++ b/mozilla/netwerk/base/src/nsInputStreamPump.h @@ -48,6 +48,7 @@ #include "nsIAsyncInputStream.h" #include "nsIEventQueue.h" #include "nsCOMPtr.h" +#include "nsInt64.h" class nsInputStreamPump : public nsIInputStreamPump , public nsIInputStreamCallback @@ -82,8 +83,8 @@ protected: nsCOMPtr mEventQ; nsCOMPtr mStream; nsCOMPtr mAsyncStream; - PRUint32 mStreamOffset; - PRUint32 mStreamLength; + nsInt64 mStreamOffset; + nsInt64 mStreamLength; PRUint32 mSegSize; PRUint32 mSegCount; nsresult mStatus; diff --git a/mozilla/netwerk/base/src/nsResumableEntityID.cpp b/mozilla/netwerk/base/src/nsResumableEntityID.cpp index de7fe583b9f..640bc32a054 100644 --- a/mozilla/netwerk/base/src/nsResumableEntityID.cpp +++ b/mozilla/netwerk/base/src/nsResumableEntityID.cpp @@ -44,21 +44,21 @@ NS_IMPL_ISUPPORTS1(nsResumableEntityID, nsIResumableEntityID) nsResumableEntityID::nsResumableEntityID() : - mSize(PR_UINT32_MAX) { + mSize(LL_MaxUint()) { } nsResumableEntityID::~nsResumableEntityID() {} NS_IMETHODIMP -nsResumableEntityID::GetSize(PRUint32 *aSize) { - if (mSize == PR_UINT32_MAX) +nsResumableEntityID::GetSize(PRUint64 *aSize) { + if (LL_EQ(mSize, LL_MaxUint())) return NS_ERROR_NOT_AVAILABLE; *aSize = mSize; return NS_OK; } NS_IMETHODIMP -nsResumableEntityID::SetSize(PRUint32 aSize) { +nsResumableEntityID::SetSize(PRUint64 aSize) { mSize = aSize; return NS_OK; } @@ -89,13 +89,13 @@ nsResumableEntityID::GetEntityTag(nsACString& aTag) { NS_IMETHODIMP nsResumableEntityID::Equals(nsIResumableEntityID *other, PRBool *ret) { - PRUint32 size; + PRUint64 size; nsCAutoString lastMod; nsCAutoString entityTag; nsresult rv = other->GetSize(&size); if (NS_FAILED(rv)) - size = PR_UINT32_MAX; + size = LL_MaxUint(); rv = other->GetLastModified(lastMod); if (NS_FAILED(rv)) @@ -109,7 +109,7 @@ nsResumableEntityID::Equals(nsIResumableEntityID *other, PRBool *ret) { // exactly the same way for both of these entity IDs (same timezone, same // format, etc). *ret = mEntityTag.Equals(entityTag) && lastMod.Equals(mLastModified) && - (mSize == size); + LL_EQ(mSize, size); return NS_OK; } diff --git a/mozilla/netwerk/base/src/nsResumableEntityID.h b/mozilla/netwerk/base/src/nsResumableEntityID.h index d2bb3553005..b5caf9e46b7 100644 --- a/mozilla/netwerk/base/src/nsResumableEntityID.h +++ b/mozilla/netwerk/base/src/nsResumableEntityID.h @@ -46,7 +46,7 @@ public: ~nsResumableEntityID(); private: - PRUint32 mSize; + PRUint64 mSize; nsCString mLastModified; nsCString mEntityTag; }; diff --git a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp index 89a50f04e58..c280cc2b022 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp @@ -86,7 +86,8 @@ nsFTPChannel::nsFTPChannel() mFTPState(nsnull), mLock(nsnull), mStatus(NS_OK), - mCanceled(PR_FALSE) + mCanceled(PR_FALSE), + mStartPos(LL_MaxUint()) { } @@ -275,7 +276,19 @@ nsFTPChannel::GenerateCacheKey(nsACString &cacheKey) NS_IMETHODIMP nsFTPChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) { - return AsyncOpenAt(listener, ctxt, PRUint32(-1), nsnull); + nsresult rv = AsyncOpenAt(listener, ctxt, mStartPos, mEntityID); + // mEntityID no longer needed, clear it to avoid returning a wrong entity + // id when someone asks us + mEntityID = nsnull; + return rv; +} + +NS_IMETHODIMP +nsFTPChannel::ResumeAt(PRUint64 aStartPos, nsIResumableEntityID* aEntityID) +{ + mEntityID = aEntityID; + mStartPos = aStartPos; + return NS_OK; } NS_IMETHODIMP @@ -286,9 +299,9 @@ nsFTPChannel::GetEntityID(nsIResumableEntityID **entityID) return NS_OK; } -NS_IMETHODIMP +nsresult nsFTPChannel::AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt, - PRUint32 startPos, nsIResumableEntityID* entityID) + PRUint64 startPos, nsIResumableEntityID* entityID) { PRInt32 port; nsresult rv = mURL->GetPort(&port); diff --git a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h index fe5807f44c2..60327311614 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h @@ -111,6 +111,8 @@ public: nsresult SetupState(PRUint32 startPos, nsIResumableEntityID* entityID); nsresult GenerateCacheKey(nsACString &cacheKey); + nsresult AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt, + PRUint64 startPos, nsIResumableEntityID* entityID); protected: nsCOMPtr mOriginalURI; @@ -153,6 +155,7 @@ protected: nsCOMPtr mCacheEntry; nsCOMPtr mProxyInfo; nsCOMPtr mEntityID; + PRUint64 mStartPos; }; #endif /* nsFTPChannel_h___ */ diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp index 0f15c96eb96..338ffba195e 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp @@ -243,14 +243,12 @@ DataRequestForwarder::GetEntityID(nsIResumableEntityID* *aEntityID) } NS_IMETHODIMP -DataRequestForwarder::AsyncOpenAt(nsIStreamListener *, - nsISupports *, - unsigned int, - nsIResumableEntityID *) +DataRequestForwarder::ResumeAt(PRUint64, + nsIResumableEntityID *) { // We shouldn't get here. This class only exists in the middle of a // request - NS_NOTREACHED("DataRequestForwarder::AsyncOpenAt"); + NS_NOTREACHED("DataRequestForwarder::ResumeAt"); return NS_ERROR_NOT_IMPLEMENTED; } @@ -384,7 +382,7 @@ nsFtpState::nsFtpState() mControlConnection = nsnull; mDRequestForwarder = nsnull; - mFileSize = PRUint32(-1); + mFileSize = LL_MaxUint(); // make sure handler stays around NS_ADDREF(gFtpHandler); @@ -1330,8 +1328,10 @@ nsFtpState::S_size() { FTP_STATE nsFtpState::R_size() { if (mResponseCode/100 == 2) { - mFileSize = atoi(mResponseMsg.get()+4); - if (NS_FAILED(mChannel->SetContentLength(mFileSize))) return FTP_ERROR; + PR_sscanf(mResponseMsg.get() + 4, "%llu", &mFileSize); + PRUint32 size32; + LL_L2UI(size32, mFileSize); + if (NS_FAILED(mChannel->SetContentLength(size32))) return FTP_ERROR; } // We may want to be able to resume this @@ -1386,7 +1386,7 @@ nsFtpState::R_mdtm() { entEqual)) { return FTP_S_REST; } else { - mInternalError = NS_ERROR_NOT_RESUMABLE; + mInternalError = NS_ERROR_ENTITY_CHANGED; mResponseMsg.Truncate(); return FTP_ERROR; } diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h index 5794f632f58..25afc8b9fe0 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h @@ -194,7 +194,7 @@ private: nsCOMPtr mDPipe; // the data transport nsCOMPtr mDPipeRequest; DataRequestForwarder* mDRequestForwarder; - PRUint32 mFileSize; + PRUint64 mFileSize; nsCString mModTime; // ****** consumer vars diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp index d02247b4674..b02840969c1 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * diff --git a/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp b/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp index 1bada4f8662..fc6bb1966f4 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -68,6 +68,7 @@ #include "nsEscape.h" #include "nsICookieService.h" #include "nsIResumableChannel.h" +#include "nsInt64.h" static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID); @@ -99,7 +100,7 @@ nsHttpChannel::nsHttpChannel() , mPostID(0) , mRequestTime(0) , mAuthContinuationState(nsnull) - , mStartPos(0) + , mStartPos(LL_MaxUint()) , mRedirectionLimit(gHttpHandler->RedirectionLimit()) , mIsPending(PR_FALSE) , mApplyConversion(PR_TRUE) @@ -537,7 +538,7 @@ nsHttpChannel::SetupTransaction() if (mResuming) { char buf[32]; - PR_snprintf(buf, sizeof(buf), "bytes=%u-", mStartPos); + PR_snprintf(buf, sizeof(buf), "bytes=%llu-", mStartPos); mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(buf)); if (mEntityID) { @@ -760,7 +761,7 @@ nsHttpChannel::ProcessResponse() case 412: // Precondition failed case 416: // Invalid range if (mResuming) { - Cancel(NS_ERROR_NOT_RESUMABLE); + Cancel(NS_ERROR_ENTITY_CHANGED); rv = CallOnStartRequest(); break; } @@ -829,7 +830,7 @@ nsHttpChannel::ProcessNormal() PRBool equal; rv = mEntityID->Equals(id, &equal); if (NS_FAILED(rv) || !equal) - Cancel(NS_ERROR_NOT_RESUMABLE); + Cancel(NS_ERROR_ENTITY_CHANGED); } } @@ -1346,16 +1347,16 @@ nsHttpChannel::CheckCache() // of the cached content, then the cached response is partial... // either we need to issue a byte range request or we need to refetch the // entire document. - PRUint32 contentLength = (PRUint32) mCachedResponseHead->ContentLength(); - if (contentLength != PRUint32(-1)) { + nsInt64 contentLength = mCachedResponseHead->ContentLength(); + if (contentLength != nsInt64(-1)) { PRUint32 size; rv = mCacheEntry->GetDataSize(&size); if (NS_FAILED(rv)) return rv; - if (size != contentLength) { + if (nsInt64(size) != contentLength) { LOG(("Cached data size does not match the Content-Length header " - "[content-length=%u size=%u]\n", contentLength, size)); - if ((size < contentLength) && mCachedResponseHead->IsResumable()) { + "[content-length=%lld size=%u]\n", PRInt64(contentLength), size)); + if ((nsInt64(size) < contentLength) && mCachedResponseHead->IsResumable()) { // looks like a partial entry. rv = SetupByteRangeRequest(size); if (NS_FAILED(rv)) return rv; @@ -1820,6 +1821,16 @@ nsHttpChannel::SetupReplacementChannel(nsIURI *newURI, if (encodedChannel) encodedChannel->SetApplyConversion(mApplyConversion); + // transfer the resume information + if (mResuming) { + nsCOMPtr resumableChannel(do_QueryInterface(newChannel)); + if (!resumableChannel) { + NS_WARNING("Got asked to resume, but redirected to non-resumable channel!"); + return NS_ERROR_NOT_RESUMABLE; + } + resumableChannel->ResumeAt(mStartPos, mEntityID); + } + return NS_OK; } @@ -2950,7 +2961,8 @@ nsHttpChannel::GetContentLength(PRInt32 *value) if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE; - *value = mResponseHead->ContentLength(); + // XXX truncates to 32 bit + LL_L2I(*value, mResponseHead->ContentLength()); return NS_OK; } @@ -3688,8 +3700,8 @@ nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, // of a byte range request, the content length stored in the cached // response headers is what we want to use here. - PRUint32 progressMax = mResponseHead->ContentLength(); - PRUint32 progress = mLogicalOffset + count; + nsInt64 progressMax(mResponseHead->ContentLength()); + nsInt64 progress = mLogicalOffset + nsInt64(count); NS_ASSERTION(progress <= progressMax, "unexpected progress values"); OnTransportStatus(nsnull, transportStatus, progress, progressMax); @@ -3856,15 +3868,13 @@ nsHttpChannel::IsFromCache(PRBool *value) //----------------------------------------------------------------------------- NS_IMETHODIMP -nsHttpChannel::AsyncOpenAt(nsIStreamListener* aListener, - nsISupports* aCtxt, - PRUint32 aStartPos, - nsIResumableEntityID* aEntityID) +nsHttpChannel::ResumeAt(PRUint64 aStartPos, + nsIResumableEntityID* aEntityID) { mEntityID = aEntityID; mStartPos = aStartPos; mResuming = PR_TRUE; - return AsyncOpen(aListener, aCtxt); + return NS_OK; } NS_IMETHODIMP @@ -3881,7 +3891,7 @@ nsHttpChannel::GetEntityID(nsIResumableEntityID** aEntityID) return NS_OK; } - PRUint32 size = PR_UINT32_MAX; + PRUint64 size = LL_MaxUint(); nsCAutoString etag, lastmod; if (mResponseHead) { size = mResponseHead->TotalEntitySize(); diff --git a/mozilla/netwerk/protocol/http/src/nsHttpChannel.h b/mozilla/netwerk/protocol/http/src/nsHttpChannel.h index 25bcc25205f..60006c4ab54 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpChannel.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpChannel.h @@ -45,6 +45,7 @@ #include "nsHttpAuthCache.h" #include "nsXPIDLString.h" #include "nsCOMPtr.h" +#include "nsInt64.h" #include "nsIHttpChannel.h" #include "nsIHttpChannelInternal.h" @@ -211,7 +212,7 @@ private: PRUint32 mLoadFlags; PRUint32 mStatus; - PRUint32 mLogicalOffset; + nsInt64 mLogicalOffset; PRUint8 mCaps; nsCString mContentTypeHint; @@ -232,7 +233,7 @@ private: // Resumable channel specific data nsCOMPtr mEntityID; - PRUint32 mStartPos; + PRUint64 mStartPos; // redirection specific data. PRUint8 mRedirectionLimit; diff --git a/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.cpp b/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.cpp index 2af45a00cc4..caba7012c78 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.cpp @@ -69,13 +69,13 @@ nsHttpResponseHead::SetHeader(nsHttpAtom hdr, } void -nsHttpResponseHead::SetContentLength(PRInt32 len) +nsHttpResponseHead::SetContentLength(PRInt64 len) { mContentLength = len; - if (len < 0) + if (!LL_GE_ZERO(len)) // < 0 mHeaders.ClearHeader(nsHttp::Content_Length); else - mHeaders.SetHeader(nsHttp::Content_Length, nsPrintfCString("%d", len)); + mHeaders.SetHeader(nsHttp::Content_Length, nsPrintfCString(20, "%lld", len)); } void @@ -207,7 +207,7 @@ nsHttpResponseHead::ParseHeaderLine(char *line) // handle some special case headers... if (hdr == nsHttp::Content_Length) - mContentLength = atoi(val); + PR_sscanf(val, "%lld", &mContentLength); else if (hdr == nsHttp::Content_Type) ParseContentType(val); else if (hdr == nsHttp::Cache_Control) @@ -440,7 +440,7 @@ nsHttpResponseHead::Reset() mVersion = NS_HTTP_VERSION_1_1; mStatus = 200; - mContentLength = -1; + mContentLength = LL_MaxUint(); mCacheControlNoStore = PR_FALSE; mCacheControlNoCache = PR_FALSE; mPragmaNoCache = PR_FALSE; @@ -520,7 +520,7 @@ nsHttpResponseHead::GetExpiresValue(PRUint32 *result) return NS_OK; } -PRInt32 +PRInt64 nsHttpResponseHead::TotalEntitySize() { const char* contentRange = PeekHeader(nsHttp::Content_Range); @@ -536,7 +536,11 @@ nsHttpResponseHead::TotalEntitySize() if (*slash == '*') // Server doesn't know the length return -1; - return atoi(slash); + PRInt64 size; + PRInt32 items = PR_sscanf(slash, "%lld", &size); + if (items <= 0) + size = LL_MaxUint(); + return size; } //----------------------------------------------------------------------------- diff --git a/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.h b/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.h index b136b39c291..7e194d1f40d 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpResponseHead.h @@ -53,7 +53,7 @@ class nsHttpResponseHead public: nsHttpResponseHead() : mVersion(NS_HTTP_VERSION_1_1) , mStatus(200) - , mContentLength(-1) + , mContentLength(LL_MaxUint()) , mCacheControlNoStore(PR_FALSE) , mCacheControlNoCache(PR_FALSE) , mPragmaNoCache(PR_FALSE) {} @@ -66,7 +66,7 @@ public: nsHttpVersion Version() { return mVersion; } PRUint16 Status() { return mStatus; } const nsAFlatCString &StatusText() { return mStatusText; } - PRInt32 ContentLength() { return mContentLength; } + PRInt64 ContentLength() { return mContentLength; } const nsAFlatCString &ContentType() { return mContentType; } const nsAFlatCString &ContentCharset() { return mContentCharset; } PRBool NoStore() { return mCacheControlNoStore; } @@ -76,7 +76,7 @@ public: * than ContentLength(), which will only represent the requested part of the * entity. */ - PRInt32 TotalEntitySize(); + PRInt64 TotalEntitySize(); const char *PeekHeader(nsHttpAtom h) { return mHeaders.PeekHeader(h); } nsresult SetHeader(nsHttpAtom h, const nsACString &v, PRBool m=PR_FALSE); @@ -86,7 +86,7 @@ public: void SetContentType(const nsACString &s) { mContentType = s; } void SetContentCharset(const nsACString &s) { mContentCharset = s; } - void SetContentLength(PRInt32); + void SetContentLength(PRInt64); // write out the response status line and headers as a single text block, // optionally pruning out transient headers (ie. headers that only make @@ -141,7 +141,7 @@ private: nsHttpVersion mVersion; PRUint16 mStatus; nsCString mStatusText; - PRInt32 mContentLength; + PRInt64 mContentLength; nsCString mContentType; nsCString mContentCharset; PRPackedBool mCacheControlNoStore; diff --git a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp index c23fa23bf32..e3a69bed72e 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp @@ -762,7 +762,7 @@ nsHttpTransaction::HandleContentStart() mContentLength = -1; } #if defined(PR_LOGGING) - else if (mContentLength == -1) + else if (mContentLength == nsInt64(-1)) LOG(("waiting for the server to close the connection.\n")); #endif } @@ -799,20 +799,20 @@ nsHttpTransaction::HandleContent(char *buf, rv = mChunkedDecoder->HandleChunkedContent(buf, count, contentRead, contentRemaining); if (NS_FAILED(rv)) return rv; } - else if (mContentLength >= 0) { + else if (mContentLength >= nsInt64(0)) { // HTTP/1.0 servers have been known to send erroneous Content-Length // headers. So, unless the connection is persistent, we must make // allowances for a possibly invalid Content-Length header. Thus, if // NOT persistent, we simply accept everything in |buf|. if (mConnection->IsPersistent()) { - *contentRead = PRUint32(mContentLength) - mContentRead; + *contentRead = mContentLength - mContentRead; *contentRead = PR_MIN(count, *contentRead); } else { *contentRead = count; // mContentLength might need to be increased... - if (*contentRead + mContentRead > (PRUint32) mContentLength) { - mContentLength = *contentRead + mContentRead; + if (nsInt64(*contentRead) + mContentRead > mContentLength) { + mContentLength = nsInt64(*contentRead) + mContentRead; //mResponseHead->SetContentLength(mContentLength); } } @@ -832,11 +832,11 @@ nsHttpTransaction::HandleContent(char *buf, */ } - LOG(("nsHttpTransaction [this=%x count=%u read=%u mContentRead=%u mContentLength=%d]\n", - this, count, *contentRead, mContentRead, mContentLength)); + LOG(("nsHttpTransaction [this=%x count=%u read=%u mContentRead=%lld mContentLength=%lld]\n", + this, count, *contentRead, mContentRead.mValue, mContentLength.mValue)); // check for end-of-file - if ((mContentRead == PRUint32(mContentLength)) || + if ((mContentRead == mContentLength) || (mChunkedDecoder && mChunkedDecoder->ReachedEOF())) { // the transaction is done with a complete response. mTransactionDone = PR_TRUE; diff --git a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h index 33d074eb20b..e0f9145d65e 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h @@ -44,6 +44,7 @@ #include "nsAHttpTransaction.h" #include "nsAHttpConnection.h" #include "nsCOMPtr.h" +#include "nsInt64.h" #include "nsIPipe.h" #include "nsIInputStream.h" @@ -170,8 +171,8 @@ private: nsCString mLineBuf; // may contain a partial line - PRInt32 mContentLength; // equals -1 if unknown - PRUint32 mContentRead; // count of consumed content bytes + nsInt64 mContentLength; // equals -1 if unknown + nsInt64 mContentRead; // count of consumed content bytes nsHttpChunkedDecoder *mChunkedDecoder; diff --git a/mozilla/netwerk/streamconv/converters/nsMultiMixedConv.cpp b/mozilla/netwerk/streamconv/converters/nsMultiMixedConv.cpp index 310bca5ef34..c3c615c9cd3 100644 --- a/mozilla/netwerk/streamconv/converters/nsMultiMixedConv.cpp +++ b/mozilla/netwerk/streamconv/converters/nsMultiMixedConv.cpp @@ -89,7 +89,7 @@ public: NS_DECL_NSIMULTIPARTCHANNEL protected: - virtual ~nsPartChannel(); + ~nsPartChannel(); protected: nsCOMPtr mMultipartChannel; @@ -190,6 +190,7 @@ nsPartChannel::Cancel(nsresult aStatus) { // Cancelling an individual part must not cancel the underlying // multipart channel... + // XXX but we should stop sending data for _this_ part channel! mStatus = aStatus; return NS_OK; } @@ -199,6 +200,7 @@ nsPartChannel::Suspend(void) { // Suspending an individual part must not suspend the underlying // multipart channel... + // XXX why not? return NS_OK; } @@ -207,6 +209,7 @@ nsPartChannel::Resume(void) { // Resuming an individual part must not resume the underlying // multipart channel... + // XXX why not? return NS_OK; } diff --git a/mozilla/netwerk/test/TestProtocols.cpp b/mozilla/netwerk/test/TestProtocols.cpp index 43c155f721a..33d4939c27e 100644 --- a/mozilla/netwerk/test/TestProtocols.cpp +++ b/mozilla/netwerk/test/TestProtocols.cpp @@ -83,6 +83,8 @@ #include "prlog.h" #include "prtime.h" +#include "nsInt64.h" + #if defined(PR_LOGGING) // // set NSPR_LOG_MODULES=Test:5 @@ -100,7 +102,7 @@ static PRBool gVerbose = PR_FALSE; static nsIEventQueue* gEventQ = nsnull; static PRBool gAskUserForInput = PR_FALSE; static PRBool gResume = PR_FALSE; -static PRUint32 gStartAt = 0; +static PRUint64 gStartAt = 0; static const char* gLastMod = NULL; static const char* gETag = NULL; @@ -178,7 +180,7 @@ public: NS_DECL_ISUPPORTS const char* Name() { return mURLString.get(); } - PRInt32 mBytesRead; + nsInt64 mBytesRead; PRTime mTotalTime; PRTime mConnectTime; nsCString mURLString; @@ -418,10 +420,10 @@ InputTestConsumer::OnStartRequest(nsIRequest *request, nsISupports* context) nsCOMPtr entityID; nsresult rv = resChannel->GetEntityID(getter_AddRefs(entityID)); if (NS_SUCCEEDED(rv) && entityID) { - PRUint32 size; + PRUint64 size; if (NS_SUCCEEDED(entityID->GetSize(&size)) && - size != PRUint32(-1)) - LOG(("\tSize: %d\n", size)); + LL_NE(size, LL_MaxUint())) + LOG(("\tSize: %llu\n", size)); else LOG(("\tSize: Unknown\n")); nsCAutoString lastModified; @@ -533,10 +535,10 @@ InputTestConsumer::OnStopRequest(nsIRequest *request, nsISupports* context, } LOG(("\tTime to connect: %.3f seconds\n", connectTime)); LOG(("\tTime to read: %.3f seconds.\n", readTime)); - LOG(("\tRead: %d bytes.\n", info->mBytesRead)); - if (!info->mBytesRead) { + LOG(("\tRead: %lld bytes.\n", info->mBytesRead.mValue)); + if (info->mBytesRead == nsInt64(0)) { } else if (readTime > 0.0) { - LOG(("\tThroughput: %.0f bps.\n", (info->mBytesRead*8)/readTime)); + LOG(("\tThroughput: %.0f bps.\n", (PRFloat64)(info->mBytesRead*nsInt64(8))/readTime)); } else { LOG(("\tThroughput: REAL FAST!!\n")); } @@ -676,14 +678,10 @@ nsresult StartLoadingURL(const char* aUrlString) id->SetSize(gTotalSize); } } - rv = res->AsyncOpenAt(listener, - info, - gStartAt, - id); - } else { - rv = pChannel->AsyncOpen(listener, // IStreamListener consumer - info); + res->ResumeAt(gStartAt, id); } + rv = pChannel->AsyncOpen(listener, // IStreamListener consumer + info); if (NS_SUCCEEDED(rv)) { gKeepRunning += 1; @@ -807,7 +805,7 @@ main(int argc, char* argv[]) if (PL_strcasecmp(argv[i], "-resume") == 0) { gResume = PR_TRUE; - gStartAt = atoi(argv[++i]); + PR_sscanf(argv[++i], "%llu", &gStartAt); continue; } diff --git a/mozilla/xpcom/io/nsPipe3.cpp b/mozilla/xpcom/io/nsPipe3.cpp index d64d8385f69..be06179f4b4 100644 --- a/mozilla/xpcom/io/nsPipe3.cpp +++ b/mozilla/xpcom/io/nsPipe3.cpp @@ -44,6 +44,7 @@ #include "nsCOMPtr.h" #include "nsCRT.h" #include "prlog.h" +#include "nsInt64.h" #if defined(PR_LOGGING) // @@ -146,7 +147,7 @@ private: // separate refcnt so that we know when to close the consumer nsrefcnt mReaderRefCnt; - PRUint32 mLogicalOffset; + nsInt64 mLogicalOffset; PRPackedBool mBlocking; // these variables can only be accessed while inside the pipe's monitor @@ -200,7 +201,7 @@ private: // separate refcnt so that we know when to close the producer nsrefcnt mWriterRefCnt; - PRUint32 mLogicalOffset; + nsInt64 mLogicalOffset; PRPackedBool mBlocking; // these variables can only be accessed while inside the pipe's monitor @@ -858,7 +859,7 @@ nsPipeInputStream::Seek(PRInt32 whence, PRInt64 offset) NS_IMETHODIMP nsPipeInputStream::Tell(PRInt64 *offset) { - LL_UI2L(*offset, mLogicalOffset); + *offset = mLogicalOffset; return NS_OK; }