mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
bug 1133177 - https tunnel of h1 without pconn inside h2 session stall r=hurley
This commit is contained in:
parent
d0b1783640
commit
0f9824c683
@ -33,6 +33,15 @@ public:
|
||||
|
||||
static ASpdySession *NewSpdySession(uint32_t version, nsISocketTransport *);
|
||||
|
||||
// MaybeReTunnel() is called by the connection manager when it cannot
|
||||
// dispatch a tunneled transaction. That might be because the tunnels it
|
||||
// expects to see are dead (and we may or may not be able to make more),
|
||||
// or it might just need to wait longer for one of them to become free.
|
||||
//
|
||||
// return true if the session takes back ownership of the transaction from
|
||||
// the connection manager.
|
||||
virtual bool MaybeReTunnel(nsAHttpTransaction *) = 0;
|
||||
|
||||
virtual void PrintDiagnostics (nsCString &log) = 0;
|
||||
|
||||
bool ResponseTimeoutEnabled() const MOZ_OVERRIDE MOZ_FINAL {
|
||||
|
@ -3271,6 +3271,24 @@ Http2Session::UnRegisterTunnel(Http2Stream *aTunnel)
|
||||
this, aTunnel, newcount, ci->HashKey().get()));
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::CreateTunnel(nsHttpTransaction *trans,
|
||||
nsHttpConnectionInfo *ci,
|
||||
nsIInterfaceRequestor *aCallbacks)
|
||||
{
|
||||
LOG(("Http2Session::CreateTunnel %p %p make new tunnel\n", this, trans));
|
||||
// The connect transaction will hold onto the underlying http
|
||||
// transaction so that an auth created by the connect can be mappped
|
||||
// to the correct security callbacks
|
||||
|
||||
nsRefPtr<SpdyConnectTransaction> connectTrans =
|
||||
new SpdyConnectTransaction(ci, aCallbacks, trans->Caps(), trans, this);
|
||||
AddStream(connectTrans, nsISupportsPriority::PRIORITY_NORMAL, false, nullptr);
|
||||
Http2Stream *tunnel = mStreamTransactionHash.Get(connectTrans);
|
||||
MOZ_ASSERT(tunnel);
|
||||
RegisterTunnel(tunnel);
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::DispatchOnTunnel(nsAHttpTransaction *aHttpTransaction,
|
||||
nsIInterfaceRequestor *aCallbacks)
|
||||
@ -3286,33 +3304,55 @@ Http2Session::DispatchOnTunnel(nsAHttpTransaction *aHttpTransaction,
|
||||
|
||||
// this transaction has done its work of setting up a tunnel, let
|
||||
// the connection manager queue it if necessary
|
||||
trans->SetDontRouteViaWildCard(true);
|
||||
trans->SetTunnelProvider(this);
|
||||
trans->EnableKeepAlive();
|
||||
|
||||
if (FindTunnelCount(ci) < gHttpHandler->MaxConnectionsPerOrigin()) {
|
||||
LOG3(("Http2Session::DispatchOnTunnel %p create on new tunnel %s",
|
||||
this, ci->HashKey().get()));
|
||||
// The connect transaction will hold onto the underlying http
|
||||
// transaction so that an auth created by the connect can be mappped
|
||||
// to the correct security callbacks
|
||||
nsRefPtr<SpdyConnectTransaction> connectTrans =
|
||||
new SpdyConnectTransaction(ci, aCallbacks,
|
||||
trans->Caps(), trans, this);
|
||||
AddStream(connectTrans, nsISupportsPriority::PRIORITY_NORMAL,
|
||||
false, nullptr);
|
||||
Http2Stream *tunnel = mStreamTransactionHash.Get(connectTrans);
|
||||
MOZ_ASSERT(tunnel);
|
||||
RegisterTunnel(tunnel);
|
||||
CreateTunnel(trans, ci, aCallbacks);
|
||||
} else {
|
||||
// requeue it. The connection manager is responsible for actually putting
|
||||
// this on the tunnel connection with the specific ci now that it
|
||||
// has DontRouteViaWildCard set.
|
||||
// this on the tunnel connection with the specific ci. If that can't
|
||||
// happen the cmgr checks with us via MaybeReTunnel() to see if it should
|
||||
// make a new tunnel or just wait longer.
|
||||
LOG3(("Http2Session::DispatchOnTunnel %p trans=%p queue in connection manager",
|
||||
this, trans));
|
||||
gHttpHandler->InitiateTransaction(trans, trans->Priority());
|
||||
}
|
||||
}
|
||||
|
||||
// From ASpdySession
|
||||
bool
|
||||
Http2Session::MaybeReTunnel(nsAHttpTransaction *aHttpTransaction)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
nsHttpTransaction *trans = aHttpTransaction->QueryHttpTransaction();
|
||||
LOG(("Http2Session::MaybeReTunnel %p trans=%p\n", this, trans));
|
||||
if (!trans || trans->TunnelProvider() != this) {
|
||||
// this isn't really one of our transactions.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mClosed || mShouldGoAway) {
|
||||
LOG(("Http2Session::MaybeReTunnel %p %p session closed - requeue\n", this, trans));
|
||||
trans->SetTunnelProvider(nullptr);
|
||||
gHttpHandler->InitiateTransaction(trans, trans->Priority());
|
||||
return true;
|
||||
}
|
||||
|
||||
nsHttpConnectionInfo *ci = aHttpTransaction->ConnectionInfo();
|
||||
LOG(("Http2Session:MaybeReTunnel %p %p count=%d limit %d\n",
|
||||
this, trans, FindTunnelCount(ci), gHttpHandler->MaxConnectionsPerOrigin()));
|
||||
if (FindTunnelCount(ci) >= gHttpHandler->MaxConnectionsPerOrigin()) {
|
||||
// patience - a tunnel will open up.
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(("Http2Session::MaybeReTunnel %p %p make new tunnel\n", this, trans));
|
||||
CreateTunnel(trans, ci, trans->SecurityCallbacks());
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Http2Session::BufferOutput(const char *buf,
|
||||
|
@ -224,7 +224,7 @@ public:
|
||||
void GetNegotiatedToken(nsACString &s) { s.Assign(mNegotiatedToken); }
|
||||
|
||||
void SendPing() MOZ_OVERRIDE;
|
||||
|
||||
bool MaybeReTunnel(nsAHttpTransaction *) MOZ_OVERRIDE;
|
||||
bool UseH2Deps() { return mUseH2Deps; }
|
||||
|
||||
private:
|
||||
@ -488,10 +488,10 @@ private:
|
||||
private:
|
||||
/// connect tunnels
|
||||
void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);
|
||||
void CreateTunnel(nsHttpTransaction *, nsHttpConnectionInfo *, nsIInterfaceRequestor *);
|
||||
void RegisterTunnel(Http2Stream *);
|
||||
void UnRegisterTunnel(Http2Stream *);
|
||||
uint32_t FindTunnelCount(nsHttpConnectionInfo *);
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, uint32_t> mTunnelHash;
|
||||
};
|
||||
|
||||
|
@ -2711,13 +2711,30 @@ SpdySession31::UnRegisterTunnel(SpdyStream31 *aTunnel)
|
||||
this, aTunnel, newcount, ci->HashKey().get()));
|
||||
}
|
||||
|
||||
void
|
||||
SpdySession31::CreateTunnel(nsHttpTransaction *trans,
|
||||
nsHttpConnectionInfo *ci,
|
||||
nsIInterfaceRequestor *aCallbacks)
|
||||
{
|
||||
LOG(("SpdySession31::CreateTunnel %p %p make new tunnel\n", this, trans));
|
||||
// The connect transaction will hold onto the underlying http
|
||||
// transaction so that an auth created by the connect can be mappped
|
||||
// to the correct security callbacks
|
||||
|
||||
nsRefPtr<SpdyConnectTransaction> connectTrans =
|
||||
new SpdyConnectTransaction(ci, aCallbacks, trans->Caps(), trans, this);
|
||||
AddStream(connectTrans, nsISupportsPriority::PRIORITY_NORMAL, false, nullptr);
|
||||
SpdyStream31 *tunnel = mStreamTransactionHash.Get(connectTrans);
|
||||
MOZ_ASSERT(tunnel);
|
||||
RegisterTunnel(tunnel);
|
||||
}
|
||||
|
||||
void
|
||||
SpdySession31::DispatchOnTunnel(nsAHttpTransaction *aHttpTransaction,
|
||||
nsIInterfaceRequestor *aCallbacks)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
nsHttpTransaction *trans = aHttpTransaction->QueryHttpTransaction();
|
||||
nsHttpConnectionInfo *ci = aHttpTransaction->ConnectionInfo();
|
||||
MOZ_ASSERT(trans);
|
||||
|
||||
LOG3(("SpdySession31::DispatchOnTunnel %p trans=%p", this, trans));
|
||||
@ -2726,33 +2743,57 @@ SpdySession31::DispatchOnTunnel(nsAHttpTransaction *aHttpTransaction,
|
||||
|
||||
// this transaction has done its work of setting up a tunnel, let
|
||||
// the connection manager queue it if necessary
|
||||
trans->SetDontRouteViaWildCard(true);
|
||||
trans->SetTunnelProvider(this);
|
||||
trans->EnableKeepAlive();
|
||||
|
||||
nsHttpConnectionInfo *ci = aHttpTransaction->ConnectionInfo();
|
||||
if (FindTunnelCount(ci) < gHttpHandler->MaxConnectionsPerOrigin()) {
|
||||
LOG3(("SpdySession31::DispatchOnTunnel %p create on new tunnel %s",
|
||||
this, ci->HashKey().get()));
|
||||
// The connect transaction will hold onto the underlying http
|
||||
// transaction so that an auth created by the connect can be mappped
|
||||
// to the correct security callbacks
|
||||
nsRefPtr<SpdyConnectTransaction> connectTrans =
|
||||
new SpdyConnectTransaction(ci, aCallbacks,
|
||||
trans->Caps(), trans, this);
|
||||
AddStream(connectTrans, nsISupportsPriority::PRIORITY_NORMAL,
|
||||
false, nullptr);
|
||||
SpdyStream31 *tunnel = mStreamTransactionHash.Get(connectTrans);
|
||||
MOZ_ASSERT(tunnel);
|
||||
RegisterTunnel(tunnel);
|
||||
CreateTunnel(trans, ci, aCallbacks);
|
||||
} else {
|
||||
// requeue it. The connection manager is responsible for actually putting
|
||||
// this on the tunnel connection with the specific ci now that it
|
||||
// has DontRouteViaWildCard set.
|
||||
// this on the tunnel connection with the specific ci. If that can't
|
||||
// happen the cmgr checks with us via MaybeReTunnel() to see if it should
|
||||
// make a new tunnel or just wait longer.
|
||||
LOG3(("SpdySession31::DispatchOnTunnel %p trans=%p queue in connection manager",
|
||||
this, trans));
|
||||
gHttpHandler->InitiateTransaction(trans, trans->Priority());
|
||||
}
|
||||
}
|
||||
|
||||
// From ASpdySession
|
||||
bool
|
||||
SpdySession31::MaybeReTunnel(nsAHttpTransaction *aHttpTransaction)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
nsHttpTransaction *trans = aHttpTransaction->QueryHttpTransaction();
|
||||
LOG(("SpdySession31::MaybeReTunnel %p trans=%p\n", this, trans));
|
||||
nsHttpConnectionInfo *ci = aHttpTransaction->ConnectionInfo();
|
||||
if (!trans || trans->TunnelProvider() != this) {
|
||||
// this isn't really one of our transactions.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mClosed || mShouldGoAway) {
|
||||
LOG(("SpdySession31::MaybeReTunnel %p %p session closed - requeue\n", this, trans));
|
||||
trans->SetTunnelProvider(nullptr);
|
||||
gHttpHandler->InitiateTransaction(trans, trans->Priority());
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG(("SpdySession31::MaybeReTunnel %p %p count=%d limit %d\n",
|
||||
this, trans, FindTunnelCount(ci), gHttpHandler->MaxConnectionsPerOrigin()));
|
||||
if (FindTunnelCount(ci) >= gHttpHandler->MaxConnectionsPerOrigin()) {
|
||||
// patience - a tunnel will open up.
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(("SpdySession31::MaybeReTunnel %p %p make new tunnel\n", this, trans));
|
||||
CreateTunnel(trans, ci, trans->SecurityCallbacks());
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdySession31::BufferOutput(const char *buf,
|
||||
uint32_t count,
|
||||
|
@ -195,6 +195,8 @@ public:
|
||||
|
||||
void SendPing() MOZ_OVERRIDE;
|
||||
|
||||
bool MaybeReTunnel(nsAHttpTransaction *) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
enum stateType {
|
||||
@ -415,6 +417,7 @@ private:
|
||||
private:
|
||||
/// connect tunnels
|
||||
void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);
|
||||
void CreateTunnel(nsHttpTransaction *, nsHttpConnectionInfo *, nsIInterfaceRequestor *);
|
||||
void RegisterTunnel(SpdyStream31 *);
|
||||
void UnRegisterTunnel(SpdyStream31 *);
|
||||
uint32_t FindTunnelCount(nsHttpConnectionInfo *);
|
||||
|
@ -1207,7 +1207,7 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent, bool consid
|
||||
}
|
||||
|
||||
rv = TryDispatchTransaction(ent,
|
||||
alreadyHalfOpen || trans->DontRouteViaWildCard(),
|
||||
alreadyHalfOpen || !!trans->TunnelProvider(),
|
||||
trans);
|
||||
if (NS_SUCCEEDED(rv) || (rv != NS_ERROR_NOT_AVAILABLE)) {
|
||||
if (NS_SUCCEEDED(rv))
|
||||
@ -1734,10 +1734,10 @@ nsHttpConnectionMgr::TryDispatchTransaction(nsConnectionEntry *ent,
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
LOG(("nsHttpConnectionMgr::TryDispatchTransaction without conn "
|
||||
"[trans=%p ci=%p ci=%s caps=%x wildcardok=%d onlyreused=%d "
|
||||
"[trans=%p ci=%p ci=%s caps=%x tunnelprovider=%p onlyreused=%d "
|
||||
"active=%d idle=%d]\n", trans,
|
||||
ent->mConnInfo.get(), ent->mConnInfo->HashKey().get(),
|
||||
uint32_t(trans->Caps()), !trans->DontRouteViaWildCard(),
|
||||
uint32_t(trans->Caps()), trans->TunnelProvider(),
|
||||
onlyReusedConnection, ent->mActiveConns.Length(),
|
||||
ent->mIdleConns.Length()));
|
||||
|
||||
@ -1901,6 +1901,10 @@ nsHttpConnectionMgr::TryDispatchTransaction(nsConnectionEntry *ent,
|
||||
LOG((" failed step 4 (%x) trans=%p\n", rv, trans));
|
||||
return rv;
|
||||
}
|
||||
} else if (trans->TunnelProvider() && trans->TunnelProvider()->MaybeReTunnel(trans)) {
|
||||
LOG((" sort of dispatched step 4a tunnel requeue trans=%p\n", trans));
|
||||
// the tunnel provider took responsibility for making a new tunnel
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// step 5
|
||||
@ -2111,7 +2115,7 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans)
|
||||
MOZ_ASSERT(ci);
|
||||
|
||||
nsConnectionEntry *ent =
|
||||
GetOrCreateConnectionEntry(ci, trans->DontRouteViaWildCard());
|
||||
GetOrCreateConnectionEntry(ci, !!trans->TunnelProvider());
|
||||
|
||||
// SPDY coalescing of hostnames means we might redirect from this
|
||||
// connection entry onto the preferred one.
|
||||
@ -2155,7 +2159,7 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans)
|
||||
trans->SetConnection(nullptr);
|
||||
rv = DispatchTransaction(ent, trans, conn);
|
||||
} else {
|
||||
rv = TryDispatchTransaction(ent, trans->DontRouteViaWildCard(), trans);
|
||||
rv = TryDispatchTransaction(ent, !!trans->TunnelProvider(), trans);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
@ -123,7 +123,6 @@ nsHttpTransaction::nsHttpTransaction()
|
||||
, mPreserveStream(false)
|
||||
, mDispatchedAsBlocking(false)
|
||||
, mResponseTimeoutEnabled(true)
|
||||
, mDontRouteViaWildCard(false)
|
||||
, mForceRestart(false)
|
||||
, mReuseOnRestart(false)
|
||||
, mReportedStart(false)
|
||||
@ -848,6 +847,7 @@ nsHttpTransaction::Close(nsresult reason)
|
||||
if (mConnection)
|
||||
connReused = mConnection->IsReused();
|
||||
mConnected = false;
|
||||
mTunnelProvider = nullptr;
|
||||
|
||||
//
|
||||
// if the connection was reset or closed before we wrote any part of the
|
||||
@ -1123,7 +1123,7 @@ nsHttpTransaction::Restart()
|
||||
}
|
||||
|
||||
LOG(("restarting transaction @%p\n", this));
|
||||
SetDontRouteViaWildCard(false);
|
||||
mTunnelProvider = nullptr;
|
||||
|
||||
// rewind streams in case we already wrote out the request
|
||||
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mRequestStream);
|
||||
|
@ -107,13 +107,6 @@ public:
|
||||
|
||||
bool ProxyConnectFailed() { return mProxyConnectFailed; }
|
||||
|
||||
// setting mDontRouteViaWildCard to true means the transaction should only
|
||||
// be dispatched on a specific ConnectionInfo Hash Key (as opposed to a
|
||||
// generic wild card one). That means in the specific case of carrying this
|
||||
// transaction on an HTTP/2 tunnel it will only be dispatched onto an
|
||||
// existing tunnel instead of triggering creation of a new one.
|
||||
void SetDontRouteViaWildCard(bool var) { mDontRouteViaWildCard = var; }
|
||||
bool DontRouteViaWildCard() { return mDontRouteViaWildCard; }
|
||||
void EnableKeepAlive() { mCaps |= NS_HTTP_ALLOW_KEEPALIVE; }
|
||||
void MakeSticky() { mCaps |= NS_HTTP_STICKY_CONNECTION; }
|
||||
|
||||
@ -282,7 +275,6 @@ private:
|
||||
bool mPreserveStream;
|
||||
bool mDispatchedAsBlocking;
|
||||
bool mResponseTimeoutEnabled;
|
||||
bool mDontRouteViaWildCard;
|
||||
bool mForceRestart;
|
||||
bool mReuseOnRestart;
|
||||
|
||||
@ -414,6 +406,21 @@ public:
|
||||
uint32_t ClassOfService() { return mClassOfService; }
|
||||
private:
|
||||
uint32_t mClassOfService;
|
||||
|
||||
public:
|
||||
// setting TunnelProvider to non-null means the transaction should only
|
||||
// be dispatched on a specific ConnectionInfo Hash Key (as opposed to a
|
||||
// generic wild card one). That means in the specific case of carrying this
|
||||
// transaction on an HTTP/2 tunnel it will only be dispatched onto an
|
||||
// existing tunnel instead of triggering creation of a new one.
|
||||
// The tunnel provider is used for ASpdySession::MaybeReTunnel() checks.
|
||||
|
||||
void SetTunnelProvider(ASpdySession *provider) { mTunnelProvider = provider; }
|
||||
ASpdySession *TunnelProvider() { return mTunnelProvider; }
|
||||
nsIInterfaceRequestor *SecurityCallbacks() { return mCallbacks; }
|
||||
|
||||
private:
|
||||
nsRefPtr<ASpdySession> mTunnelProvider;
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
Loading…
Reference in New Issue
Block a user