зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
ced01d51fe
Коммит
74764af9f2
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче