Never recycle the socket transport if the server responded with Connection: close

This commit is contained in:
ruslan%netscape.com 2000-03-21 01:36:18 +00:00
parent 2fa72ac8a2
commit b096f987bc
8 changed files with 81 additions and 29 deletions

View File

@ -1404,12 +1404,12 @@ nsresult nsHTTPChannel::ResponseCompleted(nsIStreamListener *aListener,
return rv; return rv;
} }
nsresult nsHTTPChannel::ReleaseTransport(nsIChannel *aTransport) nsresult nsHTTPChannel::ReleaseTransport (nsIChannel *aTransport, PRBool keepAlive)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
if (aTransport) { if (aTransport) {
(void) mRequest->ReleaseTransport (aTransport); (void) mRequest->ReleaseTransport (aTransport);
rv = mHandler->ReleaseTransport(aTransport); rv = mHandler->ReleaseTransport (aTransport, keepAlive);
} }
return rv; return rv;

View File

@ -98,7 +98,7 @@ public:
nsresult ResponseCompleted(nsIStreamListener* aListener, nsresult ResponseCompleted(nsIStreamListener* aListener,
nsresult aStatus, nsresult aStatus,
const PRUnichar* aMsg); const PRUnichar* aMsg);
nsresult ReleaseTransport(nsIChannel *aTransport); nsresult ReleaseTransport (nsIChannel *aTransport, PRBool keepAlive = PR_FALSE);
nsresult SetResponse(nsHTTPResponse* i_pResp); nsresult SetResponse(nsHTTPResponse* i_pResp);
nsresult GetResponseContext(nsISupports** aContext); nsresult GetResponseContext(nsISupports** aContext);

View File

@ -954,7 +954,7 @@ nsresult nsHTTPHandler::CreateTransport(const char* host,
o_pTrans); o_pTrans);
} }
nsresult nsHTTPHandler::ReleaseTransport(nsIChannel* i_pTrans) nsresult nsHTTPHandler::ReleaseTransport(nsIChannel* i_pTrans, PRBool keepAlive)
{ {
nsresult rv; nsresult rv;
PRUint32 count=0, transportsInUseCount = 0; PRUint32 count=0, transportsInUseCount = 0;
@ -974,7 +974,7 @@ nsresult nsHTTPHandler::ReleaseTransport(nsIChannel* i_pTrans)
rv = mTransportList->RemoveElement(i_pTrans); rv = mTransportList->RemoveElement(i_pTrans);
NS_ASSERTION(NS_SUCCEEDED(rv), "Transport not in table..."); NS_ASSERTION(NS_SUCCEEDED(rv), "Transport not in table...");
if (mDoKeepAlive) if (mDoKeepAlive && keepAlive)
{ {
nsresult rv; nsresult rv;
nsCOMPtr<nsISocketTransport> trans = do_QueryInterface (i_pTrans, &rv); nsCOMPtr<nsISocketTransport> trans = do_QueryInterface (i_pTrans, &rv);

View File

@ -81,7 +81,7 @@ public:
nsIChannel** o_pTrans); nsIChannel** o_pTrans);
/* Remove this transport from the list. */ /* Remove this transport from the list. */
virtual nsresult ReleaseTransport(nsIChannel* i_pTrans); virtual nsresult ReleaseTransport(nsIChannel* i_pTrans, PRBool keepAlive = PR_FALSE);
virtual nsresult CancelPendingChannel(nsHTTPChannel* aChannel); virtual nsresult CancelPendingChannel(nsHTTPChannel* aChannel);
PRTime GetSessionStartTime() { return mSessionStartTime; } PRTime GetSessionStartTime() { return mSessionStartTime; }

View File

@ -52,6 +52,7 @@ nsHTTPResponse::nsHTTPResponse()
// The content length is unknown... // The content length is unknown...
mContentLength = -1; mContentLength = -1;
mChunkedResponse = PR_FALSE; mChunkedResponse = PR_FALSE;
mConnectionToken = HTTP_CONNECTION_TOKEN_NONE;
} }
nsHTTPResponse::~nsHTTPResponse() nsHTTPResponse::~nsHTTPResponse()
@ -424,7 +425,9 @@ nsresult nsHTTPResponse::ProcessHeader(nsIAtom* aHeader, nsCString& aValue)
// When the Content-Length response header is processed, set the // When the Content-Length response header is processed, set the
// ContentLength in the response ... // ContentLength in the response ...
// //
else if (nsHTTPAtoms::Content_Length == aHeader) { else
if (nsHTTPAtoms::Content_Length == aHeader)
{
PRInt32 length, status; PRInt32 length, status;
length = aValue.ToInteger(&status); length = aValue.ToInteger(&status);
@ -434,9 +437,20 @@ nsresult nsHTTPResponse::ProcessHeader(nsIAtom* aHeader, nsCString& aValue)
SetContentLength(length); SetContentLength(length);
} }
} }
else if (nsHTTPAtoms::Transfer_Encoding == aHeader && else
!PL_strcmp(aValue, "chunked")) if (nsHTTPAtoms::Transfer_Encoding == aHeader && !PL_strcmp(aValue, "chunked"))
mChunkedResponse = PR_TRUE; mChunkedResponse = PR_TRUE;
else
if (nsHTTPAtoms::Connection == aHeader)
{
if (!PL_strcasecmp (aValue, "close"))
mConnectionToken = HTTP_CONNECTION_TOKEN_CLOSE;
else
if (!PL_strcasecmp (aValue, "keep-alive"))
mConnectionToken = HTTP_CONNECTION_TOKEN_KEEPALIVE;
else
mConnectionToken = HTTP_CONNECTION_TOKEN_UNKNOWN;
}
// //
// Set the response header... // Set the response header...
@ -524,6 +538,12 @@ PRBool nsHTTPResponse::isChunkedResponse ()
return mChunkedResponse; return mChunkedResponse;
} }
HTTPConnectionToken
nsHTTPResponse::GetHttpConnectionToken ()
{
return mConnectionToken;
}
// Check to see if a (cached) HTTP response is stale and, therefore, // Check to see if a (cached) HTTP response is stale and, therefore,
// must be revalidated with the origin server. // must be revalidated with the origin server.
// //

