bug 623921: Out of an abundance of caution back out feature: 592284 - HTTP Syn Retry r=honzab a=backout

This commit is contained in:
Patrick McManus 2011-01-07 11:11:22 -05:00
parent 6137ed3ea4
commit 4016cea6b9
11 changed files with 81 additions and 432 deletions

View File

@ -736,11 +736,6 @@ pref("network.http.prompt-temp-redirect", true);
// Section 4.8 "High-Throughput Data Service Class"
pref("network.http.qos", 0);
// The number of milliseconds after sending a SYN for an HTTP connection,
// to wait before trying a different connection. 0 means do not use a second
// connection.
pref("network.http.connection-retry-timeout", 250);
// default values for FTP
// in a DSCP environment this should be 40 (0x28, or AF11), per RFC-4594,
// Section 4.8 "High-Throughput Data Service Class", and 80 (0x50, or AF22)

View File

@ -1778,20 +1778,9 @@ nsSocketTransport::GetSecurityCallbacks(nsIInterfaceRequestor **callbacks)
NS_IMETHODIMP
nsSocketTransport::SetSecurityCallbacks(nsIInterfaceRequestor *callbacks)
{
nsCOMPtr<nsISupports> secinfo;
{
nsAutoLock lock(mLock);
mCallbacks = callbacks;
SOCKET_LOG(("Reset callbacks for secinfo=%p callbacks=%p\n", mSecInfo.get(), mCallbacks.get()));
secinfo = mSecInfo;
}
// don't call into PSM while holding mLock!!
nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(secinfo));
if (secCtrl)
secCtrl->SetNotificationCallbacks(callbacks);
nsAutoLock lock(mLock);
mCallbacks = callbacks;
// XXX should we tell PSM about this?
return NS_OK;
}

View File

@ -44,7 +44,6 @@ class nsAHttpConnection;
class nsAHttpSegmentReader;
class nsAHttpSegmentWriter;
class nsIInterfaceRequestor;
class nsIEventTarget;
//----------------------------------------------------------------------------
// Abstract base class for a HTTP transaction:
@ -63,8 +62,7 @@ public:
// called by the connection to get security callbacks to set on the
// socket transport.
virtual void GetSecurityCallbacks(nsIInterfaceRequestor **,
nsIEventTarget **) = 0;
virtual void GetSecurityCallbacks(nsIInterfaceRequestor **) = 0;
// called to report socket status (see nsITransportEventSink)
virtual void OnTransportStatus(nsresult status, PRUint64 progress) = 0;
@ -90,8 +88,7 @@ public:
#define NS_DECL_NSAHTTPTRANSACTION \
void SetConnection(nsAHttpConnection *); \
void GetSecurityCallbacks(nsIInterfaceRequestor **, \
nsIEventTarget **); \
void GetSecurityCallbacks(nsIInterfaceRequestor **); \
void OnTransportStatus(nsresult status, PRUint64 progress); \
PRBool IsDone(); \
nsresult Status(); \

View File

@ -51,7 +51,6 @@
#include "netCore.h"
#include "nsNetCID.h"
#include "nsAutoLock.h"
#include "nsProxyRelease.h"
#include "prmem.h"
#ifdef DEBUG
@ -61,17 +60,6 @@ extern PRThread *gSocketThread;
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
// Statistics - only update on gSocketThread
// currently uncollected
static PRUint32 sCreateTransport1 = 0;
static PRUint32 sCreateTransport2 = 0;
static PRUint32 sSuccessTransport1 = 0;
static PRUint32 sSuccessTransport2 = 0;
static PRUint32 sUnNecessaryTransport2 = 0;
static PRUint32 sWastedReuseCount = 0;
//-----------------------------------------------------------------------------
// nsHttpConnection <public>
//-----------------------------------------------------------------------------
@ -87,7 +75,6 @@ nsHttpConnection::nsHttpConnection()
, mSupportsPipelining(PR_FALSE) // assume low-grade server
, mIsReused(PR_FALSE)
, mCompletedSSLConnect(PR_FALSE)
, mActivationCount(0)
{
LOG(("Creating nsHttpConnection @%x\n", this));
@ -99,15 +86,9 @@ nsHttpConnection::nsHttpConnection()
nsHttpConnection::~nsHttpConnection()
{
LOG(("Destroying nsHttpConnection @%x\n", this));
CancelSynTimer();
if (mBackupConnection) {
gHttpHandler->ReclaimConnection(mBackupConnection);
mBackupConnection = nsnull;
}
ReleaseCallbacks();
NS_IF_RELEASE(mConnInfo);
NS_IF_RELEASE(mTransaction);
if (mLock) {
PR_DestroyLock(mLock);
@ -119,25 +100,6 @@ nsHttpConnection::~nsHttpConnection()
NS_RELEASE(handler);
}
void
nsHttpConnection::ReleaseCallbacks()
{
if (mCallbacks) {
nsIInterfaceRequestor *cbs = nsnull;
mCallbacks.swap(cbs);
NS_ProxyRelease(mCallbackTarget, cbs);
}
}
void
nsHttpConnection::CancelSynTimer()
{
if (mIdleSynTimer) {
mIdleSynTimer->Cancel();
mIdleSynTimer = nsnull;
}
}
nsresult
nsHttpConnection::Init(nsHttpConnectionInfo *info, PRUint16 maxHangTime)
{
@ -158,59 +120,12 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info, PRUint16 maxHangTime)
return NS_OK;
}
void
nsHttpConnection::IdleSynTimeout(nsITimer *timer, void *closure)
{
// nsITimer is guaranteed to execute timer on same thread it
// was initialized on
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
nsHttpConnection *self = (nsHttpConnection *)closure;
NS_ABORT_IF_FALSE(timer == self->mIdleSynTimer, "wrong timer");
self->mIdleSynTimer = nsnull;
if (!self->mSocketTransport) {
NS_ABORT_IF_FALSE(self->mSocketTransport1 && !self->mSocketTransport2,
"establishing backup tranport");
LOG(("SocketTransport hit idle timer - starting backup socket"));
// if we have already cleared ::CloseTransaction, then we do not
// need to create the backup connection
if (!self->mTransaction)
return;
gHttpHandler->ConnMgr()->GetConnection(self->mConnInfo,
self->mSocketCaps,
getter_AddRefs(
self->mBackupConnection));
if (!self->mBackupConnection)
return;
nsresult rv =
self->CreateTransport(self->mSocketCaps,
getter_AddRefs(self->mSocketTransport2),
getter_AddRefs(self->mSocketIn2),
getter_AddRefs(self->mSocketOut2));
if (NS_SUCCEEDED(rv)) {
sCreateTransport2++;
self->mTransaction->
GetSecurityCallbacks(
getter_AddRefs(self->mCallbacks),
getter_AddRefs(self->mCallbackTarget));
self->mSocketOut2->AsyncWait(self, 0, 0, nsnull);
}
}
return;
}
// called on the socket thread
nsresult
nsHttpConnection::Activate(nsAHttpTransaction *trans, PRUint8 caps)
{
nsresult rv;
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
LOG(("nsHttpConnection::Activate [this=%x trans=%x caps=%x]\n",
this, trans, caps));
@ -219,47 +134,32 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, PRUint8 caps)
// take ownership of the transaction
mTransaction = trans;
mActivationCount++;
ReleaseCallbacks();
NS_ADDREF(mTransaction);
// set mKeepAlive according to what will be requested
mKeepAliveMask = mKeepAlive = (caps & NS_HTTP_ALLOW_KEEPALIVE);
// if we don't have a socket transport then create a new one
if (!mSocketTransport) {
rv = CreateTransport(caps);
if (NS_FAILED(rv))
goto loser;
}
// need to handle SSL proxy CONNECT if this is the first time.
if (mConnInfo->UsingSSL() && mConnInfo->UsingHttpProxy() && !mCompletedSSLConnect) {
rv = SetupSSLProxyConnect();
if (NS_FAILED(rv))
goto failed_activation;
goto loser;
}
// if we don't have a socket transport then create a new one
if (!mSocketTransport) {
rv = CreateTransport(caps);
}
else {
NS_ABORT_IF_FALSE(mSocketOut && mSocketIn,
"Socket Transport and SocketOut mismatch");
// If this is the first transaction on this connection, but
// we already have a socket that means the socket was created
// speculatively in the past, not used at that time, and
// given to the connection manager.
if (mActivationCount == 1) {
sWastedReuseCount++;
rv = mSocketTransport->SetEventSink(this, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
rv = mSocketTransport->SetSecurityCallbacks(this);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mSocketOut->AsyncWait(this, 0, 0, nsnull);
}
failed_activation:
if (NS_FAILED(rv)) {
mTransaction = nsnull;
CancelSynTimer();
}
// wait for the output stream to be readable
rv = mSocketOut->AsyncWait(this, 0, 0, nsnull);
if (NS_SUCCEEDED(rv))
return rv;
loser:
NS_RELEASE(mTransaction);
return rv;
}
@ -268,7 +168,7 @@ nsHttpConnection::Close(nsresult reason)
{
LOG(("nsHttpConnection::Close [this=%x reason=%x]\n", this, reason));
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
if (NS_FAILED(reason)) {
if (mSocketTransport) {
@ -276,18 +176,6 @@ nsHttpConnection::Close(nsresult reason)
mSocketTransport->SetEventSink(nsnull, nsnull);
mSocketTransport->Close(reason);
}
if (mSocketTransport1) {
mSocketTransport1->SetSecurityCallbacks(nsnull);
mSocketTransport1->SetEventSink(nsnull, nsnull);
mSocketTransport1->Close(reason);
}
if (mSocketTransport2) {
mSocketTransport2->SetSecurityCallbacks(nsnull);
mSocketTransport2->SetEventSink(nsnull, nsnull);
mSocketTransport2->Close(reason);
}
mKeepAlive = PR_FALSE;
}
}
@ -518,7 +406,7 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans,
// processing a transaction pipeline until after the first HTTP/1.1
// response.
nsHttpTransaction *trans =
static_cast<nsHttpTransaction *>(mTransaction.get());
static_cast<nsHttpTransaction *>(mTransaction);
trans->SetSSLConnectFailed();
}
}
@ -572,51 +460,9 @@ nsHttpConnection::ResumeRecv()
nsresult
nsHttpConnection::CreateTransport(PRUint8 caps)
{
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
NS_ABORT_IF_FALSE(!mSocketTransport, "unexpected");
nsresult rv;
mSocketCaps = caps;
sCreateTransport1++;
PRUint16 timeout = gHttpHandler->GetIdleSynTimeout();
if (timeout) {
// Setup the timer that will establish a backup socket
// if we do not get a writable event on the main one.
// We do this because a lost SYN takes a very long time
// to repair at the TCP level.
//
// Failure to setup the timer is something we can live with,
// so don't return an error in that case.
mIdleSynTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
mIdleSynTimer->InitWithFuncCallback(IdleSynTimeout, this,
timeout,
nsITimer::TYPE_ONE_SHOT);
}
rv = CreateTransport(mSocketCaps,
getter_AddRefs(mSocketTransport1),
getter_AddRefs(mSocketIn1),
getter_AddRefs(mSocketOut1));
if (NS_FAILED(rv))
return rv;
// wait for the output stream to be readable or timeout to occur
return mSocketOut1->AsyncWait(this, 0, 0, nsnull);
}
nsresult
nsHttpConnection::CreateTransport(PRUint8 caps,
nsISocketTransport **sock,
nsIAsyncInputStream **instream,
nsIAsyncOutputStream **outstream)
{
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
nsresult rv;
NS_PRECONDITION(!mSocketTransport, "unexpected");
nsCOMPtr<nsISocketTransportService> sts =
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
@ -668,21 +514,9 @@ nsHttpConnection::CreateTransport(PRUint8 caps,
getter_AddRefs(sin));
if (NS_FAILED(rv)) return rv;
strans.forget(sock);
CallQueryInterface(sin, instream);
CallQueryInterface(sout, outstream);
return NS_OK;
}
nsresult
nsHttpConnection::AssignTransport(nsISocketTransport *sock,
nsIAsyncOutputStream *outs,
nsIAsyncInputStream *ins)
{
mSocketTransport = sock;
mSocketOut = outs;
mSocketIn = ins;
mSocketTransport = strans;
mSocketIn = do_QueryInterface(sin);
mSocketOut = do_QueryInterface(sout);
return NS_OK;
}
@ -700,7 +534,9 @@ nsHttpConnection::CloseTransaction(nsAHttpTransaction *trans, nsresult reason)
reason = NS_OK;
mTransaction->Close(reason);
mTransaction = nsnull;
NS_RELEASE(mTransaction);
mTransaction = 0;
if (NS_FAILED(reason))
Close(reason);
@ -911,8 +747,7 @@ nsHttpConnection::SetupSSLProxyConnect()
// NOTE: this cast is valid since this connection cannot be processing a
// transaction pipeline until after the first HTTP/1.1 response.
nsHttpTransaction *trans =
static_cast<nsHttpTransaction *>(mTransaction.get());
nsHttpTransaction *trans = static_cast<nsHttpTransaction *>(mTransaction);
val = trans->RequestHead()->PeekHeader(nsHttp::Host);
if (val) {
@ -935,85 +770,6 @@ nsHttpConnection::SetupSSLProxyConnect()
return NS_NewCStringInputStream(getter_AddRefs(mSSLProxyConnectStream), buf);
}
void
nsHttpConnection::ReleaseBackupTransport(nsISocketTransport *sock,
nsIAsyncOutputStream *outs,
nsIAsyncInputStream *ins)
{
// We need to establish a small non-zero idle timeout so the connection
// mgr perceives this socket as suitable for persistent connection reuse
NS_ABORT_IF_FALSE(sock && outs && ins, "release Backup precond");
mBackupConnection->mIdleTimeout = NS_MIN((PRUint16) 5,
gHttpHandler->IdleTimeout());
mBackupConnection->mIsReused = PR_TRUE;
nsresult rv = mBackupConnection->AssignTransport(sock, outs, ins);
if (NS_SUCCEEDED(rv))
rv = gHttpHandler->ReclaimConnection(mBackupConnection);
if (NS_FAILED(rv))
NS_WARNING("Backup nsHttpConnection could not be reclaimed");
mBackupConnection = nsnull;
}
void
nsHttpConnection::SelectPrimaryTransport(nsIAsyncOutputStream *out)
{
LOG(("nsHttpConnection::SelectPrimaryTransport(out=%p), mSocketOut1=%p, mSocketOut2=%p, mSocketOut=%p",
out, mSocketOut1.get(), mSocketOut2.get(), mSocketOut.get()));
if (!mSocketOut) {
// Setup the Main Socket
CancelSynTimer();
if (out == mSocketOut1) {
sSuccessTransport1++;
mSocketTransport.swap(mSocketTransport1);
mSocketOut.swap(mSocketOut1);
mSocketIn.swap(mSocketIn1);
if (mSocketTransport2)
sUnNecessaryTransport2++;
}
else if (out == mSocketOut2) {
NS_ABORT_IF_FALSE(mSocketOut1,
"backup socket without primary being tested");
sSuccessTransport2++;
mSocketTransport.swap(mSocketTransport2);
mSocketOut.swap(mSocketOut2);
mSocketIn.swap(mSocketIn2);
}
else {
NS_ABORT_IF_FALSE(0, "setup on unexpected socket");
return;
}
}
else if (out == mSocketOut1) {
// Socket2 became the primary socket but Socket1 is now valid - give it
// to the connection manager
ReleaseBackupTransport(mSocketTransport1,
mSocketOut1,
mSocketIn1);
sSuccessTransport1++;
mSocketTransport1 = nsnull;
mSocketOut1 = nsnull;
mSocketIn1 = nsnull;
}
else if (out == mSocketOut2) {
// Socket1 became the primary socket but Socket2 is now valid - give it
// to the connectionmanager
ReleaseBackupTransport(mSocketTransport2,
mSocketOut2,
mSocketIn2);
sSuccessTransport2++;
mSocketTransport2 = nsnull;
mSocketOut2 = nsnull;
mSocketIn2 = nsnull;
}
}
//-----------------------------------------------------------------------------
// nsHttpConnection::nsISupports
//-----------------------------------------------------------------------------
@ -1055,13 +811,8 @@ nsHttpConnection::OnInputStreamReady(nsIAsyncInputStream *in)
NS_IMETHODIMP
nsHttpConnection::OnOutputStreamReady(nsIAsyncOutputStream *out)
{
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
NS_ABORT_IF_FALSE(out == mSocketOut ||
out == mSocketOut1 ||
out == mSocketOut2 , "unexpected socket");
if (out != mSocketOut)
SelectPrimaryTransport(out);
NS_ASSERTION(out == mSocketOut, "unexpected stream");
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
// if the transaction was dropped...
if (!mTransaction) {
@ -1069,12 +820,9 @@ nsHttpConnection::OnOutputStreamReady(nsIAsyncOutputStream *out)
return NS_OK;
}
if (mSocketOut == out) {
NS_ABORT_IF_FALSE(!mIdleSynTimer,"IdleSynTimer should not be set");
nsresult rv = OnSocketWritable();
if (NS_FAILED(rv))
CloseTransaction(mTransaction, rv);
}
nsresult rv = OnSocketWritable();
if (NS_FAILED(rv))
CloseTransaction(mTransaction, rv);
return NS_OK;
}
@ -1107,12 +855,13 @@ nsHttpConnection::GetInterface(const nsIID &iid, void **result)
// have to worry about the possibility of mTransaction going away
// part-way through this function call. See CloseTransaction.
NS_ASSERTION(PR_GetCurrentThread() != gSocketThread, "wrong thread");
nsCOMPtr<nsIInterfaceRequestor> callbacks = mCallbacks;
if (!callbacks && mTransaction)
mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks), nsnull);
if (callbacks)
return callbacks->GetInterface(iid, result);
if (mTransaction) {
nsCOMPtr<nsIInterfaceRequestor> callbacks;
mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
if (callbacks)
return callbacks->GetInterface(iid, result);
}
return NS_ERROR_NO_INTERFACE;
}

