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
This commit is contained in:
cbiesinger%web.de
2004-06-16 19:51:21 +00:00
parent c5a54952c4
commit 8f66d1ac2b
22 changed files with 159 additions and 116 deletions

View File

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

View File

@@ -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

View File

@@ -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.
*/

View File

@@ -618,7 +618,7 @@ NS_GetURLSpecFromFile(nsIFile *aFile,
inline nsresult
NS_NewResumableEntityID(nsIResumableEntityID **aRes,
PRUint32 size,
PRUint64 size,
const nsACString &lastModified,
const nsACString &entityTag)
{

View File

@@ -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<nsISeekableStream> 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) {
//

View File

@@ -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<nsIEventQueue> mEventQ;
nsCOMPtr<nsIInputStream> mStream;
nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
PRUint32 mStreamOffset;
PRUint32 mStreamLength;
nsInt64 mStreamOffset;
nsInt64 mStreamLength;
PRUint32 mSegSize;
PRUint32 mSegCount;
nsresult mStatus;

View File

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

View File

@@ -46,7 +46,7 @@ public:
~nsResumableEntityID();
private:
PRUint32 mSize;
PRUint64 mSize;
nsCString mLastModified;
nsCString mEntityTag;
};

View File

@@ -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);

View File

@@ -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<nsIURI> mOriginalURI;
@@ -153,6 +155,7 @@ protected:
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
nsCOMPtr<nsIProxyInfo> mProxyInfo;
nsCOMPtr<nsIResumableEntityID> mEntityID;
PRUint64 mStartPos;
};
#endif /* nsFTPChannel_h___ */

View File

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

View File

@@ -194,7 +194,7 @@ private:
nsCOMPtr<nsISocketTransport> mDPipe; // the data transport
nsCOMPtr<nsIRequest> mDPipeRequest;
DataRequestForwarder* mDRequestForwarder;
PRUint32 mFileSize;
PRUint64 mFileSize;
nsCString mModTime;
// ****** consumer vars

View File

@@ -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
*

View File

@@ -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<nsIResumableChannel> 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();

View File

@@ -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<nsIResumableEntityID> mEntityID;
PRUint32 mStartPos;
PRUint64 mStartPos;
// redirection specific data.
PRUint8 mRedirectionLimit;

View File

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

View File

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

View File

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

View File

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

View File

@@ -89,7 +89,7 @@ public:
NS_DECL_NSIMULTIPARTCHANNEL
protected:
virtual ~nsPartChannel();
~nsPartChannel();
protected:
nsCOMPtr<nsIChannel> 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;
}

View File

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

View File

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