View File

@ -40,6 +40,11 @@
-Gagan Saksena 03/29/99 -Gagan Saksena 03/29/99
*/ */
typedef enum {
HTTP_CONNECTION_TOKEN_UNKNOWN, HTTP_CONNECTION_TOKEN_NONE, HTTP_CONNECTION_TOKEN_CLOSE, HTTP_CONNECTION_TOKEN_KEEPALIVE
} HTTPConnectionToken;
class nsHTTPResponse : public nsISupports class nsHTTPResponse : public nsISupports
{ {
@ -79,6 +84,7 @@ public:
PRBool IsStale(PRBool aUseHeuristicExpiration); PRBool IsStale(PRBool aUseHeuristicExpiration);
PRBool isChunkedResponse (); PRBool isChunkedResponse ();
HTTPConnectionToken GetHttpConnectionToken ();
nsresult UpdateHeaders(nsISimpleEnumerator *aEnumerator); nsresult UpdateHeaders(nsISimpleEnumerator *aEnumerator);
@ -98,6 +104,7 @@ protected:
nsHTTPHeaderArray mHeaders; nsHTTPHeaderArray mHeaders;
private: private:
PRBool mChunkedResponse; PRBool mChunkedResponse;
HTTPConnectionToken mConnectionToken;
}; };
#endif /* _nsHTTPResponse_h_ */ #endif /* _nsHTTPResponse_h_ */

View File

@ -453,7 +453,32 @@ nsHTTPServerListener::OnStopRequest(nsIChannel* channel,
("nsHTTPServerListener::OnStopRequest [this=%x]. " ("nsHTTPServerListener::OnStopRequest [this=%x]. "
"Discarding 304 response\n", this)); "Discarding 304 response\n", this));
} }
mChannel->ReleaseTransport(channel); PRBool keepAlive = PR_FALSE;
if (mResponse)
{
HTTPVersion ver;
rv = mResponse -> GetServerVersion (&ver);
if (NS_SUCCEEDED (rv))
{
HTTPConnectionToken token = mResponse -> GetHttpConnectionToken ();
if (ver == HTTP_ONE_ONE )
{
// ruslan: some older incorrect 1.1 servers may do this
if (token != HTTP_CONNECTION_TOKEN_CLOSE)
keepAlive = PR_TRUE;
}
else
if (ver == HTTP_ONE_ZERO)
{
if (token == HTTP_CONNECTION_TOKEN_KEEPALIVE)
keepAlive = PR_TRUE;
}
}
}
mChannel -> ReleaseTransport (channel, keepAlive);
} }
NS_IF_RELEASE(mChannel); NS_IF_RELEASE(mChannel);