View File

@ -53,8 +53,6 @@
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsIInterfaceRequestor.h"
#include "nsIEventTarget.h"
#include "nsITimer.h"
//-----------------------------------------------------------------------------
// nsHttpConnection - represents a connection to a HTTP server (or proxy)
@ -133,14 +131,6 @@ private:
nsresult ProxyStartSSL();
nsresult CreateTransport(PRUint8 caps);
nsresult CreateTransport(PRUint8 caps,
nsISocketTransport **sock,
nsIAsyncInputStream **instream,
nsIAsyncOutputStream **outstream);
nsresult AssignTransport(nsISocketTransport *sock,
nsIAsyncOutputStream *outs,
nsIAsyncInputStream *ins);
nsresult OnTransactionDone(nsresult reason);
nsresult OnSocketWritable();
nsresult OnSocketReadable();
@ -150,13 +140,6 @@ private:
PRBool IsAlive();
PRBool SupportsPipelining(nsHttpResponseHead *);
static void IdleSynTimeout(nsITimer *, void *);
void SelectPrimaryTransport(nsIAsyncOutputStream *out);
void ReleaseBackupTransport(nsISocketTransport *sock,
nsIAsyncOutputStream *outs,
nsIAsyncInputStream *ins);
void CancelSynTimer();
void ReleaseCallbacks();
private:
nsCOMPtr<nsISocketTransport> mSocketTransport;
nsCOMPtr<nsIAsyncInputStream> mSocketIn;
@ -168,16 +151,7 @@ private:
nsCOMPtr<nsIInputStream> mSSLProxyConnectStream;
nsCOMPtr<nsIInputStream> mRequestStream;
// mTransaction only points to the HTTP Transaction callbacks if the
// transaction is open, otherwise it is null.
nsRefPtr<nsAHttpTransaction> mTransaction;
// The security callbacks are only stored if we initiate a
// backup connection because they need to be proxy released
// on the main thread.
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIEventTarget> mCallbackTarget;
nsAHttpTransaction *mTransaction; // hard ref
nsHttpConnectionInfo *mConnInfo; // hard ref
PRLock *mLock;
@ -191,22 +165,6 @@ private:
PRPackedBool mSupportsPipelining;
PRPackedBool mIsReused;
PRPackedBool mCompletedSSLConnect;
PRUint32 mActivationCount;
// These items are used to implement a parallel connection opening
// attempt when network.http.connection-retry-timeout has expired
PRUint8 mSocketCaps;
nsCOMPtr<nsITimer> mIdleSynTimer;
nsRefPtr<nsHttpConnection> mBackupConnection;
nsCOMPtr<nsISocketTransport> mSocketTransport1;
nsCOMPtr<nsIAsyncInputStream> mSocketIn1;
nsCOMPtr<nsIAsyncOutputStream> mSocketOut1;
nsCOMPtr<nsISocketTransport> mSocketTransport2;
nsCOMPtr<nsIAsyncInputStream> mSocketIn2;
nsCOMPtr<nsIAsyncOutputStream> mSocketOut2;
};
#endif // nsHttpConnection_h__

View File

@ -400,21 +400,13 @@ nsHttpConnectionMgr::ProcessOneTransactionCB(nsHashKey *key, void *data, void *c
return kHashEnumerateNext;
}
// If the global number of idle connections is preventing the opening of
// new connections to a host without idle connections, then
// close them regardless of their TTL
PRIntn
nsHttpConnectionMgr::PurgeExcessIdleConnectionsCB(nsHashKey *key,
void *data, void *closure)
nsHttpConnectionMgr::PurgeOneIdleConnectionCB(nsHashKey *key, void *data, void *closure)
{
nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
nsConnectionEntry *ent = (nsConnectionEntry *) data;
while (self->mNumIdleConns + self->mNumActiveConns + 1 >= self->mMaxConns) {
if (!ent->mIdleConns.Length()) {
// There are no idle conns left in this connection entry
return kHashEnumerateNext;
}
if (ent->mIdleConns.Length() > 0) {
nsHttpConnection *conn = ent->mIdleConns[0];
ent->mIdleConns.RemoveElementAt(0);
conn->Close(NS_ERROR_ABORT);
@ -422,8 +414,10 @@ nsHttpConnectionMgr::PurgeExcessIdleConnectionsCB(nsHashKey *key,
self->mNumIdleConns--;
if (0 == self->mNumIdleConns)
self->StopPruneDeadConnectionsTimer();
return kHashEnumerateStop;
}
return kHashEnumerateStop;
return kHashEnumerateNext;
}
PRIntn
@ -598,8 +592,8 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 cap
LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n",
ci->HashKey().get(), caps));
// If there are more active connections than the global limit, then we're
// done. Purging idle connections won't get us below it.
// If we have more active connections than the limit, then we're done --
// purging idle connections won't get us below it.
if (mNumActiveConns >= mMaxConns) {
LOG((" num active conns == max conns\n"));
return PR_TRUE;
@ -636,18 +630,6 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 cap
(persistCount >= maxPersistConns) );
}
void
nsHttpConnectionMgr::GetConnection(nsHttpConnectionInfo *ci,
PRUint8 caps,
nsHttpConnection **result)
{
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
nsCStringKey key(ci->HashKey());
nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
if (!ent) return;
GetConnection(ent, caps, result);
}
void
nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
nsHttpConnection **result)
@ -655,19 +637,12 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
LOG(("nsHttpConnectionMgr::GetConnection [ci=%s caps=%x]\n",
ent->mConnInfo->HashKey().get(), PRUint32(caps)));
// First, see if an idle persistent connection may be reused instead of
// establishing a new socket. We do not need to check the connection limits
// yet as they govern the maximum number of open connections and reusing
// an old connection never increases that.
*result = nsnull;
nsHttpConnection *conn = nsnull;
if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
// search the idle connection list. Each element in the list
// has a reference, so if we remove it from the list into a local
// ptr, that ptr now owns the reference
// search the idle connection list
while (!conn && (ent->mIdleConns.Length() > 0)) {
conn = ent->mIdleConns[0];
// we check if the connection can be reused before even checking if
@ -697,7 +672,7 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
// XXX this just purges a random idle connection. we should instead
// enumerate the entire hash table to find the eldest idle connection.
if (mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 >= mMaxConns)
mCT.Enumerate(PurgeExcessIdleConnectionsCB, this);
mCT.Enumerate(PurgeOneIdleConnectionCB, this);
// Need to make a new TCP connection. First, we check if we've hit
// either the maximum connection limit globally or for this particular
@ -708,7 +683,10 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
}
conn = new nsHttpConnection();
if (!conn)
return;
NS_ADDREF(conn);
nsresult rv = conn->Init(ent->mConnInfo, mMaxRequestDelay);
if (NS_FAILED(rv)) {
NS_RELEASE(conn);
@ -716,11 +694,6 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
}
}
// hold an owning ref to this connection
ent->mActiveConns.AppendElement(conn);
mNumActiveConns++;
NS_ADDREF(conn);
*result = conn;
}
@ -745,6 +718,11 @@ nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent,
trans = pipeline;
}
// hold an owning ref to this connection
ent->mActiveConns.AppendElement(conn);
mNumActiveConns++;
NS_ADDREF(conn);
// give the transaction the indirect reference to the connection.
trans->SetConnection(handle);
@ -859,6 +837,15 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans)
// destroy connection handle.
trans->SetConnection(nsnull);
// remove sticky connection from active connection list; we'll add it
// right back in DispatchTransaction.
if (ent->mActiveConns.RemoveElement(conn))
mNumActiveConns--;
else {
NS_ERROR("sticky connection not found in active list");
return NS_ERROR_UNEXPECTED;
}
}
else
GetConnection(ent, caps, &conn);
@ -1011,22 +998,13 @@ nsHttpConnectionMgr::OnMsgReclaimConnection(PRInt32, void *param)
NS_ASSERTION(ent, "no connection entry");
if (ent) {
// If the connection is in the active list, remove that entry
// and the reference held by the mActiveConns list.
// This is never the final reference on conn as the event context
// is also holding one that is released at the end of this function.
if (ent->mActiveConns.RemoveElement(conn)) {
nsHttpConnection *temp = conn;
NS_RELEASE(temp);
mNumActiveConns--;
}
ent->mActiveConns.RemoveElement(conn);
mNumActiveConns--;
if (conn->CanReuse()) {
LOG((" adding connection to idle list\n"));
// hold onto this connection in the idle list. we push it to
// the end of the list so as to ensure that we'll visit older
// connections first before getting to this one.
NS_ADDREF(conn);
ent->mIdleConns.AppendElement(conn);
mNumIdleConns++;
// If the added connection was first idle connection or has shortest
@ -1040,6 +1018,8 @@ nsHttpConnectionMgr::OnMsgReclaimConnection(PRInt32, void *param)
LOG((" connection cannot be reused; closing connection\n"));
// make sure the connection is closed and release our reference.
conn->Close(NS_ERROR_ABORT);
nsHttpConnection *temp = conn;
NS_RELEASE(temp);
}
}

