зеркало из https://github.com/mozilla/gecko-dev.git
Fixes bug 82181 "bugzilla queries won't submit" r=gagan sr=blizzard a=asa
This commit is contained in:
Родитель
4c871de289
Коммит
1d0e280b41
|
@ -45,7 +45,8 @@ static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
|||
static void *PR_CALLBACK
|
||||
TransactionReleaseEventHandler(PLEvent *ev)
|
||||
{
|
||||
nsHttpTransaction *trans = (nsHttpTransaction *) PL_GetEventOwner(ev);
|
||||
nsHttpTransaction *trans =
|
||||
NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev));
|
||||
|
||||
LOG(("TransactionReleaseEventHandler [trans=%x refcnt=%u] calling release...\n",
|
||||
trans, trans->RefCnt()));
|
||||
|
@ -125,11 +126,11 @@ nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
|
|||
NS_ADDREF(mTransaction);
|
||||
|
||||
// grab a reference to the calling thread's event queue.
|
||||
mEventQ = 0;
|
||||
mConsumerEventQ = 0;
|
||||
nsCOMPtr<nsIEventQueueService> eqs;
|
||||
nsHttpHandler::get()->GetEventQueueService(getter_AddRefs(eqs));
|
||||
if (eqs)
|
||||
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mEventQ));
|
||||
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mConsumerEventQ));
|
||||
|
||||
// build a proxy for the progress event sink
|
||||
mProgressSink = 0;
|
||||
|
@ -139,7 +140,7 @@ nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
|
|||
nsCOMPtr<nsIProxyObjectManager> mgr;
|
||||
nsHttpHandler::get()->GetProxyObjectManager(getter_AddRefs(mgr));
|
||||
if (mgr)
|
||||
mgr->GetProxyForObject(mEventQ,
|
||||
mgr->GetProxyForObject(mConsumerEventQ,
|
||||
NS_GET_IID(nsIProgressEventSink),
|
||||
temp,
|
||||
PROXY_ASYNC | PROXY_ALWAYS,
|
||||
|
@ -301,7 +302,7 @@ nsHttpConnection::ProxyStepUp()
|
|||
PRBool
|
||||
nsHttpConnection::CanReuse()
|
||||
{
|
||||
return (mReuseCount < mMaxReuseCount) &&
|
||||
return mKeepAlive && (mReuseCount < mMaxReuseCount) &&
|
||||
(NowInSeconds() - mLastActiveTime < mIdleTimeout) && IsAlive();
|
||||
}
|
||||
|
||||
|
@ -317,6 +318,20 @@ nsHttpConnection::IsAlive()
|
|||
return isAlive;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnection::DropTransaction()
|
||||
{
|
||||
// the assertion here is that the transaction will not be destroyed
|
||||
// by this release. we unfortunately don't have a threadsafe way of
|
||||
// asserting this.
|
||||
NS_IF_RELEASE(mTransaction);
|
||||
mTransaction = 0;
|
||||
mProgressSink = 0;
|
||||
|
||||
// if the transaction was dropped, then we cannot reuse this connection.
|
||||
mKeepAlive = PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnection::ReportProgress(PRUint32 progress, PRInt32 progressMax)
|
||||
{
|
||||
|
@ -420,7 +435,7 @@ nsHttpConnection::ProxyReleaseTransaction(nsHttpTransaction *trans)
|
|||
LOG(("nsHttpConnection::ProxyReleaseTransaction [this=%x trans=%x refcnt=%u]\n",
|
||||
this, trans, trans->RefCnt()));
|
||||
|
||||
NS_ENSURE_TRUE(mEventQ, NS_ERROR_NOT_INITIALIZED);
|
||||
NS_ENSURE_TRUE(mConsumerEventQ, NS_ERROR_NOT_INITIALIZED);
|
||||
NS_ENSURE_ARG_POINTER(trans);
|
||||
|
||||
PLEvent *event = new PLEvent;
|
||||
|
@ -431,7 +446,7 @@ nsHttpConnection::ProxyReleaseTransaction(nsHttpTransaction *trans)
|
|||
TransactionReleaseEventHandler,
|
||||
TransactionReleaseDestroyHandler);
|
||||
|
||||
return mEventQ->PostEvent(event);
|
||||
return mConsumerEventQ->PostEvent(event);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -89,10 +89,12 @@ public:
|
|||
PRUint32 MaxReuseCount() { return mMaxReuseCount; }
|
||||
PRUint32 IdleTimeout() { return mIdleTimeout; }
|
||||
|
||||
void DropTransaction();
|
||||
void ReportProgress(PRUint32 progress, PRInt32 progressMax);
|
||||
|
||||
nsHttpTransaction *Transaction() { return mTransaction; }
|
||||
nsHttpConnectionInfo *ConnectionInfo() { return mConnectionInfo; }
|
||||
nsHttpTransaction *Transaction() { return mTransaction; }
|
||||
nsHttpConnectionInfo *ConnectionInfo() { return mConnectionInfo; }
|
||||
nsIEventQueue *ConsumerEventQ() { return mConsumerEventQ; }
|
||||
|
||||
private:
|
||||
enum {
|
||||
|
@ -117,7 +119,7 @@ private:
|
|||
nsCOMPtr<nsIRequest> mReadRequest;
|
||||
|
||||
nsCOMPtr<nsIProgressEventSink> mProgressSink;
|
||||
nsCOMPtr<nsIEventQueue> mEventQ;
|
||||
nsCOMPtr<nsIEventQueue> mConsumerEventQ;
|
||||
|
||||
nsCOMPtr<nsIInputStream> mSSLProxyConnectStream;
|
||||
|
||||
|
|
|
@ -30,6 +30,46 @@
|
|||
#include "nsHttpChunkedDecoder.h"
|
||||
#include "nsIStringStream.h"
|
||||
#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
|
||||
|
@ -50,6 +90,7 @@ nsHttpTransaction::nsHttpTransaction(nsIStreamListener *listener,
|
|||
, mHaveAllHeaders(PR_FALSE)
|
||||
, mFiredOnStart(PR_FALSE)
|
||||
, mNoContent(PR_FALSE)
|
||||
, mPrematureEOF(PR_FALSE)
|
||||
{
|
||||
LOG(("Creating nsHttpTransaction @%x\n", this));
|
||||
|
||||
|
@ -106,12 +147,8 @@ nsHttpTransaction::SetupRequest(nsHttpRequestHead *requestHead,
|
|||
nsresult
|
||||
nsHttpTransaction::SetConnection(nsHttpConnection *conn)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(conn);
|
||||
NS_ENSURE_TRUE(!mConnection, NS_ERROR_ALREADY_INITIALIZED);
|
||||
|
||||
mConnection = conn;
|
||||
NS_ADDREF(mConnection);
|
||||
|
||||
NS_IF_ADDREF(mConnection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -176,6 +213,28 @@ nsHttpTransaction::OnDataReadable(nsIInputStream *is)
|
|||
LOG(("nsHttpTransaction: listener returned [rv=%x]\n", rv));
|
||||
|
||||
mSource = 0;
|
||||
|
||||
// check if this transaction needs to be restarted
|
||||
if (mPrematureEOF) {
|
||||
mPrematureEOF = PR_FALSE;
|
||||
|
||||
LOG(("restarting transaction @%x\n", this));
|
||||
|
||||
// just in case the connection is holding the last reference to us...
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
// 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");
|
||||
|
||||
NS_RELEASE_THIS();
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -447,6 +506,27 @@ nsHttpTransaction::HandleContent(char *buf,
|
|||
return (!mNoContent && !*countRead) ? NS_BASE_STREAM_WOULD_BLOCK : NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpTransaction::ProxyRestartTransaction(nsIEventQueue *eventQ)
|
||||
{
|
||||
LOG(("nsHttpTransaction::ProxyRestartTransaction [this=%x]\n", this));
|
||||
|
||||
NS_ENSURE_ARG_POINTER(eventQ);
|
||||
NS_PRECONDITION(!mResponseHead, "already received a (partial) response!");
|
||||
|
||||
PLEvent *event = new PLEvent;
|
||||
if (!event)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
PL_InitEvent(event, this,
|
||||
TransactionRestartEventHandler,
|
||||
TransactionRestartDestroyHandler);
|
||||
|
||||
return eventQ->PostEvent(event);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpTransaction::nsISupports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -577,12 +657,25 @@ nsHttpTransaction::Read(char *buf, PRUint32 count, PRUint32 *bytesWritten)
|
|||
if (mTransactionDone)
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
|
||||
*bytesWritten = 0;
|
||||
|
||||
// read some data from our source and put it in the given buf
|
||||
rv = mSource->Read(buf, count, bytesWritten);
|
||||
if (NS_FAILED(rv) || (*bytesWritten == 0)) {
|
||||
LOG(("mSource->Read [rv=%x count=%u countRead=%u]\n", rv, count, *bytesWritten));
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("nsHttpTransaction: mSource->Read() returned [rv=%x]\n", rv));
|
||||
return rv;
|
||||
}
|
||||
if (NS_SUCCEEDED(rv) && (*bytesWritten == 0)) {
|
||||
LOG(("nsHttpTransaction: reached EOF\n"));
|
||||
if (!mHaveStatusLine) {
|
||||
// we've read nothing from the socket...
|
||||
mPrematureEOF = PR_TRUE;
|
||||
// return would block to prevent being called again.
|
||||
return NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// pretend that no bytes were written (since we're just borrowing the
|
||||
// given buf anyways).
|
||||
|
|
|
@ -36,6 +36,7 @@ class nsHttpRequestHead;
|
|||
class nsHttpResponseHead;
|
||||
class nsHttpConnection;
|
||||
class nsHttpChunkedDecoder;
|
||||
class nsIEventQueue;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpTransaction represents a single HTTP transaction. It is thread-safe,
|
||||
|
@ -88,6 +89,7 @@ private:
|
|||
void ParseLineSegment(char *seg, PRUint32 len);
|
||||
nsresult ParseHead(char *, PRUint32 count, PRUint32 *countRead);
|
||||
nsresult HandleContent(char *, PRUint32 count, PRUint32 *countRead);
|
||||
nsresult ProxyRestartTransaction(nsIEventQueue *);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
|
@ -116,6 +118,7 @@ private:
|
|||
PRPackedBool mHaveAllHeaders;
|
||||
PRPackedBool mFiredOnStart;
|
||||
PRPackedBool mNoContent; // true if we're expecting an empty entity body
|
||||
PRPackedBool mPrematureEOF;
|
||||
};
|
||||
|
||||
#endif // nsHttpTransaction_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче