Fixes bug 80419 (part 2) "http should reclaim connections immediately"

r=bbaetz, rs=dougt, a=blizzard
This commit is contained in:
darin%netscape.com 2001-06-11 21:20:29 +00:00
parent 1f7dc204b3
commit cf3d4afb48
5 changed files with 232 additions and 206 deletions

View File

@ -38,29 +38,6 @@
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
//-----------------------------------------------------------------------------
// helpers...
//-----------------------------------------------------------------------------
static void *PR_CALLBACK
TransactionReleaseEventHandler(PLEvent *ev)
{
nsHttpTransaction *trans =
NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev));
LOG(("TransactionReleaseEventHandler [trans=%x refcnt=%u] calling release...\n",
trans, trans->RefCnt()));
NS_RELEASE(trans);
return 0;
}
static void PR_CALLBACK
TransactionReleaseDestroyHandler(PLEvent *ev)
{
delete ev;
}
//-----------------------------------------------------------------------------
// nsHttpConnection <public>
//-----------------------------------------------------------------------------
@ -86,10 +63,7 @@ nsHttpConnection::~nsHttpConnection()
NS_IF_RELEASE(mConnectionInfo);
mConnectionInfo = 0;
if (mTransaction) {
ProxyReleaseTransaction(mTransaction);
mTransaction = 0;
}
NS_IF_RELEASE(mTransaction);
// warning: this call could result in OnStopRequest being called. this
// is why we are careful to null out mTransaction and mConnectionInfo ;-)
@ -111,7 +85,7 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info)
return NS_OK;
}
// never called from the socket thread
// called from any thread
nsresult
nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
{
@ -125,22 +99,15 @@ nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
mTransaction = transaction;
NS_ADDREF(mTransaction);
// grab a reference to the calling thread's event queue.
mConsumerEventQ = 0;
nsCOMPtr<nsIEventQueueService> eqs;
nsHttpHandler::get()->GetEventQueueService(getter_AddRefs(eqs));
if (eqs)
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mConsumerEventQ));
// build a proxy for the progress event sink
mProgressSink = 0;
if (mTransaction->Callbacks()) {
if (mTransaction->Callbacks() && mTransaction->ConsumerEventQ()) {
nsCOMPtr<nsIProgressEventSink> temp = do_GetInterface(mTransaction->Callbacks());
if (temp) {
nsCOMPtr<nsIProxyObjectManager> mgr;
nsHttpHandler::get()->GetProxyObjectManager(getter_AddRefs(mgr));
if (mgr)
mgr->GetProxyForObject(mConsumerEventQ,
mgr->GetProxyForObject(mTransaction->ConsumerEventQ(),
NS_GET_IID(nsIProgressEventSink),
temp,
PROXY_ASYNC | PROXY_ALWAYS,
@ -429,26 +396,6 @@ nsHttpConnection::CreateTransport()
return rv;
}
nsresult
nsHttpConnection::ProxyReleaseTransaction(nsHttpTransaction *trans)
{
LOG(("nsHttpConnection::ProxyReleaseTransaction [this=%x trans=%x refcnt=%u]\n",
this, trans, trans->RefCnt()));
NS_ENSURE_TRUE(mConsumerEventQ, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_ARG_POINTER(trans);
PLEvent *event = new PLEvent;
if (!event)
return NS_ERROR_OUT_OF_MEMORY;
PL_InitEvent(event, trans,
TransactionReleaseEventHandler,
TransactionReleaseDestroyHandler);
return mConsumerEventQ->PostEvent(event);
}
nsresult
nsHttpConnection::SetupSSLProxyConnect()
{
@ -549,17 +496,15 @@ nsHttpConnection::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
mProgressSink = 0;
// make sure mTransaction is clear before calling OnStopTransaction
nsHttpTransaction *trans = mTransaction;
mTransaction = nsnull;
if (mTransaction) {
nsHttpTransaction *trans = mTransaction;
mTransaction = nsnull;
trans->OnStopTransaction(status);
trans->OnStopTransaction(status);
NS_RELEASE(trans);
}
// because this could be the last reference to the transaction and
// because we are on the socket transport thread, it is essential that
// this final release be proxied to the thread which called
// SetTransaction.
if (NS_FAILED(ProxyReleaseTransaction(trans)))
NS_NOTREACHED("proxy release of transaction failed");
nsHttpHandler::get()->ReclaimConnection(this);
}
// no point in returning anything else but NS_OK
return NS_OK;

View File

@ -45,6 +45,7 @@
#include "nsPrintfCString.h"
#include "nsCOMPtr.h"
#include "nsNetCID.h"
#include "nsAutoLock.h"
#include "prprf.h"
#if defined(XP_UNIX) || defined(XP_BEOS)
@ -143,6 +144,11 @@ nsHttpHandler::~nsHttpHandler()
mAuthCache = nsnull;
}
if (mConnectionLock) {
PR_DestroyLock(mConnectionLock);
mConnectionLock = nsnull;
}
mGlobalInstance = nsnull;
}
@ -186,6 +192,10 @@ nsHttpHandler::Init()
return rv;
}
mConnectionLock = PR_NewLock();
if (!mConnectionLock)
return NS_ERROR_OUT_OF_MEMORY;
mPrefs = do_GetService(kPrefServiceCID, &rv);
if (NS_FAILED(rv)) {
NS_WARNING("unable to continue without prefs service");
@ -326,75 +336,23 @@ nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy,
return NS_OK;
}
// may be called from any thread
nsresult
nsHttpHandler::InitiateTransaction(nsHttpTransaction *trans,
nsHttpConnectionInfo *ci,
PRBool failIfBusy)
{
nsresult rv;
LOG(("nsHttpHandler::InitiateTransaction\n"));
NS_ENSURE_ARG_POINTER(trans);
NS_ENSURE_ARG_POINTER(ci);
if ((mActiveConnections.Count() == mMaxConnections) ||
(CountActiveConnections(ci) == PRUint32(mMaxConnectionsPerServer))) {
LOG(("unable to perform the transaction at this time [trans=%x]\n", trans));
if (failIfBusy) return NS_ERROR_FAILURE;
return EnqueueTransaction(trans, ci);
}
nsAutoLock lock(mConnectionLock);
nsHttpConnection *conn = nsnull;
// search the idle connection list
PRInt32 i;
for (i=0; i<mIdleConnections.Count(); ++i) {
conn = (nsHttpConnection *) mIdleConnections[i];
LOG(("comparing against idle connection [host=%s:%d]\n",
conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port()));
// we check if the connection can be reused before even checking if it
// is a "matching" connection. this is how we keep the idle connection
// list fresh. we could alternatively use some sort of timer for this.
if (!conn->CanReuse()) {
LOG(("dropping stale connection: [conn=%x]\n", conn));
mIdleConnections.RemoveElementAt(i);
i--;
NS_RELEASE(conn);
}
else if (conn->ConnectionInfo()->Equals(ci)) {
LOG(("reusing connection [conn=%x]\n", conn));
mIdleConnections.RemoveElementAt(i);
i--;
break;
}
conn = nsnull;
}
if (!conn) {
LOG(("creating new connection...\n"));
NS_NEWXPCOM(conn, nsHttpConnection);
if (!conn)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(conn);
rv = conn->Init(ci);
if (NS_FAILED(rv)) goto failed;
}
rv = conn->SetTransaction(trans);
if (NS_FAILED(rv)) goto failed;
mActiveConnections.AppendElement(conn);
return NS_OK;
failed:
NS_RELEASE(conn);
return rv;
return InitiateTransaction_Locked(trans, ci, failIfBusy);
}
// may be called from any thread
nsresult
nsHttpHandler::ReclaimConnection(nsHttpConnection *conn)
{
@ -403,6 +361,8 @@ nsHttpHandler::ReclaimConnection(nsHttpConnection *conn)
LOG(("nsHttpHandler::ReclaimConnection [conn=%x keep-alive=%d]\n",
conn, conn->CanReuse()));
nsAutoLock lock(mConnectionLock);
// remove connection from the active connection list
mActiveConnections.RemoveElement(conn);
@ -446,8 +406,9 @@ nsHttpHandler::CancelPendingTransaction(nsHttpTransaction *trans,
NS_ENSURE_ARG_POINTER(trans);
nsPendingTransaction *pt = nsnull;
nsAutoLock lock(mConnectionLock);
nsPendingTransaction *pt = nsnull;
PRInt32 i;
for (i=0; i<mTransactionQ.Count(); ++i) {
pt = (nsPendingTransaction *) mTransactionQ[i];
@ -624,6 +585,7 @@ nsHttpHandler::UserAgent()
return mUserAgent.get();
}
// called while holding the connection lock
void
nsHttpHandler::ProcessTransactionQ()
{
@ -640,9 +602,9 @@ nsHttpHandler::ProcessTransactionQ()
// try to initiate this transaction... if it fails
// then we'll just skip over this pending transaction
// and try the next.
nsresult rv = InitiateTransaction(pt->Transaction(),
pt->ConnectionInfo(),
PR_TRUE);
nsresult rv = InitiateTransaction_Locked(pt->Transaction(),
pt->ConnectionInfo(),
PR_TRUE);
if (NS_SUCCEEDED(rv)) {
mTransactionQ.RemoveElementAt(i);
delete pt;
@ -651,6 +613,7 @@ nsHttpHandler::ProcessTransactionQ()
}
}
// called while holding the connection lock
nsresult
nsHttpHandler::EnqueueTransaction(nsHttpTransaction *trans,
nsHttpConnectionInfo *ci)
@ -667,14 +630,90 @@ nsHttpHandler::EnqueueTransaction(nsHttpTransaction *trans,
return NS_OK;
}
nsresult
nsHttpHandler::InitiateTransaction_Locked(nsHttpTransaction *trans,
nsHttpConnectionInfo *ci,
PRBool failIfBusy)
{
nsresult rv;
LOG(("nsHttpHandler::InitiateTransaction_Locked [failIfBusy=%d]\n", failIfBusy));
if ((mActiveConnections.Count() == mMaxConnections) ||
(CountActiveConnections(ci) == PRUint32(mMaxConnectionsPerServer))) {
LOG(("unable to perform the transaction at this time [trans=%x]\n", trans));
if (failIfBusy) return NS_ERROR_FAILURE;
return EnqueueTransaction(trans, ci);
}
nsHttpConnection *conn = nsnull;
// search the idle connection list
PRInt32 i;
for (i=0; i<mIdleConnections.Count(); ++i) {
conn = (nsHttpConnection *) mIdleConnections[i];
LOG(("comparing against idle connection [host=%s:%d]\n",
conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port()));
// we check if the connection can be reused before even checking if it
// is a "matching" connection. this is how we keep the idle connection
// list fresh. we could alternatively use some sort of timer for this.
if (!conn->CanReuse()) {
LOG(("dropping stale connection: [conn=%x]\n", conn));
mIdleConnections.RemoveElementAt(i);
i--;
NS_RELEASE(conn);
}
else if (conn->ConnectionInfo()->Equals(ci)) {
LOG(("reusing connection [conn=%x]\n", conn));
mIdleConnections.RemoveElementAt(i);
i--;
break;
}
conn = nsnull;
}
if (!conn) {
LOG(("creating new connection...\n"));
NS_NEWXPCOM(conn, nsHttpConnection);
if (!conn)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(conn);
rv = conn->Init(ci);
if (NS_FAILED(rv)) goto failed;
}
rv = conn->SetTransaction(trans);
if (NS_FAILED(rv)) goto failed;
mActiveConnections.AppendElement(conn);
return NS_OK;
failed:
NS_RELEASE(conn);
return rv;
}
PRUint32
nsHttpHandler::CountActiveConnections(nsHttpConnectionInfo *ci)
{
PRUint32 count = mActiveConnections.Count();
PRUint32 count = 0;
nsHttpConnection *conn = 0;
LOG(("nsHttpHandler::CountActiveConnections [host=%s:%d] found %u\n",
ci->Host(), ci->Port(), count));
LOG(("nsHttpHandler::CountActiveConnections [host=%s:%d]\n",
ci->Host(), ci->Port()));
PRInt32 i;
for (i=0; i<mActiveConnections.Count(); ++i) {
conn = NS_STATIC_CAST(nsHttpConnection *, mActiveConnections[i]);
// only include a matching connection in the count...
if (conn->ConnectionInfo()->Equals(ci))
count++;
}
LOG(("found count=%u\n", count));
return count;
}
@ -692,7 +731,7 @@ nsHttpHandler::CountIdleConnections(nsHttpConnectionInfo *ci)
PRInt32 i;
for (i=0; i<mIdleConnections.Count(); ++i) {
conn = (nsHttpConnection *) mIdleConnections[i];
conn = NS_STATIC_CAST(nsHttpConnection *, mIdleConnections[i]);
// only include a matching connection in the count if it
// can still be reused.
if (conn->ConnectionInfo()->Equals(ci)) {

View File

@ -106,16 +106,17 @@ public:
// Called to kick-off a new transaction, by default the transaction
// will be put on the pending transaction queue if it cannot be
// initiated at this time.
// initiated at this time. Callable from any thread.
nsresult InitiateTransaction(nsHttpTransaction *,
nsHttpConnectionInfo *,
PRBool failIfBusy = PR_FALSE);
// Called when a connection is done processing a transaction
// Called when a connection is done processing a transaction. Callable
// from any thread.
nsresult ReclaimConnection(nsHttpConnection *);
// Called when a transaction, which is not assigned to a connection,
// is canceled.
// is canceled. Callable from any thread.
nsresult CancelPendingTransaction(nsHttpTransaction *, nsresult status);
//
@ -161,6 +162,11 @@ private:
void ProcessTransactionQ();
nsresult EnqueueTransaction(nsHttpTransaction *, nsHttpConnectionInfo *);
// Called with mConnectionLock held
nsresult InitiateTransaction_Locked(nsHttpTransaction *,
nsHttpConnectionInfo *,
PRBool failIfBusy = PR_FALSE);
PRUint32 CountActiveConnections(nsHttpConnectionInfo *);
PRUint32 CountIdleConnections(nsHttpConnectionInfo *);
@ -195,7 +201,7 @@ private:
nsCOMPtr<nsIMIMEService> mMimeService;
// the authentication credentials cache
nsHttpAuthCache *mAuthCache;
nsHttpAuthCache *mAuthCache;
//
// prefs
@ -231,6 +237,7 @@ private:
nsVoidArray mActiveConnections; // list of nsHttpConnection objects
nsVoidArray mIdleConnections; // list of nsHttpConnection objects
nsVoidArray mTransactionQ; // list of nsPendingTransaction objects
PRLock *mConnectionLock; // protect connection lists
// useragent components
nsXPIDLCString mAppName;

View File

@ -32,45 +32,6 @@
#include "pratom.h"
#include "plevent.h"
//-----------------------------------------------------------------------------
// helpers...
//-----------------------------------------------------------------------------
static void *PR_CALLBACK
TransactionRestartEventHandler(PLEvent *ev)
{
nsHttpTransaction *trans =
NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev));
LOG(("TransactionRestartEventHandler [trans=%x]\n", trans));
NS_PRECONDITION(trans->Connection() &&
trans->Connection()->ConnectionInfo(), "oops");
if (trans->Connection()) {
nsHttpConnectionInfo *ci = trans->Connection()->ConnectionInfo();
if (ci) {
NS_ADDREF(ci);
// clean up the old connection
nsHttpHandler::get()->ReclaimConnection(trans->Connection());
trans->SetConnection(nsnull);
// initiate the transaction again
nsHttpHandler::get()->InitiateTransaction(trans, ci);
NS_RELEASE(ci);
}
}
NS_RELEASE(trans);
return 0;
}
static void PR_CALLBACK
TransactionRestartDestroyHandler(PLEvent *ev)
{
delete ev;
}
//-----------------------------------------------------------------------------
// nsHttpTransaction
//-----------------------------------------------------------------------------
@ -103,10 +64,7 @@ nsHttpTransaction::~nsHttpTransaction()
{
LOG(("Destroying nsHttpTransaction @%x\n", this));
if (mConnection) {
nsHttpHandler::get()->ReclaimConnection(mConnection);
NS_RELEASE(mConnection);
}
NS_IF_RELEASE(mConnection);
if (mChunkedDecoder)
delete mChunkedDecoder;
@ -122,6 +80,12 @@ nsHttpTransaction::SetupRequest(nsHttpRequestHead *requestHead,
NS_ENSURE_ARG_POINTER(requestHead);
// grab a reference to the calling thread's event queue.
nsCOMPtr<nsIEventQueueService> eqs;
nsHttpHandler::get()->GetEventQueueService(getter_AddRefs(eqs));
if (eqs)
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mConsumerEventQ));
if (requestHead->Method() == nsHttp::Head)
mNoContent = PR_TRUE;
@ -150,6 +114,9 @@ nsHttpTransaction::SetupRequest(nsHttpRequestHead *requestHead,
nsresult
nsHttpTransaction::SetConnection(nsHttpConnection *conn)
{
LOG(("nsHttpTransaction::SetConnection [this=%x mConnection=%x conn=%x]\n",
this, mConnection, conn));
mConnection = conn;
NS_IF_ADDREF(mConnection);
return NS_OK;
@ -229,11 +196,17 @@ nsHttpTransaction::OnDataReadable(nsIInputStream *is)
// we don't want the connection to send anymore notifications to us.
mConnection->DropTransaction();
// the transaction needs to be restarted from the thread on which
// it was created.
rv = ProxyRestartTransaction(mConnection->ConsumerEventQ());
NS_ASSERTION(NS_SUCCEEDED(rv), "ProxyRestartTransaction failed");
nsHttpConnectionInfo *ci = mConnection->ConnectionInfo();
NS_ADDREF(ci);
// we must release the connection before calling initiate transaction
// since we will be getting a new connection.
NS_RELEASE(mConnection);
rv = nsHttpHandler::get()->InitiateTransaction(this, ci);
NS_ASSERTION(NS_SUCCEEDED(rv), "InitiateTransaction failed");
NS_RELEASE(ci);
NS_RELEASE_THIS();
return NS_BINDING_ABORTED;
}
@ -502,7 +475,13 @@ nsHttpTransaction::HandleContent(char *buf,
if (priorVal == 0 && mConnection) {
// let the connection know that we are done with it; this should
// result in OnStopTransaction being fired.
return mConnection->OnTransactionComplete(NS_OK);
rv = mConnection->OnTransactionComplete(NS_OK);
// at this point, we no longer need the connection
//nsHttpHandler::get()->ReclaimConnection(mConnection);
NS_RELEASE(mConnection);
return rv;
}
return NS_OK;
}
@ -512,34 +491,83 @@ nsHttpTransaction::HandleContent(char *buf,
return (!mNoContent && !*countRead) ? NS_BASE_STREAM_WOULD_BLOCK : NS_OK;
}
nsresult
nsHttpTransaction::ProxyRestartTransaction(nsIEventQueue *eventQ)
void
nsHttpTransaction::DeleteSelfOnConsumerThread()
{
LOG(("nsHttpTransaction::ProxyRestartTransaction [this=%x]\n", this));
nsCOMPtr<nsIEventQueueService> eqs;
nsCOMPtr<nsIEventQueue> currentEventQ;
NS_ENSURE_ARG_POINTER(eventQ);
NS_PRECONDITION(!mResponseHead, "already received a (partial) response!");
LOG(("nsHttpTransaction::DeleteSelfOnConsumerThread [this=%x]\n", this));
PLEvent *event = new PLEvent;
if (!event)
return NS_ERROR_OUT_OF_MEMORY;
nsHttpHandler::get()->GetEventQueueService(getter_AddRefs(eqs));
if (eqs)
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(currentEventQ));
NS_ADDREF_THIS();
if (currentEventQ == mConsumerEventQ)
delete this;
else {
LOG(("proxying delete to consumer thread...\n"));
PL_InitEvent(event, this,
TransactionRestartEventHandler,
TransactionRestartDestroyHandler);
PLEvent *event = new PLEvent;
if (!event) {
NS_WARNING("out of memory");
// probably better to leak |this| than to delete it on this thread.
return;
}
return eventQ->PostEvent(event);
PL_InitEvent(event, this,
nsHttpTransaction::DeleteThis_EventHandlerFunc,
nsHttpTransaction::DeleteThis_EventCleanupFunc);
PRStatus status = mConsumerEventQ->PostEvent(event);
NS_ASSERTION(status == PR_SUCCESS, "PostEvent failed");
}
}
void *PR_CALLBACK
nsHttpTransaction::DeleteThis_EventHandlerFunc(PLEvent *ev)
{
nsHttpTransaction *trans =
NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev));
LOG(("nsHttpTransaction::DeleteThis_EventHandlerFunc [trans=%x]\n", trans));
delete trans;
return nsnull;
}
void PR_CALLBACK
nsHttpTransaction::DeleteThis_EventCleanupFunc(PLEvent *ev)
{
delete ev;
}
//-----------------------------------------------------------------------------
// nsHttpTransaction::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_THREADSAFE_ISUPPORTS2(nsHttpTransaction,
nsIRequest,
nsIInputStream)
NS_IMPL_THREADSAFE_ADDREF(nsHttpTransaction)
NS_IMETHODIMP_(nsrefcnt)
nsHttpTransaction::Release()
{
nsrefcnt count;
NS_PRECONDITION(0 != mRefCnt, "dup release");
count = PR_AtomicDecrement((PRInt32 *) &mRefCnt);
NS_LOG_RELEASE(this, count, "nsHttpTransaction");
if (0 == count) {
mRefCnt = 1; /* stablize */
// it is essential that the transaction be destroyed on the consumer
// thread (we could be holding the last reference to our consumer).
DeleteSelfOnConsumerThread();
return 0;
}
return count;
}
NS_IMPL_THREADSAFE_QUERY_INTERFACE2(nsHttpTransaction,
nsIRequest,
nsIInputStream)
//-----------------------------------------------------------------------------
// nsHttpTransaction::nsIRequest
@ -592,8 +620,10 @@ nsHttpTransaction::Cancel(nsresult status)
// completion, in which case we should ignore this cancelation request.
PRInt32 priorVal = PR_AtomicSet(&mTransactionDone, 1);
if (priorVal == 0)
if (priorVal == 0) {
mConnection->OnTransactionComplete(status);
NS_RELEASE(mConnection);
}
return NS_OK;
}

View File

@ -29,6 +29,7 @@
#include "nsIStreamListener.h"
#include "nsIInputStream.h"
#include "nsIInterfaceRequestor.h"
#include "nsIEventQueue.h"
#include "nsXPIDLString.h"
#include "nsCOMPtr.h"
@ -36,7 +37,6 @@ class nsHttpRequestHead;
class nsHttpResponseHead;
class nsHttpConnection;
class nsHttpChunkedDecoder;
class nsIEventQueue;
//-----------------------------------------------------------------------------
// nsHttpTransaction represents a single HTTP transaction. It is thread-safe,
@ -63,11 +63,12 @@ public:
// Called to initialize the transaction
nsresult SetupRequest(nsHttpRequestHead *, nsIInputStream *);
nsIStreamListener *Listener() { return mListener; }
nsHttpConnection *Connection() { return mConnection; }
nsHttpRequestHead *RequestHead() { return mRequestHead; }
nsHttpResponseHead *ResponseHead() { return mResponseHead; }
nsIInterfaceRequestor *Callbacks() { return mCallbacks; }
nsIStreamListener *Listener() { return mListener; }
nsHttpConnection *Connection() { return mConnection; }
nsHttpRequestHead *RequestHead() { return mRequestHead; }
nsHttpResponseHead *ResponseHead() { return mResponseHead; }
nsIInterfaceRequestor *Callbacks() { return mCallbacks; }
nsIEventQueue *ConsumerEventQ() { return mConsumerEventQ; }
// Called to take ownership of the response headers; the transaction
// will drop any reference to the response headers after this call.
@ -90,11 +91,15 @@ private:
void ParseLineSegment(char *seg, PRUint32 len);
nsresult ParseHead(char *, PRUint32 count, PRUint32 *countRead);
nsresult HandleContent(char *, PRUint32 count, PRUint32 *countRead);
nsresult ProxyRestartTransaction(nsIEventQueue *);
void DeleteSelfOnConsumerThread();
static void *PR_CALLBACK DeleteThis_EventHandlerFunc(PLEvent *);
static void PR_CALLBACK DeleteThis_EventCleanupFunc(PLEvent *);
private:
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIEventQueue> mConsumerEventQ;
nsHttpConnection *mConnection; // hard ref