View File

@ -137,9 +137,6 @@ public:
// preference to the specified connection.
nsresult ProcessPendingQ(nsHttpConnectionInfo *);
// called to reserve a nshttpconnection object with the manager
void GetConnection(nsHttpConnectionInfo *, PRUint8 caps,
nsHttpConnection **);
private:
virtual ~nsHttpConnectionMgr();
@ -209,10 +206,10 @@ private:
//-------------------------------------------------------------------------
static PRIntn ProcessOneTransactionCB(nsHashKey *, void *, void *);
static PRIntn PurgeOneIdleConnectionCB(nsHashKey *, void *, void *);
static PRIntn PruneDeadConnectionsCB(nsHashKey *, void *, void *);
static PRIntn ShutdownPassCB(nsHashKey *, void *, void *);
static PRIntn PurgeExcessIdleConnectionsCB(nsHashKey *, void *, void *);
PRBool ProcessPendingQForEntry(nsConnectionEntry *);
PRBool AtActiveConnectionLimit(nsConnectionEntry *, PRUint8 caps);
void GetConnection(nsConnectionEntry *, PRUint8 caps, nsHttpConnection **);

View File

@ -178,7 +178,6 @@ nsHttpHandler::nsHttpHandler()
, mIdleTimeout(10)
, mMaxRequestAttempts(10)
, mMaxRequestDelay(10)
, mIdleSynTimeout(250)
, mMaxConnections(24)
, mMaxConnectionsPerServer(8)
, mMaxPersistentConnectionsPerServer(2)
@ -919,12 +918,6 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
mRedirectionLimit = (PRUint8) NS_CLAMP(val, 0, 0xff);
}
if (PREF_CHANGED(HTTP_PREF("connection-retry-timeout"))) {
rv = prefs->GetIntPref(HTTP_PREF("connection-retry-timeout"), &val);
if (NS_SUCCEEDED(rv))
mIdleSynTimeout = (PRUint16) NS_CLAMP(val, 0, 3000);
}
if (PREF_CHANGED(HTTP_PREF("version"))) {
nsXPIDLCString httpVersion;
prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));

View File

@ -107,7 +107,6 @@ public:
nsIIDNService *IDNConverter() { return mIDNConverter; }
PRUint32 PhishyUserPassLength() { return mPhishyUserPassLength; }
PRUint8 GetQoSBits() { return mQoSBits; }
PRUint16 GetIdleSynTimeout() { return mIdleSynTimeout; }
PRBool IsPersistentHttpsCachingEnabled() { return mEnablePersistentHttpsCaching; }
@ -264,7 +263,6 @@ private:
PRUint16 mIdleTimeout;
PRUint16 mMaxRequestAttempts;
PRUint16 mMaxRequestDelay;
PRUint16 mIdleSynTimeout;
PRUint16 mMaxConnections;
PRUint8 mMaxConnectionsPerServer;

View File

@ -310,20 +310,16 @@ nsHttpPipeline::SetConnection(nsAHttpConnection *conn)
}
void
nsHttpPipeline::GetSecurityCallbacks(nsIInterfaceRequestor **result,
nsIEventTarget **target)
nsHttpPipeline::GetSecurityCallbacks(nsIInterfaceRequestor **result)
{
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
// return security callbacks from first request
nsAHttpTransaction *trans = Request(0);
if (trans)
trans->GetSecurityCallbacks(result, target);
else {
trans->GetSecurityCallbacks(result);
else
*result = nsnull;
if (target)
*target = nsnull;
}
}
void

View File

@ -328,12 +328,9 @@ nsHttpTransaction::SetConnection(nsAHttpConnection *conn)
}
void
nsHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **cb,
nsIEventTarget **target)
nsHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **cb)
{
NS_IF_ADDREF(*cb = mCallbacks);
if (target)
NS_IF_ADDREF(*target = mConsumerTarget);
}
void