bug 447866 http pipelining is bursty r=honzab

--HG--
extra : rebase_source : e927c5961b2f6c79c1aa73897900e95ed3f286c5
This commit is contained in:
Patrick McManus 2012-03-20 13:11:32 -04:00
Родитель e2109fe3bc
Коммит 7abd00c179
12 изменённых файлов: 333 добавлений и 53 удалений

Просмотреть файл

@ -2075,6 +2075,13 @@ SpdySession::Status()
return NS_ERROR_UNEXPECTED;
}
PRUint8
SpdySession::Caps()
{
NS_ABORT_IF_FALSE(false, "SpdySession::Caps()");
return 0;
}
PRUint32
SpdySession::Available()
{
@ -2132,6 +2139,26 @@ SpdySession::TakeSubTransactions(
return NS_OK;
}
nsresult
SpdySession::AddTransaction(nsAHttpTransaction *)
{
// This API is meant for pipelining, SpdySession's should be
// extended with AddStream()
NS_ABORT_IF_FALSE(false,
"SpdySession::AddTransaction() should not be called");
return NS_ERROR_NOT_IMPLEMENTED;
}
PRUint16
SpdySession::PipelineDepthAvailable()
{
// any attempt at pipelining will be turned into parallelism
return 0;
}
//-----------------------------------------------------------------------------
// Pass through methods of nsAHttpConnection
//-----------------------------------------------------------------------------
@ -2179,6 +2206,13 @@ SpdySession::PushBack(const char *buf, PRUint32 len)
return mConnection->PushBack(buf, len);
}
bool
SpdySession::IsProxyConnectInProgress()
{
NS_ABORT_IF_FALSE(mConnection, "no connection");
return mConnection->IsProxyConnectInProgress();
}
bool
SpdySession::LastTransactionExpectedNoContent()
{

Просмотреть файл

@ -127,6 +127,11 @@ public:
// than it should have (eg. containing part of the next pipelined response).
virtual nsresult PushBack(const char *data, PRUint32 length) = 0;
// Used to determine if the connection wants read events even though
// it has not written out a transaction. Used when a connection has issued
// a preamble such as a proxy ssl CONNECT sequence.
virtual bool IsProxyConnectInProgress() = 0;
// Used by a transaction to manage the state of previous response bodies on
// the same connection and work around buggy servers.
virtual bool LastTransactionExpectedNoContent() = 0;
@ -154,6 +159,7 @@ public:
bool IsPersistent(); \
bool IsReused(); \
nsresult PushBack(const char *, PRUint32); \
bool IsProxyConnectInProgress(); \
bool LastTransactionExpectedNoContent(); \
void SetLastTransactionExpectedNoContent(bool); \
nsHttpConnection *TakeHttpConnection(); \

Просмотреть файл

@ -77,6 +77,7 @@ public:
// called to check the transaction status.
virtual bool IsDone() = 0;
virtual nsresult Status() = 0;
virtual PRUint8 Caps() = 0;
// called to find out how much request data is available for writing.
virtual PRUint32 Available() = 0;
@ -114,6 +115,14 @@ public:
//
virtual nsresult TakeSubTransactions(
nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions) = 0;
// called to add a sub-transaction in the case of pipelined transactions
// classes that do not implement sub transactions
// return NS_ERROR_NOT_IMPLEMENTED
virtual nsresult AddTransaction(nsAHttpTransaction *transaction) = 0;
// called to count the number of sub transactions that can be added
virtual PRUint16 PipelineDepthAvailable() = 0;
};
#define NS_DECL_NSAHTTPTRANSACTION \
@ -125,6 +134,7 @@ public:
nsresult status, PRUint64 progress); \
bool IsDone(); \
nsresult Status(); \
PRUint8 Caps(); \
PRUint32 Available(); \
nsresult ReadSegments(nsAHttpSegmentReader *, PRUint32, PRUint32 *); \
nsresult WriteSegments(nsAHttpSegmentWriter *, PRUint32, PRUint32 *); \
@ -132,7 +142,9 @@ public:
void SetSSLConnectFailed(); \
nsHttpRequestHead *RequestHead(); \
PRUint32 Http1xTransactionCount(); \
nsresult TakeSubTransactions(nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions);
nsresult TakeSubTransactions(nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions); \
nsresult AddTransaction(nsAHttpTransaction *); \
PRUint16 PipelineDepthAvailable();
//-----------------------------------------------------------------------------
// nsAHttpSegmentReader

Просмотреть файл

@ -86,6 +86,7 @@ nsHttpConnection::nsHttpConnection()
, mCompletedProxyConnect(false)
, mLastTransactionExpectedNoContent(false)
, mIdleMonitoring(false)
, mProxyConnectInProgress(false)
, mHttp1xTransactionCount(0)
, mNPNComplete(false)
, mSetupNPNCalled(false)
@ -153,6 +154,7 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info,
NS_ENSURE_TRUE(!mConnInfo, NS_ERROR_ALREADY_INITIALIZED);
mConnInfo = info;
mSupportsPipelining = mConnInfo->SupportsPipelining();
mMaxHangTime = PR_SecondsToInterval(maxHangTime);
mLastReadTime = PR_IntervalNow();
@ -369,6 +371,7 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, PRUint8 caps, PRInt32 pri)
rv = SetupProxyConnect();
if (NS_FAILED(rv))
goto failed_activation;
mProxyConnectInProgress = true;
}
// Clear the per activation counter
@ -733,6 +736,7 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans,
}
}
mKeepAliveMask = mKeepAlive;
mConnInfo->SetSupportsPipelining(mSupportsPipelining);
// if this connection is persistent, then the server may send a "Keep-Alive"
// header specifying the maximum number of times the connection can be
@ -1094,6 +1098,7 @@ nsHttpConnection::OnSocketWritable()
}
LOG((" writing transaction request stream\n"));
mProxyConnectInProgress = false;
rv = mTransaction->ReadSegments(this, nsIOService::gDefaultSegmentSize, &n);
}

Просмотреть файл

