mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 447866 pre patch 0 - pipeline and spdy mix r=honzab
This commit is contained in:
parent
2fed82f6c6
commit
ea7056c261
@ -1949,6 +1949,40 @@ SpdySession::Http1xTransactionCount()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// used as an enumerator by TakeSubTransactions()
|
||||
static PLDHashOperator
|
||||
TakeStream(nsAHttpTransaction *key,
|
||||
nsAutoPtr<SpdyStream> &stream,
|
||||
void *closure)
|
||||
{
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > *list =
|
||||
static_cast<nsTArray<nsRefPtr<nsAHttpTransaction> > *>(closure);
|
||||
|
||||
list->AppendElement(key);
|
||||
|
||||
// removing the stream from the hash will delete the stream
|
||||
// and drop the transaction reference the hash held
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdySession::TakeSubTransactions(
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions)
|
||||
{
|
||||
// Generally this cannot be done with spdy as transactions are
|
||||
// started right away.
|
||||
|
||||
LOG3(("SpdySession::TakeSubTransactions %p\n", this));
|
||||
|
||||
if (mConcurrentHighWater > 0)
|
||||
return NS_ERROR_ALREADY_OPENED;
|
||||
|
||||
LOG3((" taking %d\n", mStreamTransactionHash.Count()));
|
||||
|
||||
mStreamTransactionHash.Enumerate(TakeStream, &outTransactions);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Pass through methods of nsAHttpConnection
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define nsAHttpTransaction_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsAHttpConnection;
|
||||
class nsAHttpSegmentReader;
|
||||
@ -101,6 +102,18 @@ public:
|
||||
// abstract object. Pipelines may have multiple, SPDY has 0,
|
||||
// normal http transactions have 1.
|
||||
virtual PRUint32 Http1xTransactionCount() = 0;
|
||||
|
||||
// called to remove the unused sub transactions from an object that can
|
||||
// handle multiple transactions simultaneously (i.e. pipelines or spdy).
|
||||
//
|
||||
// Returns NS_ERROR_NOT_IMPLEMENTED if the object does not implement
|
||||
// sub-transactions.
|
||||
//
|
||||
// Returns NS_ERROR_ALREADY_OPENED if the subtransactions have been
|
||||
// at least partially written and cannot be moved.
|
||||
//
|
||||
virtual nsresult TakeSubTransactions(
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions) = 0;
|
||||
};
|
||||
|
||||
#define NS_DECL_NSAHTTPTRANSACTION \
|
||||
@ -118,7 +131,8 @@ public:
|
||||
void Close(nsresult reason); \
|
||||
void SetSSLConnectFailed(); \
|
||||
nsHttpRequestHead *RequestHead(); \
|
||||
PRUint32 Http1xTransactionCount();
|
||||
PRUint32 Http1xTransactionCount(); \
|
||||
nsresult TakeSubTransactions(nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsAHttpSegmentReader
|
||||
|
@ -170,6 +170,93 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnection::StartSpdy()
|
||||
{
|
||||
LOG(("nsHttpConnection::StartSpdy [this=%p]\n", this));
|
||||
|
||||
NS_ABORT_IF_FALSE(!mSpdySession, "mSpdySession should be null");
|
||||
|
||||
mUsingSpdy = true;
|
||||
mEverUsedSpdy = true;
|
||||
|
||||
// Setting the connection as reused allows some transactions that fail
|
||||
// with NS_ERROR_NET_RESET to be restarted and SPDY uses that code
|
||||
// to handle clean rejections (such as those that arrived after
|
||||
// a server goaway was generated).
|
||||
mIsReused = true;
|
||||
|
||||
// If mTransaction is a pipeline object it might represent
|
||||
// several requests. If so, we need to unpack that and
|
||||
// pack them all into a new spdy session.
|
||||
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > list;
|
||||
nsresult rv = mTransaction->TakeSubTransactions(list);
|
||||
|
||||
if (rv == NS_ERROR_ALREADY_OPENED) {
|
||||
// Has the interface for TakeSubTransactions() changed?
|
||||
LOG(("TakeSubTranscations somehow called after "
|
||||
"nsAHttpTransaction began processing\n"));
|
||||
NS_ABORT_IF_FALSE(false,
|
||||
"TakeSubTranscations somehow called after "
|
||||
"nsAHttpTransaction began processing");
|
||||
mTransaction->Close(NS_ERROR_ABORT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED) {
|
||||
// Has the interface for TakeSubTransactions() changed?
|
||||
LOG(("unexpected rv from nnsAHttpTransaction::TakeSubTransactions()"));
|
||||
NS_ABORT_IF_FALSE(false,
|
||||
"unexpected result from "
|
||||
"nsAHttpTransaction::TakeSubTransactions()");
|
||||
mTransaction->Close(NS_ERROR_ABORT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) { // includes NS_ERROR_NOT_IMPLEMENTED
|
||||
NS_ABORT_IF_FALSE(list.IsEmpty(), "sub transaction list not empty");
|
||||
|
||||
// This is ok - treat mTransaction as a single real request.
|
||||
// Wrap the old http transaction into the new spdy session
|
||||
// as the first stream.
|
||||
mSpdySession = new SpdySession(mTransaction,
|
||||
mSocketTransport,
|
||||
mPriority);
|
||||
LOG(("nsHttpConnection::StartSpdy moves single transaction %p "
|
||||
"into SpdySession %p\n", mTransaction.get(), mSpdySession.get()));
|
||||
}
|
||||
else {
|
||||
NS_ABORT_IF_FALSE(!list.IsEmpty(), "sub transaction list empty");
|
||||
|
||||
PRInt32 count = list.Length();
|
||||
|
||||
LOG(("nsHttpConnection::StartSpdy moving transaction list len=%d "
|
||||
"into SpdySession %p\n", count, mSpdySession.get()));
|
||||
|
||||
for (PRInt32 index = 0; index < count; ++index) {
|
||||
if (!mSpdySession) {
|
||||
mSpdySession = new SpdySession(list[index],
|
||||
mSocketTransport,
|
||||
mPriority);
|
||||
}
|
||||
else {
|
||||
// AddStream() cannot fail
|
||||
if (!mSpdySession->AddStream(list[index], mPriority)) {
|
||||
NS_ABORT_IF_FALSE(false, "SpdySession::AddStream failed");
|
||||
LOG(("SpdySession::AddStream failed\n"));
|
||||
mTransaction->Close(NS_ERROR_ABORT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mSupportsPipelining = false; // dont use http/1 pipelines with spdy
|
||||
mTransaction = mSpdySession;
|
||||
mIdleTimeout = gHttpHandler->SpdyTimeout();
|
||||
}
|
||||
|
||||
bool
|
||||
nsHttpConnection::EnsureNPNComplete()
|
||||
{
|
||||
@ -215,31 +302,15 @@ nsHttpConnection::EnsureNPNComplete()
|
||||
goto npnComplete;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
goto npnComplete;
|
||||
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete %p negotiated to '%s'",
|
||||
this, negotiatedNPN.get()));
|
||||
|
||||
if (negotiatedNPN.Equals(NS_LITERAL_CSTRING("spdy/2"))) {
|
||||
mUsingSpdy = true;
|
||||
mEverUsedSpdy = true;
|
||||
|
||||
// Setting the connection as reused allows some transactions that fail
|
||||
// with NS_ERROR_NET_RESET to be restarted and SPDY uses that code
|
||||
// to handle clean rejections (such as those that arrived after
|
||||
// a server goaway was generated).
|
||||
mIsReused = true;
|
||||
|
||||
// Wrap the old http transaction into the new spdy session
|
||||
// as the first stream
|
||||
mSpdySession = new SpdySession(mTransaction,
|
||||
mSocketTransport,
|
||||
mPriority);
|
||||
mTransaction = mSpdySession;
|
||||
mIdleTimeout = gHttpHandler->SpdyTimeout();
|
||||
}
|
||||
if (negotiatedNPN.Equals(NS_LITERAL_CSTRING("spdy/2")))
|
||||
StartSpdy();
|
||||
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SPDY_NPN_CONNECT,
|
||||
mUsingSpdy);
|
||||
|
@ -180,6 +180,9 @@ private:
|
||||
// redirections
|
||||
void HandleAlternateProtocol(nsHttpResponseHead *);
|
||||
|
||||
// Start the Spdy transaction handler when NPN indicates spdy/2
|
||||
void StartSpdy();
|
||||
|
||||
// Directly Add a transaction to an active connection for SPDY
|
||||
nsresult AddTransaction(nsAHttpTransaction *, PRInt32);
|
||||
|
||||
|
@ -364,6 +364,33 @@ nsHttpPipeline::Http1xTransactionCount()
|
||||
return mHttp1xTransactionCount;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpPipeline::TakeSubTransactions(
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions)
|
||||
{
|
||||
LOG(("nsHttpPipeline::TakeSubTransactions [this=%p]\n", this));
|
||||
|
||||
if (mResponseQ.Length() || mRequestIsPartial)
|
||||
return NS_ERROR_ALREADY_OPENED;
|
||||
|
||||
// request queue could be empty if it was already canceled, in which
|
||||
// case it is safe to treat this as a case without any
|
||||
// sub-transactions.
|
||||
if (!mRequestQ.Length())
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
PRInt32 i, count = mRequestQ.Length();
|
||||
for (i = 0; i < count; ++i) {
|
||||
nsAHttpTransaction *trans = Request(i);
|
||||
outTransactions.AppendElement(trans);
|
||||
NS_RELEASE(trans);
|
||||
}
|
||||
mRequestQ.Clear();
|
||||
|
||||
LOG((" took %d\n", count));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpPipeline::nsAHttpConnection
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -341,6 +341,13 @@ nsHttpTransaction::Http1xTransactionCount()
|
||||
return 1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpTransaction::TakeSubTransactions(
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsHttpTransaction::nsAHttpTransaction
|
||||
//----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user