Fix 10738, partial fix for 21020. Keep-alive, http/1.1, transfer-encoding: chunked

can now be turned on (network.http.version=1.1); network.http.keep-alive can also
be used, however not recommended (1.1 pref will automatically enable keepa-alive).
r=warren,gagan
This commit is contained in:
ruslan%netscape.com 2000-03-14 03:41:46 +00:00
Родитель ced01d51fe
Коммит 74764af9f2
19 изменённых файлов: 318 добавлений и 82 удалений

Просмотреть файл

@ -26,4 +26,10 @@
interface nsISocketTransport : nsISupports
{
attribute boolean reuseConnection;
/**
* Is used to tell the channel to stop reading data after a certain point;
* needed by HTTP/1.1
*/
attribute long bytesExpected;
};

Просмотреть файл

@ -56,7 +56,8 @@ interface nsISocketTransportService : nsISupports
*/
boolean reuseTransport(in nsIChannel i_Transport);
void shutdown();
void shutdown ();
void wakeup (in nsIChannel i_Transport);
};
%{C++

Просмотреть файл

@ -137,7 +137,8 @@ nsSocketTransport::nsSocketTransport():
mWriteCount(0),
mWriteBuffer(nsnull),
mWriteBufferIndex(0),
mWriteBufferLength(0)
mWriteBufferLength(0),
mBytesExpected(-1)
{
NS_INIT_REFCNT();
@ -490,6 +491,8 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
if (mCloseConnectionOnceDone)
CloseConnection();
mBytesExpected = -1;
}
//
@ -526,12 +529,21 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
case eSocketState_WaitReadWrite:
// Process the read request...
if (GetReadType() != eSocketRead_None) {
mStatus = doRead(aSelectFlags);
if (NS_SUCCEEDED(mStatus)) {
SetFlag(eSocketRead_Done);
break;
}
if (GetReadType() != eSocketRead_None)
{
if (mBytesExpected == 0)
{
mStatus = NS_OK;
mSelectFlags &= (~PR_POLL_READ);
}
else
mStatus = doRead (aSelectFlags);
if (NS_SUCCEEDED(mStatus))
{
SetFlag(eSocketRead_Done);
break;
}
}
// Process the write request...
if ((NS_SUCCEEDED(mStatus) || mStatus == NS_BASE_STREAM_WOULD_BLOCK)
@ -837,11 +849,14 @@ nsReadFromSocket(void* closure,
info->bEOF = PR_FALSE;
*readCount = 0;
if (count > 0) {
len = PR_Read(info->fd, toRawSegment, count);
if (len >= 0) {
if (count > 0)
{
len = PR_Read (info -> fd, toRawSegment, count);
if (len >= 0)
{
*readCount = (PRUint32)len;
info->bEOF = (0 == len);
info -> bEOF = (0 == len);
}
//
// Error...
@ -947,7 +962,7 @@ nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags)
//
totalBytesWritten = 0;
info.fd = mSocketFD;
//
// Release the transport lock... WriteSegments(...) aquires the nsBuffer
// lock which could cause a deadlock by blocking the socket transport
// thread
@ -961,11 +976,37 @@ nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags)
("WriteSegments [fd=%x]. rv = %x. Bytes read =%d\n",
mSocketFD, rv, totalBytesWritten));
//
// Fire a single OnDataAvaliable(...) notification once as much data has
// been filled into the stream as possible...
//
if (totalBytesWritten)
{
if (mReadListener)
{
nsresult rv1;
rv1 = mReadListener->OnDataAvailable(this, mReadContext, mReadPipeIn,
mReadOffset,
totalBytesWritten);
//
// If the consumer returns failure, then cancel the operation...
//
if (NS_FAILED(rv1))
rv = rv1;
}
mReadOffset += totalBytesWritten;
}
//
// Deal with the possible return values...
//
if (NS_SUCCEEDED(rv)) {
if (info.bEOF) { // EOF condition
if (info.bEOF || mBytesExpected == 0)
{
// EOF condition
mSelectFlags &= (~PR_POLL_READ);
rv = NS_OK;
}
@ -974,27 +1015,6 @@ nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags)
}
}
//
// Fire a single OnDataAvaliable(...) notification once as much data has
// been filled into the stream as possible...
//
if (totalBytesWritten) {
if (mReadListener) {
nsresult rv1;
rv1 = mReadListener->OnDataAvailable(this, mReadContext, mReadPipeIn,
mReadOffset,
totalBytesWritten);
//
// If the consumer returns failure, then cancel the operation...
//
if (NS_FAILED(rv1)) {
rv = rv1;
}
}
mReadOffset += totalBytesWritten;
}
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("--- Leaving nsSocketTransport::doRead() [%s:%d %x]. rv = %x.\t"
"Total bytes read: %d\n\n",
@ -1254,6 +1274,31 @@ nsSocketTransport::SetReuseConnection(PRBool aReuse)
return NS_OK;
}
NS_IMETHODIMP
nsSocketTransport::GetBytesExpected (PRInt32 * bytes)
{
if (bytes != NULL)
{
*bytes = mBytesExpected;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSocketTransport::SetBytesExpected (PRInt32 bytes)
{
if (mCurrentState == eSocketState_WaitReadWrite)
{
mBytesExpected = bytes;
if (mBytesExpected == 0)
mService -> Wakeup (this);
}
return NS_OK;
}
//
// --------------------------------------------------------------------------

Просмотреть файл

@ -226,6 +226,7 @@ protected:
PRInt32 mSuspendCount;
PRInt32 mWriteCount;
nsCOMPtr<nsISupports> mWriteContext;
PRInt32 mBytesExpected;
// The following four members are used when AsyncWrite(...) is called
// with an nsIInputStream which does not also support the

Просмотреть файл

@ -412,6 +412,7 @@ nsSocketTransportService::Run(void)
int i;
count = PR_Poll(mSelectFDSet, mSelectFDSetCount, pollTimeout);
if (-1 == count) {
// XXX: PR_Poll failed... What should happen?
}
@ -587,6 +588,29 @@ nsSocketTransportService::ReuseTransport(nsIChannel* i_Transport,
return NS_OK;
}
/**
* wakeup the transport from PR_Poll ()
*/
NS_IMETHODIMP
nsSocketTransportService::Wakeup (nsIChannel* i_Transport)
{
nsSocketTransport *transport = NS_STATIC_CAST (nsSocketTransport *, i_Transport);
if (transport == NULL)
return NS_ERROR_NULL_POINTER;
AddToWorkQ (transport);
#ifdef USE_POLLABLE_EVENT
PR_SetPollableEvent (mThreadEvent);
#else
// XXX/ruslan: normally we would call PR_Interrupt (), but since it did work
// wait till NSPR fixes it one day
#endif
return NS_OK;
}
NS_IMETHODIMP
nsSocketTransportService::Shutdown(void)
{

Просмотреть файл

@ -62,6 +62,7 @@ interface nsIHTTPProtocolHandler : nsIProtocolHandler
in unsigned long encodeFlags);
attribute string acceptLanguages;
attribute unsigned long httpVersion;
/* i'll file a bug on the http guys to make nsAuthEngine scriptable
and then we can get rid of this no script code! */
[noscript] void getAuthEngine(out nsAuthEnginePtr authEngine);

Просмотреть файл

@ -370,6 +370,23 @@ nsHTTPHandler::GetAcceptLanguages(char* *o_AcceptLanguages)
}
}
NS_IMETHODIMP
nsHTTPHandler::SetHttpVersion (unsigned int i_HttpVersion)
{
mHttpVersion = i_HttpVersion;
return NS_OK;
}
NS_IMETHODIMP
nsHTTPHandler::GetHttpVersion (unsigned int * o_HttpVersion)
{
if (!o_HttpVersion)
return NS_ERROR_NULL_POINTER;
*o_HttpVersion = mHttpVersion;
return NS_OK;
}
NS_IMETHODIMP
nsHTTPHandler::GetAuthEngine(nsAuthEngine** o_AuthEngine)
{
@ -532,6 +549,7 @@ nsHTTPHandler::SetMisc(const PRUnichar* aMisc)
nsHTTPHandler::nsHTTPHandler():
mAcceptLanguages(nsnull),
mHttpVersion(HTTP_ONE_ZERO),
mDoKeepAlive(PR_FALSE),
mReferrerLevel(0)
{
@ -764,7 +782,7 @@ nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri,
if (port == -1)
GetDefaultPort(&port);
nsIChannel* trans;
nsIChannel* trans = nsnull;
// Check in the idle transports for a host/port match
count = 0;
PRInt32 index = 0;
@ -772,7 +790,7 @@ nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri,
{
mIdleTransports->Count(&count);
for (index=count-1; index >= 0; --index)
for (index=count-1; index >= 0; --index, trans = nsnull)
{
nsCOMPtr<nsIURI> uri;
trans = (nsIChannel*) mIdleTransports->ElementAt(index);
@ -796,7 +814,7 @@ nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri,
NS_ADDREF(trans);
// Remove it from the idle
mIdleTransports->RemoveElement(trans);
//break;// break out of the for loop
break;// break out of the for loop
}
}
}
@ -806,7 +824,7 @@ nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri,
}
}
// if we didn't find any from the keep-alive idlelist
if (*o_pTrans == nsnull)
if (trans == nsnull)
{
// Ask the channel for proxy info... since that overrides
PRBool usingProxy = PR_FALSE;
@ -1055,6 +1073,22 @@ nsHTTPHandler::PrefsChanged(const char* pref)
mReferrerLevel = referrerLevel;
}
nsXPIDLCString httpVersion;
rv = mPrefs -> CopyCharPref("network.http.version", getter_Copies(httpVersion));
if (NS_SUCCEEDED (rv) && httpVersion)
{
if (!PL_strcmp (httpVersion, "1.1"))
mHttpVersion = HTTP_ONE_ONE;
else
if (!PL_strcmp (httpVersion, "0.9"))
mHttpVersion = HTTP_ZERO_NINE;
}
else
mHttpVersion = HTTP_ONE_ZERO;
if (mHttpVersion == HTTP_ONE_ONE)
mDoKeepAlive = PR_TRUE;
// Things read only during initialization...
if (bChangedAll) // intl.accept_languages
{

Просмотреть файл

@ -104,6 +104,7 @@ protected:
nsCOMPtr<nsISupportsArray> mIdleTransports;
char* mAcceptLanguages;
PRUint32 mHttpVersion;
nsAuthEngine mAuthEngine;
PRBool mDoKeepAlive;
nsCOMPtr<nsIPref> mPrefs;

Просмотреть файл

@ -40,6 +40,7 @@
#include "nsIIOService.h"
#include "nsAuthEngine.h"
#include "nsIServiceManager.h"
#include "plstr.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gHTTPLog;
@ -120,6 +121,8 @@ nsHTTPRequest::nsHTTPRequest(nsIURI* i_URL, HTTPMethod i_Method):
if (acceptLanguages && *acceptLanguages)
SetHeader(nsHTTPAtoms::Accept_Language, acceptLanguages);
}
httpHandler -> GetHttpVersion (&mVersion);
}
@ -292,7 +295,18 @@ nsresult nsHTTPRequest::WriteRequest()
if (-1 != refLocation)
mRequestBuffer.Truncate(refLocation);
mRequestBuffer.Append(" HTTP/1.0"CRLF);
char * httpVersion = " HTTP/1.0" CRLF;
switch (mVersion)
{
case HTTP_ZERO_NINE:
httpVersion = " HTTP/0.9"CRLF;
break;
case HTTP_ONE_ONE:
httpVersion = " HTTP/1.1"CRLF;
}
mRequestBuffer.Append (httpVersion);
//
// Write the request headers, if any...
@ -407,13 +421,13 @@ nsresult nsHTTPRequest::GetHeader(nsIAtom* i_Header, char* *o_Value)
}
nsresult nsHTTPRequest::SetHTTPVersion(HTTPVersion i_Version)
nsresult nsHTTPRequest::SetHTTPVersion (PRUint32 i_Version)
{
mVersion = i_Version;
return NS_OK;
}
nsresult nsHTTPRequest::GetHTTPVersion(HTTPVersion* o_Version)
nsresult nsHTTPRequest::GetHTTPVersion (PRUint32 * o_Version)
{
*o_Version = mVersion;
return NS_OK;

Просмотреть файл

@ -91,8 +91,8 @@ public:
*/
nsresult Clone(const nsHTTPRequest* *o_Copy) const;
nsresult SetHTTPVersion(HTTPVersion i_Version);
nsresult GetHTTPVersion(HTTPVersion* o_Version);
nsresult SetHTTPVersion (PRUint32 i_Version);
nsresult GetHTTPVersion (PRUint32 * o_Version);
nsresult SetMethod(HTTPMethod i_Method);
HTTPMethod GetMethod(void) const;
@ -142,7 +142,7 @@ protected:
HTTPMethod mMethod;
nsCOMPtr<nsIURL> mURI;
HTTPVersion mVersion;
PRUint32 mVersion;
nsCOMPtr<nsIChannel> mTransport;
nsHTTPChannel* mConnection;

Просмотреть файл

@ -51,6 +51,7 @@ nsHTTPResponse::nsHTTPResponse()
// The content length is unknown...
mContentLength = -1;
mChunkedResponse = PR_FALSE;
}
nsHTTPResponse::~nsHTTPResponse()
@ -433,6 +434,8 @@ nsresult nsHTTPResponse::ProcessHeader(nsIAtom* aHeader, nsCString& aValue)
SetContentLength(length);
}
}
else if (nsHTTPAtoms::Transfer_Encoding == aHeader && !PL_strcmp (aValue, "chunked"))
mChunkedResponse = PR_TRUE;
//
// Set the response header...
@ -515,6 +518,11 @@ nsresult nsHTTPResponse::GetMaxAge(PRUint32* aMaxAge, PRBool* aMaxAgeIsPresent)
}
PRBool nsHTTPResponse::isChunkedResponse ()
{
return mChunkedResponse;
}
// Check to see if a (cached) HTTP response is stale and, therefore,
// must be revalidated with the origin server.
//