@ -41,7 +41,6 @@
#include "nsHttp.h"
#include "nsHttpConnectionInfo.h"
#include "nsAHttpConnection.h"
#include "nsAHttpTransaction.h"
#include "nsXPIDLString.h"
#include "nsCOMPtr.h"
@ -56,6 +55,9 @@
#include "nsIInterfaceRequestor.h"
#include "nsIEventTarget.h"
class nsHttpRequestHead;
class nsHttpResponseHead;
//-----------------------------------------------------------------------------
// nsHttpConnection - represents a connection to a HTTP server (or proxy)
//
@ -115,6 +117,11 @@ public:
void DontReuse();
void DropTransport() { DontReuse(); mSocketTransport = 0; }
bool IsProxyConnectInProgress()
{
return mProxyConnectInProgress;
}
bool LastTransactionExpectedNoContent()
{
return mLastTransactionExpectedNoContent;
@ -228,6 +235,7 @@ private:
bool mCompletedProxyConnect;
bool mLastTransactionExpectedNoContent;
bool mIdleMonitoring;
bool mProxyConnectInProgress;
// The number of <= HTTP/1.1 transactions performed on this connection. This
// excludes spdy transactions.

Просмотреть файл

@ -60,6 +60,7 @@ public:
: mRef(0)
, mProxyInfo(proxyInfo)
, mUsingSSL(usingSSL)
, mSupportsPipelining(false)
{
LOG(("Creating nsHttpConnectionInfo @%x\n", this));
@ -125,6 +126,11 @@ public:
void SetAnonymous(bool anon)
{ mHashKey.SetCharAt(anon ? 'A' : '.', 2); }
bool GetAnonymous() { return mHashKey.CharAt(2) == 'A'; }
bool SupportsPipelining() { return mSupportsPipelining; }
void SetSupportsPipelining(bool support)
{ mSupportsPipelining = support; }
bool ShouldForceConnectMethod();
const nsCString &GetHost() { return mHost; }
@ -136,6 +142,7 @@ private:
nsCOMPtr<nsProxyInfo> mProxyInfo;
bool mUsingHttpProxy;
bool mUsingSSL;
bool mSupportsPipelining;
};
#endif // nsHttpConnectionInfo_h__

Просмотреть файл

@ -352,26 +352,38 @@ nsHttpConnectionMgr::GetSocketThreadTarget(nsIEventTarget **target)
void
nsHttpConnectionMgr::AddTransactionToPipeline(nsHttpPipeline *pipeline)
{
/* called on an existing pipeline anytime we might add more data to an
existing pipeline such as when a transaction completes (and
therefore the quota has new room), or when we receive headers which
might change our view of pipelining */
LOG(("nsHttpConnectionMgr::AddTransactionToPipeline [pipeline=%x]\n", pipeline));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
PRUint16 avail = pipeline->PipelineDepthAvailable();
nsRefPtr<nsHttpConnectionInfo> ci;
pipeline->GetConnectionInfo(getter_AddRefs(ci));
if (ci) {
if (ci && avail && ci->SupportsPipelining()) {
nsConnectionEntry *ent = mCT.Get(ci->HashKey());
if (ent) {
// search for another request to pipeline...
PRInt32 i, count = ent->mPendingQ.Length();
for (i=0; i<count; ++i) {
for (i = 0; i < count; ) {
nsHttpTransaction *trans = ent->mPendingQ[i];
if (trans->Caps() & NS_HTTP_ALLOW_PIPELINING) {
pipeline->AddTransaction(trans);
// remove transaction from pending queue
ent->mPendingQ.RemoveElementAt(i);
--count;
NS_RELEASE(trans);
break;
if (--avail == 0)
break;
}
else {
++i;
}
}
}
@ -956,6 +968,69 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent)
return false;
}
bool
nsHttpConnectionMgr::ProcessPipelinePendingQForEntry(nsConnectionEntry *ent)
{
LOG(("nsHttpConnectionMgr::ProcessPipelinePendingQForEntry [ci=%s]\n",
ent->mConnInfo->HashKey().get()));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
if (mMaxPipelinedRequests < 2)
return false;
PRUint32 activeCount = ent->mActiveConns.Length();
PRUint32 originalPendingCount = ent->mPendingQ.Length();
PRUint32 pendingCount = originalPendingCount;
PRUint32 pendingIndex = 0;
for (PRUint32 activeIndex = 0;
(activeIndex < activeCount) && (pendingIndex < pendingCount);
++activeIndex) {
nsHttpConnection *conn = ent->mActiveConns[activeIndex];
if (!conn->SupportsPipelining())
continue;
nsAHttpTransaction *activeTrans = conn->Transaction();
if (!activeTrans)
continue;
nsresult rv = NS_OK;
PRUint16 avail = activeTrans->PipelineDepthAvailable();
while (NS_SUCCEEDED(rv) && avail && (pendingIndex < pendingCount)) {
nsHttpTransaction *trans = ent->mPendingQ[pendingIndex];
if (trans->Caps() & NS_HTTP_ALLOW_PIPELINING) {
rv = activeTrans->AddTransaction(trans);
if (NS_SUCCEEDED(rv)) {
// remove transaction from pending queue
ent->mPendingQ.RemoveElementAt(pendingIndex);
// adjust iterator to reflect coalesced queue
--pendingCount;
--avail;
NS_RELEASE(trans);
}
}
else
// skip over this one
++pendingIndex;
}
}
return originalPendingCount != pendingCount;
}
bool
nsHttpConnectionMgr::ProcessPipelinePendingQForCI(nsHttpConnectionInfo *ci)
{
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
nsConnectionEntry *ent = mCT.Get(ci->HashKey());
return ent && ProcessPipelinePendingQForEntry(ent);
}
// we're at the active connection limit if any one of the following conditions is true:
// (1) at max-connections
// (2) keep-alive enabled and at max-persistent-connections-per-server/proxy
@ -1231,11 +1306,12 @@ nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent,
nsHttpPipeline *pipeline = nsnull;
nsAHttpTransaction *trans = aTrans;
if (conn->SupportsPipelining() && (caps & NS_HTTP_ALLOW_PIPELINING)) {
LOG((" looking to build pipeline...\n"));
if (BuildPipeline(ent, trans, &pipeline))
trans = pipeline;
}
/* Use pipeline datastructure even if connection does not currently qualify
to pipeline this transaction because a different pipeline-eligible
transaction might be placed on the active connection */
if (BuildPipeline(ent, trans, &pipeline))
trans = pipeline;
// give the transaction the indirect reference to the connection.
trans->SetConnection(handle);
@ -1268,40 +1344,48 @@ nsHttpConnectionMgr::BuildPipeline(nsConnectionEntry *ent,
nsAHttpTransaction *firstTrans,
nsHttpPipeline **result)
{
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
if (mMaxPipelinedRequests < 2)
return false;
nsHttpPipeline *pipeline = nsnull;
nsHttpTransaction *trans;
/* form a pipeline here even if nothing is pending so that we
can stream-feed it as new transactions arrive */
PRUint32 i = 0, numAdded = 0;
while (i < ent->mPendingQ.Length()) {
trans = ent->mPendingQ[i];
if (trans->Caps() & NS_HTTP_ALLOW_PIPELINING) {
if (numAdded == 0) {
pipeline = new nsHttpPipeline;
if (!pipeline)
return false;
pipeline->AddTransaction(firstTrans);
numAdded = 1;
nsHttpPipeline *pipeline = new nsHttpPipeline(mMaxPipelinedRequests);
/* the first transaction can go in unconditionally - 1 transaction
on a nsHttpPipeline object is not a real HTTP pipeline */
PRUint16 numAdded = 1;
pipeline->AddTransaction(firstTrans);
if (ent->mConnInfo->SupportsPipelining() &&
firstTrans->Caps() & NS_HTTP_ALLOW_PIPELINING) {
PRUint32 i = 0;
nsHttpTransaction *trans;
while (i < ent->mPendingQ.Length()) {
trans = ent->mPendingQ[i];
if (trans->Caps() & NS_HTTP_ALLOW_PIPELINING) {
pipeline->AddTransaction(trans);
// remove transaction from pending queue
ent->mPendingQ.RemoveElementAt(i);
NS_RELEASE(trans);
if (++numAdded == mMaxPipelinedRequests)
break;
}
else {
++i; // skip to next pending transaction
}
pipeline->AddTransaction(trans);
// remove transaction from pending queue
ent->mPendingQ.RemoveElementAt(i);
NS_RELEASE(trans);
if (++numAdded == mMaxPipelinedRequests)
break;
}
else
++i; // skip to next pending transaction
}
if (numAdded == 0)
return false;
if (numAdded > 1)
LOG((" pipelined %u transactions\n", numAdded));
LOG((" pipelined %u transactions\n", numAdded));
NS_ADDREF(*result = pipeline);
return true;
}
@ -1375,6 +1459,11 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans)
// put this transaction on the pending queue...
InsertTransactionSorted(ent->mPendingQ, trans);
NS_ADDREF(trans);
/* there still remains the possibility that the transaction we just
queued could go out right away as a pipelined request on an existing
connection */
ProcessPipelinePendingQForEntry(ent);
rv = NS_OK;
}
else {
@ -2297,6 +2386,12 @@ nsHttpConnectionMgr::nsConnectionHandle::TakeHttpConnection()
return conn;
}
bool
nsHttpConnectionMgr::nsConnectionHandle::IsProxyConnectInProgress()
{
return mConn->IsProxyConnectInProgress();
}
bool
nsHttpConnectionMgr::nsConnectionHandle::LastTransactionExpectedNoContent()
{

Просмотреть файл

@ -142,7 +142,7 @@ public:
// NOTE: functions below may be called only on the socket thread.
//-------------------------------------------------------------------------
// removes the next transaction for the specified connection from the
// removes the next transactions for the specified connection from the
// pending transaction queue.
void AddTransactionToPipeline(nsHttpPipeline *);
@ -160,6 +160,10 @@ public:
// bit different.
void ReportSpdyConnection(nsHttpConnection *, bool usingSpdy);
// Similar to ProcessPendingQ, but only considers adding transactions to
// existing connections
bool ProcessPipelinePendingQForCI(nsHttpConnectionInfo *);
private:
virtual ~nsHttpConnectionMgr();
class nsHalfOpenSocket;
@ -311,6 +315,7 @@ private:
static PLDHashOperator ClosePersistentConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
bool ProcessPendingQForEntry(nsConnectionEntry *);
bool AtActiveConnectionLimit(nsConnectionEntry *, PRUint8 caps);
bool ProcessPipelinePendingQForEntry(nsConnectionEntry *);
void GetConnection(nsConnectionEntry *, nsHttpTransaction *,
bool, nsHttpConnection **);
nsresult DispatchTransaction(nsConnectionEntry *, nsHttpTransaction *,

Просмотреть файл

@ -92,12 +92,14 @@ private:
// nsHttpPipeline <public>
//-----------------------------------------------------------------------------
nsHttpPipeline::nsHttpPipeline()
: mConnection(nsnull)
nsHttpPipeline::nsHttpPipeline(PRUint16 maxPipelineDepth)
: mMaxPipelineDepth(maxPipelineDepth)
, mConnection(nsnull)
, mStatus(NS_OK)
, mRequestIsPartial(false)
, mResponseIsPartial(false)
, mClosed(false)
, mUtilizedPipeline(false)
, mPushBackBuf(nsnull)
, mPushBackLen(0)
, mPushBackMax(0)
@ -124,6 +126,9 @@ nsHttpPipeline::AddTransaction(nsAHttpTransaction *trans)
{
LOG(("nsHttpPipeline::AddTransaction [this=%x trans=%x]\n", this, trans));
if (mRequestQ.Length() || mResponseQ.Length())
mUtilizedPipeline = true;
NS_ADDREF(trans);
mRequestQ.AppendElement(trans);
@ -137,6 +142,27 @@ nsHttpPipeline::AddTransaction(nsAHttpTransaction *trans)
return NS_OK;
}
PRUint16
nsHttpPipeline::PipelineDepthAvailable()
{
PRUint16 currentTransactions = mRequestQ.Length() + mResponseQ.Length();
// Check to see if there are too many transactions currently in use.
if (currentTransactions >= mMaxPipelineDepth)
return 0;
// Check to see if this connection is being used by a non-pipelineable
// transaction already.
nsAHttpTransaction *trans = Request(0);
if (!trans)
trans = Response(0);
if (trans && !(trans->Caps() & NS_HTTP_ALLOW_PIPELINING))
return 0;
// There is still some room available.
return mMaxPipelineDepth - currentTransactions;
}
//-----------------------------------------------------------------------------
// nsHttpPipeline::nsISupports
//-----------------------------------------------------------------------------
@ -165,8 +191,25 @@ nsHttpPipeline::OnHeadersAvailable(nsAHttpTransaction *trans,
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
NS_ASSERTION(mConnection, "no connection");
nsRefPtr<nsHttpConnectionInfo> ci;
GetConnectionInfo(getter_AddRefs(ci));
NS_ABORT_IF_FALSE(ci, "no connection info");
bool pipeliningBefore = ci->SupportsPipelining();
// trans has now received its response headers; forward to the real connection
return mConnection->OnHeadersAvailable(trans, requestHead, responseHead, reset);
nsresult rv = mConnection->OnHeadersAvailable(trans,
requestHead,
responseHead,
reset);
if (!pipeliningBefore && ci->SupportsPipelining())
// The received headers have expanded the eligible
// pipeline depth for this connection
gHttpHandler->ConnMgr()->ProcessPipelinePendingQForCI(ci);
return rv;
}
nsresult
@ -261,7 +304,9 @@ nsHttpPipeline::IsPersistent()
bool
nsHttpPipeline::IsReused()
{
return true; // pipelining requires this
if (!mUtilizedPipeline && mConnection)
return mConnection->IsReused();
return true;
}
nsresult
@ -309,6 +354,13 @@ nsHttpPipeline::PushBack(const char *data, PRUint32 length)
return NS_OK;
}
bool
nsHttpPipeline::IsProxyConnectInProgress()
{
NS_ABORT_IF_FALSE(mConnection, "no connection");
return mConnection->IsProxyConnectInProgress();
}
bool
nsHttpPipeline::LastTransactionExpectedNoContent()
{
@ -425,8 +477,13 @@ nsHttpPipeline::GetSecurityCallbacks(nsIInterfaceRequestor **result,
{
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
// return security callbacks from first request
// depending on timing this could be either the request or the response
// that is needed - but they both go to the same host. A request for these
// callbacks directly in nsHttpTransaction would not make a distinction
// over whether the the request had been transmitted yet.
nsAHttpTransaction *trans = Request(0);
if (!trans)
trans = Response(0);
if (trans)
trans->GetSecurityCallbacks(result, target);
else {
@ -546,6 +603,16 @@ nsHttpPipeline::Status()
return mStatus;
}
PRUint8
nsHttpPipeline::Caps()
{
nsAHttpTransaction *trans = Request(0);
if (!trans)
trans = Response(0);
return trans ? trans->Caps() : 0;
}
PRUint32
nsHttpPipeline::Available()
{
@ -632,6 +699,17 @@ nsHttpPipeline::WriteSegments(nsAHttpSegmentWriter *writer,
nsresult rv;
trans = Response(0);
// This code deals with the establishment of a CONNECT tunnel through
// an HTTP proxy. It allows the connection to do the CONNECT/200
// HTTP transaction to establish an SSL tunnel as a precursor to the
// actual pipeline of regular HTTP transactions.
if (!trans && mRequestQ.Length() &&
mConnection->IsProxyConnectInProgress()) {
LOG(("nsHttpPipeline::WriteSegments [this=%p] Forced Delegation\n",
this));
trans = Request(0);
}
if (!trans) {
if (mRequestQ.Length() > 0)
rv = NS_BASE_STREAM_WOULD_BLOCK;
@ -701,22 +779,32 @@ nsHttpPipeline::Close(nsresult reason)
nsAHttpTransaction *trans;
// any pending requests can ignore this error and be restarted
// unless it is during a CONNECT tunnel request
count = mRequestQ.Length();
for (i=0; i<count; ++i) {
for (i = 0; i < count; ++i) {
trans = Request(i);
trans->Close(NS_ERROR_NET_RESET);
if (mConnection && mConnection->IsProxyConnectInProgress())
trans->Close(reason);
else
trans->Close(NS_ERROR_NET_RESET);
NS_RELEASE(trans);
}
mRequestQ.Clear();
trans = Response(0);
if (trans) {
// if the current response is partially complete, then it cannot be
// restarted and will have to fail with the status of the connection.
if (mResponseIsPartial)
trans->Close(reason);
else
// The current transaction can be restarted via reset
// if the response has not started to arrive and the reason
// for failure is innocuous (e.g. not an SSL error)
if (!mResponseIsPartial &&
(reason == NS_ERROR_NET_RESET ||
reason == NS_OK ||
reason == NS_BASE_STREAM_CLOSED)) {
trans->Close(NS_ERROR_NET_RESET);
}
else {
trans->Close(reason);
}
NS_RELEASE(trans);
// any remaining pending responses can be restarted

Просмотреть файл

@ -57,11 +57,9 @@ public:
NS_DECL_NSAHTTPTRANSACTION
NS_DECL_NSAHTTPSEGMENTREADER
nsHttpPipeline();
nsHttpPipeline(PRUint16 maxPipelineDepth);
virtual ~nsHttpPipeline();
nsresult AddTransaction(nsAHttpTransaction *);
private:
nsresult FillSendBuf();
@ -84,6 +82,7 @@ private:
return mResponseQ[i];
}
PRUint16 mMaxPipelineDepth;
nsAHttpConnection *mConnection;
nsTArray<nsAHttpTransaction*> mRequestQ; // array of transactions
nsTArray<nsAHttpTransaction*> mResponseQ; // array of transactions
@ -99,6 +98,10 @@ private:
// indicates whether or not the pipeline has been explicitly closed.
bool mClosed;
// indicates whether or not a true pipeline (more than 1 request without
// a synchronous response) has been formed.
bool mUtilizedPipeline;
// used when calling ReadSegments/WriteSegments on a transaction.
nsAHttpSegmentReader *mReader;
nsAHttpSegmentWriter *mWriter;

Просмотреть файл

@ -456,6 +456,12 @@ nsHttpTransaction::Status()
return mStatus;
}
PRUint8
nsHttpTransaction::Caps()
{
return mCaps;
}
PRUint32
nsHttpTransaction::Available()
{
@ -704,6 +710,18 @@ nsHttpTransaction::Close(nsresult reason)
mPipeOut->CloseWithStatus(reason);
}
nsresult
nsHttpTransaction::AddTransaction(nsAHttpTransaction *trans)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
PRUint16
nsHttpTransaction::PipelineDepthAvailable()
{
return 0;
}
//-----------------------------------------------------------------------------
// nsHttpTransaction <private>
//-----------------------------------------------------------------------------

Просмотреть файл

@ -113,7 +113,6 @@ public:
nsIAsyncInputStream **responseBody);
// attributes
PRUint8 Caps() { return mCaps; }
nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; }
nsHttpResponseHead *ResponseHead() { return mHaveAllHeaders ? mResponseHead : nsnull; }
nsISupports *SecurityInfo() { return mSecurityInfo; }