From 0e08e3e2eec2fcbd7fa418dc3b5dfd65c80c729a Mon Sep 17 00:00:00 2001 From: "ruslan%netscape.com" Date: Fri, 7 Apr 2000 21:54:37 +0000 Subject: [PATCH] Fix for link-click problem git-svn-id: svn://10.0.0.236/branches/linkclickfix_tmp_branch@65508 18797224-902f-48f8-a5cc-f745e15eee43 --- .../base/public/nsISocketTransport.idl | 12 +- .../netwerk/base/src/nsSocketTransport.cpp | 125 ++++++++++++------ mozilla/netwerk/base/src/nsSocketTransport.h | 13 +- .../base/src/nsSocketTransportService.cpp | 22 +-- .../base/src/nsSocketTransportService.h | 9 +- .../protocol/http/src/nsHTTPChannel.cpp | 14 +- .../protocol/http/src/nsHTTPHandler.cpp | 27 +++- .../netwerk/protocol/http/src/nsHTTPHandler.h | 6 + .../protocol/http/src/nsHTTPRequest.cpp | 57 +++++++- .../netwerk/protocol/http/src/nsHTTPRequest.h | 1 + .../http/src/nsHTTPResponseListener.cpp | 20 ++- .../http/src/nsHTTPResponseListener.h | 1 + 12 files changed, 217 insertions(+), 90 deletions(-) diff --git a/mozilla/netwerk/base/public/nsISocketTransport.idl b/mozilla/netwerk/base/public/nsISocketTransport.idl index 3cd7471c807..7b1ade77708 100644 --- a/mozilla/netwerk/base/public/nsISocketTransport.idl +++ b/mozilla/netwerk/base/public/nsISocketTransport.idl @@ -27,6 +27,16 @@ interface nsISocketTransport : nsISupports { attribute boolean reuseConnection; + /** + * socket read/write timeout in seconds; 0 = no timeout + */ + attribute unsigned long socketTimeout; + + /** + * socket connect timeout in seconds; 0 = no timeout + */ + attribute unsigned long socketConnectTimeout; + /** * Is used to tell the channel to stop reading data after a certain point; * needed by HTTP/1.1 @@ -39,7 +49,7 @@ interface nsISocketTransport : nsISupports * * @param seconds amount of time after which the socket is always deemed to be * dead (no further checking is done in this case); seconds = 0 - * will cause it not to do timeout checking at all + * will cause it not to do the timeout checking at all */ boolean isAlive (in unsigned long seconds); }; diff --git a/mozilla/netwerk/base/src/nsSocketTransport.cpp b/mozilla/netwerk/base/src/nsSocketTransport.cpp index ad1c16eb8ec..04f6dce6328 100644 --- a/mozilla/netwerk/base/src/nsSocketTransport.cpp +++ b/mozilla/netwerk/base/src/nsSocketTransport.cpp @@ -98,7 +98,6 @@ nsSocketState gStateTable[eSocketOperation_Max][eSocketState_Max] = { #define CONNECT_TIMEOUT_IN_MS 20 static PRIntervalTime gConnectTimeout = PR_INTERVAL_NO_WAIT; -static PRIntervalTime gTimeoutInterval = PR_INTERVAL_NO_WAIT; #if defined(PR_LOGGING) // @@ -143,7 +142,9 @@ nsSocketTransport::nsSocketTransport(): mWriteBufferIndex(0), mWriteBufferLength(0), mBufferSegmentSize(0), - mBufferMaxSize(0) + mBufferMaxSize(0), + mSocketTimeout (PR_INTERVAL_NO_TIMEOUT), + mSocketConnectTimeout (PR_MillisecondsToInterval (DEFAULT_SOCKET_CONNECT_TIMEOUT_IN_MS)) { NS_INIT_REFCNT(); @@ -308,16 +309,17 @@ nsresult nsSocketTransport::CheckForTimeout (PRIntervalTime aCurrentTime) idleInterval = aCurrentTime - mLastActiveTime; - // - // Only timeout if the transport is waiting to connect to the server - // - if ((mCurrentState == eSocketState_WaitConnect) - && idleInterval >= gTimeoutInterval) + if (mSocketConnectTimeout != PR_INTERVAL_NO_TIMEOUT && mCurrentState == eSocketState_WaitConnect + && idleInterval >= mSocketConnectTimeout + || + mSocketTimeout != PR_INTERVAL_NO_TIMEOUT && mCurrentState == eSocketState_WaitReadWrite + && idleInterval >= mSocketTimeout) { - PR_LOG(gSocketLog, PR_LOG_ERROR, - ("nsSocketTransport::CheckForTimeout() [%s:%d %x].\t" - "TIMED OUT... Idle interval: %d\n", - mHostName, mPort, this, idleInterval)); + PR_LOG ( + gSocketLog, PR_LOG_ERROR, ("nsSocketTransport::CheckForTimeout() [%s:%d %x].\t" + "TIMED OUT... Idle interval: %d\n", + mHostName, mPort, this, idleInterval) + ); // Move the transport into the Timeout state... mCurrentState = eSocketState_Timeout; @@ -1254,12 +1256,6 @@ nsresult nsSocketTransport::CloseConnection(PRBool bNow) } -void nsSocketTransport::SetSocketTimeout(PRIntervalTime aTimeInterval) -{ - gTimeoutInterval = aTimeInterval; -} - - // // -------------------------------------------------------------------------- // nsISupports implementation... @@ -2156,28 +2152,6 @@ nsSocketTransport::SetNotificationCallbacks(nsIInterfaceRequestor* aNotification return NS_OK; } -nsresult -nsSocketTransport::fireStatus(PRUint32 aCode) -{ - // need to optimize this - TODO - nsXPIDLString tempmesg; - nsresult rv = GetSocketErrorString(aCode, getter_Copies(tempmesg)); - - nsAutoString mesg(tempmesg); - if (mPrintHost) - mesg.AppendWithConversion(mPrintHost); - else - mesg.AppendWithConversion(mHostName); - - if (NS_FAILED(rv)) return rv; - - return mEventSink ? mEventSink->OnStatus(this, - mReadContext, - mesg.GetUnicode()) // this gets freed elsewhere. - : NS_ERROR_FAILURE; -} - - NS_IMETHODIMP nsSocketTransport::IsAlive (PRUint32 seconds, PRBool *alive) { @@ -2197,11 +2171,11 @@ nsSocketTransport::IsAlive (PRUint32 seconds, PRBool *alive) static char c; PRInt32 rval = PR_Read (mSocketFD, &c, 0); - if (rval <= 0) + if (rval < 0) { PRErrorCode code = PR_GetError (); - if (rval < 0 && code != PR_WOULD_BLOCK_ERROR) + if (code != PR_WOULD_BLOCK_ERROR) *alive = PR_FALSE; } } @@ -2211,6 +2185,75 @@ nsSocketTransport::IsAlive (PRUint32 seconds, PRBool *alive) return NS_OK; } +NS_IMETHODIMP +nsSocketTransport::GetSocketTimeout (PRUint32 * o_Seconds) +{ + if (o_Seconds == NULL) + return NS_ERROR_NULL_POINTER; + + if (mSocketTimeout == PR_INTERVAL_NO_TIMEOUT) + *o_Seconds = 0; + else + *o_Seconds = PR_IntervalToSeconds (mSocketTimeout); + + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::SetSocketTimeout (PRUint32 a_Seconds) +{ + if (a_Seconds == 0) + mSocketTimeout = PR_INTERVAL_NO_TIMEOUT; + else + mSocketTimeout = PR_SecondsToInterval (a_Seconds); + + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::GetSocketConnectTimeout (PRUint32 * o_Seconds) +{ + if (o_Seconds == NULL) + return NS_ERROR_NULL_POINTER; + + if (mSocketConnectTimeout == PR_INTERVAL_NO_TIMEOUT) + *o_Seconds = 0; + else + *o_Seconds = PR_IntervalToSeconds (mSocketConnectTimeout); + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::SetSocketConnectTimeout (PRUint32 a_Seconds) +{ + if (a_Seconds == 0) + mSocketConnectTimeout = PR_INTERVAL_NO_TIMEOUT; + else + mSocketConnectTimeout = PR_SecondsToInterval (a_Seconds); + return NS_OK; +} + +nsresult +nsSocketTransport::fireStatus(PRUint32 aCode) +{ + // need to optimize this - TODO + nsXPIDLString tempmesg; + nsresult rv = GetSocketErrorString(aCode, getter_Copies(tempmesg)); + + nsAutoString mesg(tempmesg); + if (mPrintHost) + mesg.AppendWithConversion(mPrintHost); + else + mesg.AppendWithConversion(mHostName); + + if (NS_FAILED(rv)) return rv; + + return mEventSink ? mEventSink->OnStatus(this, + mReadContext, + mesg.GetUnicode()) // this gets freed elsewhere. + : NS_ERROR_FAILURE; +} + //TODO l10n and i18n stuff here! nsresult nsSocketTransport::GetSocketErrorString(PRUint32 iCode, diff --git a/mozilla/netwerk/base/src/nsSocketTransport.h b/mozilla/netwerk/base/src/nsSocketTransport.h index 8fc5d4a1a10..53bdd029398 100644 --- a/mozilla/netwerk/base/src/nsSocketTransport.h +++ b/mozilla/netwerk/base/src/nsSocketTransport.h @@ -106,6 +106,12 @@ enum nsSocketReadWriteInfo { eSocketDNS_Wait = 0x2020 }; +// +// This is the default timeout value (in milliseconds) for sockets which have +// no activity... +// +#define DEFAULT_SOCKET_CONNECT_TIMEOUT_IN_MS 35*1000 + // Forward declarations... class nsSocketTransportService; class nsIInterfaceRequestor; @@ -137,7 +143,7 @@ public: nsresult Process(PRInt16 aSelectFlags); - nsresult CheckForTimeout(PRIntervalTime aCurrentTime); + nsresult CheckForTimeout (PRIntervalTime aCurrentTime); // Close this socket either right away or once done with the transaction. nsresult CloseConnection(PRBool bNow=PR_TRUE); @@ -149,8 +155,6 @@ public: static nsSocketTransport* GetInstance(PRCList* qp) { return (nsSocketTransport*)((char*)qp - offsetof(nsSocketTransport, mListLink)); } - static void SetSocketTimeout(PRIntervalTime aTimeoutInterval); - PRBool CanBeReused(void) { return (mCurrentState != eSocketState_Error) && !mCloseConnectionOnceDone;} @@ -167,6 +171,9 @@ protected: nsresult GetSocketErrorString(PRUint32 iCode, PRUnichar** oString) const; private: + PRIntervalTime mSocketTimeout; + PRIntervalTime mSocketConnectTimeout; + // Access methods for manipulating the ReadWriteInfo... inline void SetReadType(nsSocketReadWriteInfo aType) { mReadWriteState = (mReadWriteState & ~eSocketRead_Type_Mask) | aType; diff --git a/mozilla/netwerk/base/src/nsSocketTransportService.cpp b/mozilla/netwerk/base/src/nsSocketTransportService.cpp index d33ff2a52e7..caea55ccd2b 100644 --- a/mozilla/netwerk/base/src/nsSocketTransportService.cpp +++ b/mozilla/netwerk/base/src/nsSocketTransportService.cpp @@ -49,8 +49,6 @@ nsSocketTransportService::nsSocketTransportService() mActiveTransportList = nsnull; mThreadRunning = PR_FALSE; - - SetSocketTimeoutInterval(PR_MillisecondsToInterval(DEFAULT_SOCKET_TIMEOUT_IN_MS)); } @@ -345,24 +343,6 @@ nsresult nsSocketTransportService::RemoveFromSelectList(nsSocketTransport* aTran } -nsresult -nsSocketTransportService::GetSocketTimeoutInterval(PRIntervalTime* aResult) -{ - *aResult = mSocketTimeoutInterval; - return NS_OK; -} - -nsresult -nsSocketTransportService::SetSocketTimeoutInterval(PRIntervalTime aTime) -{ - mSocketTimeoutInterval = aTime; - - // Update the timeout value in the socket transport... - nsSocketTransport::SetSocketTimeout(aTime); - - return NS_OK; -} - // // -------------------------------------------------------------------------- // nsISupports implementation... @@ -389,7 +369,7 @@ nsSocketTransportService::Run(void) mSelectFDSet[0].fd = mThreadEvent; mSelectFDSet[0].in_flags = PR_POLL_READ; mSelectFDSetCount = 1; - pollTimeout = mSocketTimeoutInterval; + pollTimeout = PR_MillisecondsToInterval (DEFAULT_POLL_TIMEOUT_IN_MS); #else // // For now, rather than breaking out of the call to PR_Poll(...) just set diff --git a/mozilla/netwerk/base/src/nsSocketTransportService.h b/mozilla/netwerk/base/src/nsSocketTransportService.h index 9cb42a11088..446144134bc 100644 --- a/mozilla/netwerk/base/src/nsSocketTransportService.h +++ b/mozilla/netwerk/base/src/nsSocketTransportService.h @@ -38,17 +38,12 @@ #define USE_POLLABLE_EVENT #endif -// -// This is the default timeout value (in milliseconds) for sockets which have -// no activity... -// -#define DEFAULT_SOCKET_TIMEOUT_IN_MS 35*1000 - // // This is the Maximum number of Socket Transport instances that can be active // at once... // #define MAX_OPEN_CONNECTIONS 50 +#define DEFAULT_POLL_TIMEOUT_IN_MS 35*1000 // Forward declarations... @@ -89,8 +84,6 @@ protected: PRLock* mThreadLock; PRBool mThreadRunning; - PRIntervalTime mSocketTimeoutInterval; - PRCList mWorkQ; PRInt32 mSelectFDSetCount; diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPChannel.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPChannel.cpp index 07b5506ca5a..ff5a699f8ba 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPChannel.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPChannel.cpp @@ -97,7 +97,8 @@ nsHTTPChannel::nsHTTPChannel(nsIURI* i_URL, nsHTTPHandler* i_Handler): mBufferSegmentSize(0), mBufferMaxSize(0), mStatus(NS_OK), - mPipeliningAllowed (PR_TRUE) + mPipeliningAllowed (PR_TRUE), + mPipelinedRequest (nsnull) { NS_INIT_REFCNT(); @@ -1327,17 +1328,24 @@ nsHTTPChannel::Open(void) if (NS_ERROR_BUSY == rv) { - mPipelinedRequest = pReq; + if (!mPipelinedRequest) + { + mPipelinedRequest = pReq; + NS_RELEASE (pReq); + } + mState = HS_WAITING_FOR_OPEN; return NS_OK; } + if (!mPipelinedRequest) + NS_RELEASE (pReq); + if (NS_FAILED (rv)) { ResponseCompleted (mResponseDataListener, rv, nsnull); return rv; } - NS_RELEASE (pReq); } mState = HS_WAITING_FOR_RESPONSE; diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp index da1a010e1c9..8e8cb426a4a 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp @@ -601,7 +601,9 @@ nsHTTPHandler::nsHTTPHandler(): mCapabilities (DEFAULT_ALLOWED_CAPABILITIES ), mKeepAliveTimeout (DEFAULT_KEEP_ALIVE_TIMEOUT), mMaxConnections (MAX_NUMBER_OF_OPEN_TRANSPORTS), - mReferrerLevel(0) + mReferrerLevel (0), + mRequestTimeout (DEFAULT_HTTP_REQUEST_TIMEOUT), + mConnectTimeout (DEFAULT_HTTP_CONNECT_TIMEOUT) { NS_INIT_REFCNT (); SetAcceptEncodings (DEFAULT_ACCEPT_ENCODINGS); @@ -970,13 +972,21 @@ nsresult nsHTTPHandler::CreateTransport(const char* host, { nsresult rv; - NS_WITH_SERVICE(nsISocketTransportService, sts, - kSocketTransportServiceCID, &rv); - if (NS_FAILED(rv)) return rv; + NS_WITH_SERVICE (nsISocketTransportService, sts, kSocketTransportServiceCID, &rv); + if (NS_FAILED (rv)) + return rv; - return sts->CreateTransport(host, port, aPrintHost, - bufferSegmentSize, bufferMaxSize, - o_pTrans); + rv = sts -> CreateTransport (host, port, aPrintHost, bufferSegmentSize, bufferMaxSize, o_pTrans); + if (NS_SUCCEEDED (rv)) + { + nsCOMPtr trans = do_QueryInterface (*o_pTrans, &rv); + if (NS_SUCCEEDED (rv)) + { + trans -> SetSocketTimeout (mRequestTimeout); + trans -> SetSocketConnectTimeout (mConnectTimeout); + } + } + return rv; } nsresult nsHTTPHandler::ReleaseTransport (nsIChannel* i_pTrans, PRUint32 aCapabilities) @@ -1225,6 +1235,9 @@ nsHTTPHandler::PrefsChanged(const char* pref) mCapabilities &= ~ALLOW_PROXY_PIPELINING; } + mPrefs -> GetIntPref ("network.http.connect.timeout", &mConnectTimeout); + mPrefs -> GetIntPref ("network.http.request.timeout", &mRequestTimeout); + // Things read only during initialization... if (bChangedAll) // intl.accept_languages { diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.h b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.h index e2733b5b3c9..666214d97cd 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.h +++ b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.h @@ -61,6 +61,9 @@ class nsHTTPChannel; // because of HTTP/1.1 is default now #define DEFAULT_ALLOWED_CAPABILITIES (DEFAULT_PROXY_CAPABILITIES|DEFAULT_SERVER_CAPABILITIES) +#define DEFAULT_HTTP_REQUEST_TIMEOUT 30 +#define DEFAULT_HTTP_CONNECT_TIMEOUT 30 + class nsHTTPPipelinedRequest; class nsIHTTPChannel; @@ -155,6 +158,9 @@ protected: private: nsHashtable mCapTable; + PRInt32 mRequestTimeout; + PRInt32 mConnectTimeout; + PRUint32 getCapabilities (const char *host, PRInt32 port, PRUint32 cap); void setCapabilities (nsIChannel* i_pTrans, PRUint32 aCapabilities); diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPRequest.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPRequest.cpp index 8ae2ae46198..1767bba69bf 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPRequest.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPRequest.cpp @@ -579,9 +579,12 @@ nsHTTPPipelinedRequest::WriteRequest () if (!mTransport) { + PRUint32 tMode = mAttempts ? TRANSPORT_OPEN_ALWAYS : TRANSPORT_REUSE_ALIVE; + if (mPostDataStream) + tMode &= ~(TRANSPORT_REUSE_ALIVE); + rv = mHandler -> RequestTransport (req -> mURI, req -> mConnection, mBufferSegmentSize, mBufferMaxSize, - getter_AddRefs (mTransport), - mAttempts ? TRANSPORT_OPEN_ALWAYS : TRANSPORT_REUSE_ALIVE); + getter_AddRefs (mTransport), tMode); if (NS_FAILED (rv)) { @@ -669,10 +672,13 @@ nsHTTPPipelinedRequest::OnStopRequest (nsIChannel* channel, nsISupports* i_Conte nsresult rv; nsCOMPtr trans = do_QueryInterface (mTransport, &rv); + mOnStopDone = PR_TRUE; nsHTTPRequest * req = (nsHTTPRequest *) mRequests -> ElementAt (0); rv = iStatus; + PR_LOG (gHTTPLog, PR_LOG_DEBUG, ("\nnsHTTPRequest::OnStopRequest () [this=%x], iStatus=%u\n", this, iStatus)); + if (NS_SUCCEEDED (rv)) { PRBool isAlive = PR_TRUE; @@ -715,7 +721,7 @@ nsHTTPPipelinedRequest::OnStopRequest (nsIChannel* channel, nsISupports* i_Conte else rv = NS_ERROR_OUT_OF_MEMORY; } - mOnStopDone = PR_TRUE; + WriteRequest (); // write again to see if anything else is queued up } } @@ -739,7 +745,7 @@ nsHTTPPipelinedRequest::OnStopRequest (nsIChannel* channel, nsISupports* i_Conte // if (NS_FAILED (rv)) { - if (mListener == nsnull) + if (mTotalProcessed == 0 && mAttempts == 0) { // the pipeline just started - we still can attempt to recover @@ -755,7 +761,6 @@ nsHTTPPipelinedRequest::OnStopRequest (nsIChannel* channel, nsISupports* i_Conte { mAttempts++; mTotalWritten = 0; - mOnStopDone = PR_TRUE; rv = WriteRequest (); @@ -766,6 +771,11 @@ nsHTTPPipelinedRequest::OnStopRequest (nsIChannel* channel, nsISupports* i_Conte } } } + else + { + mHandler -> ReleaseTransport (mTransport, 0); + mTransport = null_nsCOMPtr (); + } // Notify the HTTPChannel that the request has finished nsCOMPtr consumer; @@ -785,6 +795,43 @@ nsHTTPPipelinedRequest::OnStopRequest (nsIChannel* channel, nsISupports* i_Conte return rv; } +nsresult +nsHTTPPipelinedRequest::RestartRequest () +{ + nsresult rv = NS_ERROR_FAILURE; + + PR_LOG (gHTTPLog, PR_LOG_DEBUG, ("\nnsHTTPPipelinedRequest::RestartRequest () [this=%x], mTotalProcessed=%u\n", this, mTotalProcessed)); + + if (mTotalProcessed == 0) + { + // the pipeline just started - we still can attempt to recover + + nsCOMPtr trans = do_QueryInterface (mTransport, &rv); + PRUint32 wasKeptAlive = 0; + + if (trans) + trans -> GetReuseCount (&wasKeptAlive); + + if (wasKeptAlive && mAttempts == 0) + { + rv = NS_OK; + mListener = nsnull; + + if (mOnStopDone) + { + mHandler -> ReleaseTransport (mTransport, 0); + mTransport = null_nsCOMPtr (); + + mTotalWritten = 0; + + mAttempts++; + rv = WriteRequest (); + } + } + } + return rv; +} + nsresult nsHTTPPipelinedRequest::IsPending (PRBool *result) { diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPRequest.h b/mozilla/netwerk/protocol/http/src/nsHTTPRequest.h index 20d008eb5c1..dc3b663605c 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPRequest.h +++ b/mozilla/netwerk/protocol/http/src/nsHTTPRequest.h @@ -195,6 +195,7 @@ public: nsresult GetCurrentRequest (nsHTTPRequest ** o_Req); nsresult AdvanceToNextRequest (); + nsresult RestartRequest (); nsresult IsPending (PRBool *result); nsresult Cancel (nsresult status ); diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.cpp index 681c1a1753d..fa6689051dc 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.cpp @@ -220,7 +220,8 @@ nsHTTPServerListener::nsHTTPServerListener(nsHTTPChannel* aChannel, nsHTTPHandle mCompressHeaderChecked (PR_FALSE), mChunkHeaderEOF(PR_FALSE), mChunkHeaderChecked (PR_FALSE), - mPipelinedRequest (request) + mPipelinedRequest (request), + mDataReceived (PR_FALSE) { nsHTTPRequest * req = nsnull; mChannel -> mHTTPServerListener = this; @@ -264,6 +265,9 @@ nsHTTPServerListener::OnDataAvailable(nsIChannel* channel, "\tstream=%x. \toffset=%d. \tlength=%d.\n", this, i_pStream, i_SourceOffset, i_Length)); + if (i_Length > 0) + mDataReceived = PR_TRUE; + if (!mResponse) { mResponse = new nsHTTPResponse (); @@ -486,6 +490,7 @@ nsHTTPServerListener::OnStartRequest (nsIChannel* channel, nsISupports* i_pConte mCompressHeaderChecked = PR_FALSE; mChunkHeaderEOF = PR_FALSE; mChunkHeaderChecked = PR_FALSE; + mDataReceived = PR_FALSE; mBytesReceived = 0; mBodyBytesReceived = 0; mHeaderBuffer.Truncate (); @@ -523,6 +528,19 @@ nsHTTPServerListener::OnStopRequest (nsIChannel* channel, nsISupports* i_pContex ("nsHTTPServerListener::OnStopRequest [this=%x]." "\tStatus = %x\n", this, i_Status)); + if (!mDataReceived) + { + // no data has been received from the channel at all - must be due to the fact that the + // server has dropped the connection on keep-alive + + if (mPipelinedRequest) + { + nsresult rv = mPipelinedRequest -> RestartRequest (); + if (NS_SUCCEEDED (rv)) + return rv; + } + } + if (NS_SUCCEEDED(rv) && !mHeadersDone) { // diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.h b/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.h index 2266df6be02..c27893ca49a 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.h +++ b/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.h @@ -122,6 +122,7 @@ protected: PRBool mCompressHeaderChecked; PRBool mChunkHeaderChecked; + PRBool mDataReceived; PRBool mChunkHeaderEOF; nsHTTPPipelinedRequest* mPipelinedRequest; };