Просмотреть файл

@ -76,12 +76,14 @@ public:
nsresult ParseHeaders(nsCString& aAllHeaders);
nsresult ProcessHeader(nsIAtom* aHeader, nsCString& aValue);
nsresult EmitHeaders(nsCString& aResult);
nsresult UpdateHeaders(nsISimpleEnumerator *aEnumerator);
PRBool IsStale(PRBool aUseHeuristicExpiration);
nsresult ParseDateHeader(nsIAtom *aAtom, PRTime *aResultTime, PRBool *aHeaderIsPresent);
PRBool isChunkedResponse ();
nsresult UpdateHeaders(nsISimpleEnumerator *aEnumerator);
nsresult ParseDateHeader(nsIAtom *aAtom, PRTime *aResultTime, PRBool *aHeaderIsPresent);
protected:
virtual ~nsHTTPResponse();
nsresult ParseDateHeader(nsIAtom *aAtom, PRUint32 *aResultTime, PRBool *aHeaderIsPresent);
@ -94,6 +96,8 @@ protected:
PRUint32 mStatus;
PRInt32 mContentLength;
nsHTTPHeaderArray mHeaders;
private:
PRBool mChunkedResponse;
};
#endif /* _nsHTTPResponse_h_ */

Просмотреть файл

@ -25,10 +25,13 @@
#include "nsIStreamListener.h"
#include "nsHTTPResponseListener.h"
#include "nsIChannel.h"
#include "nsISocketTransport.h"
#include "nsIBufferInputStream.h"
#include "nsHTTPChannel.h"
#include "nsHTTPResponse.h"
#include "nsCRT.h"
#include "nsIStreamConverterService.h"
#include "nsIStreamConverter.h"
#include "nsHTTPAtoms.h"
#include "nsIHttpNotify.h"
@ -53,12 +56,8 @@ extern PRLogModuleInfo* gHTTPLog;
//
static const int kMAX_HEADER_SIZE = 60000;
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
///////////////////////////////////////////////////////////////////////////////
//
// nsHTTPResponseListener Implementation (abstract base class)
//
///////////////////////////////////////////////////////////////////////////////
nsHTTPResponseListener::nsHTTPResponseListener(nsHTTPChannel *aChannel)
: mChannel(aChannel)
{
@ -216,12 +215,15 @@ nsHTTPServerListener::nsHTTPServerListener(nsHTTPChannel* aChannel)
mResponse(nsnull),
mFirstLineParsed(PR_FALSE),
mHeadersDone(PR_FALSE),
mBytesReceived(0)
mBytesReceived(0),
mBodyBytesReceived (0)
{
mChannel->mHTTPServerListener = this;
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("Creating nsHTTPServerListener [this=%x].\n", this));
mChunkConverterPushed = PR_FALSE;
}
nsHTTPServerListener::~nsHTTPServerListener()
@ -305,6 +307,7 @@ nsHTTPServerListener::OnDataAvailable(nsIChannel* channel,
//
rv = FinishedResponseHeaders();
if (NS_FAILED(rv)) return rv;
}
// At this point we've digested headers from the server and we're
@ -334,6 +337,35 @@ nsHTTPServerListener::OnDataAvailable(nsIChannel* channel,
if (NS_SUCCEEDED(rv)) {
if (i_Length) {
PRInt32 cl = -1;
mResponse -> GetContentLength (&cl);
mBodyBytesReceived += i_Length;
if (cl != -1)
{
nsresult rv;
nsCOMPtr<nsISocketTransport> trans = do_QueryInterface (channel, &rv);
if (NS_SUCCEEDED (rv))
trans -> SetBytesExpected (cl - mBodyBytesReceived);
}
if (!mChunkConverterPushed && mResponse -> isChunkedResponse ())
{
NS_WITH_SERVICE (nsIStreamConverterService, StreamConvService, kStreamConverterServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsString2 fromStr ( "chunked" );
nsString2 toStr ("unchunked");
nsCOMPtr<nsIStreamListener> converterListener;
rv = StreamConvService -> AsyncConvertData (fromStr.GetUnicode(), toStr.GetUnicode(), mResponseDataListener, channel, getter_AddRefs (converterListener));
if (NS_FAILED(rv)) return rv;
mResponseDataListener = converterListener;
mChunkConverterPushed = PR_TRUE;
}
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("\tOnDataAvailable [this=%x]. Calling consumer "
"OnDataAvailable.\tlength:%d\n", this, i_Length));

Просмотреть файл

@ -114,6 +114,8 @@ protected:
nsCOMPtr<nsIInputStream> mDataStream;
PRUint32 mBytesReceived;
PRBool mChunkConverterPushed;
PRInt32 mBodyBytesReceived;
};

Просмотреть файл

@ -38,6 +38,7 @@ CPPSRCS = \
nsConvFactories.cpp \
mozTXTToHTMLConv.cpp \
nsUnknownDecoder.cpp \
nsHTTPChunkConv.cpp \
$(NULL)
EXPORTS = \

Просмотреть файл

@ -30,6 +30,7 @@ DLL=.\$(OBJDIR)\$(DLLNAME).dll
EXPORTS = \
nsMultiMixedConv.h \
nsFTPDirListingConv.h \
nsHTTPChunkConv.h \
$(NULL)
LLIBS= $(LLIBS) \
@ -55,6 +56,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsFTPDirListingConv.obj \
.\$(OBJDIR)\nsConvFactories.obj \
.\$(OBJDIR)\mozTXTToHTMLConv.obj \
.\$(OBJDIR)\nsHTTPChunkConv.obj \
.\$(OBJDIR)\nsUnknownDecoder.obj \
$(NULL)

Просмотреть файл

@ -26,12 +26,14 @@
#include "nsFTPDirListingConv.h"
#include "nsMultiMixedConv.h"
#include "nsHTTPChunkConv.h"
#include "mozTXTToHTMLConv.h"
#include "nsUnknownDecoder.h"
nsresult NS_NewFTPDirListingConv(nsFTPDirListingConv** result);
nsresult NS_NewMultiMixedConv(nsMultiMixedConv** result);
nsresult MOZ_NewTXTToHTMLConv(mozTXTToHTMLConv** result);
nsresult NS_NewMultiMixedConv (nsMultiMixedConv** result);
nsresult MOZ_NewTXTToHTMLConv (mozTXTToHTMLConv** result);
nsresult NS_NewHTTPChunkConv (nsHTTPChunkConv ** result);
static NS_IMETHODIMP
@ -106,6 +108,30 @@ CreateNewTXTToHTMLConvFactory(nsISupports* aOuter, REFNSIID aIID, void **aResult
return rv;
}
static NS_IMETHODIMP
CreateNewHTTPChunkConvFactory (nsISupports* aOuter, REFNSIID aIID, void **aResult)
{
if (!aResult) {
return NS_ERROR_INVALID_POINTER;
}
if (aOuter) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
nsHTTPChunkConv* inst = nsnull;
nsresult rv = NS_NewHTTPChunkConv (&inst);
if (NS_FAILED(rv)) {
*aResult = nsnull;
return rv;
}
rv = inst->QueryInterface(aIID, aResult);
if (NS_FAILED(rv)) {
*aResult = nsnull;
}
NS_RELEASE(inst); /* get rid of extra refcnt */
return rv;
}
static NS_IMETHODIMP
CreateNewUnknownDecoderFactory(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
@ -172,6 +198,19 @@ static nsModuleComponentInfo components[] =
NS_ISTREAMCONVERTER_KEY "?from=application/x-unknown-content-type?to=*/*",
CreateNewUnknownDecoderFactory
},
{ "HttpChunkConverter",
NS_HTTPCHUNKCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=chunked?to=unchunked",
CreateNewHTTPChunkConvFactory
},
{ "HttpChunkConverter",
NS_HTTPCHUNKCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=unchunked?to=chunked",
CreateNewHTTPChunkConvFactory
},
};
NS_IMPL_NSGETMODULE("nsConvModule", components);

Просмотреть файл

@ -25,6 +25,7 @@
#include "plstr.h"
#include "prlog.h"
#include "nsIChannel.h"
#include "nsISocketTransport.h"
#include "nsCOMPtr.h"
#include "nsIStringStream.h"
#include "nsIStreamListener.h"
@ -78,6 +79,8 @@ nsHTTPChunkConv::AsyncConvertData (
// hook ourself up with the receiving listener.
mListener = aListener;
NS_ADDREF (mListener);
mAsyncConvContext = aCtxt;
return NS_OK;
}
@ -175,24 +178,35 @@ nsHTTPChunkConv::OnDataAvailable (
// send data upstream
{
nsIInputStream * convertedStream = nsnull;
nsCString convertedString (mChunkBuffer);
nsISupports * convertedStreamSup = nsnull;
if (mChunkBufferLength > 0)
{
nsIInputStream * convertedStream = nsnull;
nsCString convertedString (mChunkBuffer);
nsISupports * convertedStreamSup = nsnull;
rv = NS_NewStringInputStream (&convertedStreamSup, convertedString);
if (NS_FAILED (rv))
return rv;
rv = NS_NewStringInputStream (&convertedStreamSup, convertedString);
if (NS_FAILED (rv))
return rv;
rv = convertedStreamSup -> QueryInterface (NS_GET_IID(nsIInputStream), (void**)&convertedStream);
NS_RELEASE (convertedStreamSup);
rv = convertedStreamSup -> QueryInterface (NS_GET_IID(nsIInputStream), (void**)&convertedStream);
NS_RELEASE (convertedStreamSup);
if (NS_FAILED (rv))
return rv;
if (NS_FAILED (rv))
return rv;
rv = mListener -> OnDataAvailable (aChannel, aContext, convertedStream, aSourceOffset, mChunkBufferLength);
rv = mListener -> OnDataAvailable (aChannel, aContext, convertedStream, aSourceOffset, mChunkBufferLength);
if (NS_FAILED (rv))
return rv;
if (NS_FAILED (rv))
return rv;
}
else
{
nsresult rv;
nsCOMPtr<nsISocketTransport> trans = do_QueryInterface (mAsyncConvContext, &rv);
if (NS_SUCCEEDED (rv))
trans -> SetBytesExpected (0);
}
mState = CHUNK_STATE_INIT;
@ -231,8 +245,13 @@ nsHTTPChunkConv::OnDataAvailable (
streamLen--;
if (mState == CHUNK_STATE_LF)
{
mChunkBuffer = (char * )nsAllocator::Alloc (mChunkBufferLength + 1);
mState = CHUNK_STATE_DATA;
if (mChunkBufferLength > 0)
{
mChunkBuffer = (char * )nsAllocator::Alloc (mChunkBufferLength + 1);
mState = CHUNK_STATE_DATA;
}
else
mState = CHUNK_STATE_CR_FINAL;
}
else
mState = CHUNK_STATE_FINAL;
@ -266,15 +285,14 @@ nsHTTPChunkConv::OnDataAvailable (
case CHUNK_STATE_DATA:
if (mChunkBufferLength - mChunkBufferPos <= streamLen)
{
// entire chunk
rv = iStr -> Read (&mChunkBuffer[mChunkBufferPos], mChunkBufferLength - mChunkBufferPos, &rl);
if (NS_FAILED (rv))
return rv;
mChunkBufferPos += rl;
mChunkBuffer[mChunkBufferPos++] = 0;
streamLen -= rl;
// entire chunk
rv = iStr -> Read (&mChunkBuffer[mChunkBufferPos], mChunkBufferLength - mChunkBufferPos, &rl);
if (NS_FAILED (rv))
return rv;
mChunkBufferPos += rl;
mChunkBuffer[mChunkBufferPos++] = 0;
streamLen -= rl;
mState = CHUNK_STATE_CR_FINAL;
}
else

Просмотреть файл

@ -25,6 +25,7 @@
#include "nsIStreamConverter.h"
#include "nsIFactory.h"
#include "nsCOMPtr.h"
#define NS_HTTPCHUNKCONVERTER_CID \
{ \
@ -51,7 +52,7 @@ typedef enum enum_ChunkState
CHUNK_STATE_DATA,
CHUNK_STATE_CR_FINAL,
CHUNK_STATE_LF_FINAL,
CHUNK_STATE_FINAL,
CHUNK_STATE_FINAL
} ChunkState;
#define HTTP_CHUNK_TYPE "chunked"
@ -83,7 +84,9 @@ private:
char mLenBuf[20];
PRUint32 mLenBufCnt;
nsCOMPtr<nsISupports> mAsyncConvContext;
};
#endif
#endif