diff --git a/netwerk/protocol/http/Http2Session.cpp b/netwerk/protocol/http/Http2Session.cpp index cbd2b28b92a8..7ebe4c728cfc 100644 --- a/netwerk/protocol/http/Http2Session.cpp +++ b/netwerk/protocol/http/Http2Session.cpp @@ -89,6 +89,7 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t versio , mShouldGoAway(false) , mClosed(false) , mCleanShutdown(false) + , mReceivedSettings(false) , mTLSProfileConfirmed(false) , mGoAwayReason(NO_HTTP_ERROR) , mClientGoAwayReason(UNASSIGNED) @@ -1504,6 +1505,8 @@ Http2Session::RecvSettings(Http2Session *self) RETURN_SESSION_ERROR(self, PROTOCOL_ERROR); } + self->mReceivedSettings = true; + uint32_t numEntries = self->mInputFrameDataSize / 6; LOG3(("Http2Session::RecvSettings %p SETTINGS Control Frame " "with %d entries ack=%X", self, numEntries, @@ -4153,49 +4156,20 @@ Http2Session::TestOriginFrame(const nsACString &hostname, int32_t port) bool Http2Session::TestJoinConnection(const nsACString &hostname, int32_t port) { - if (!mConnection || mClosed || mShouldGoAway) { - return false; - } - - if (mOriginFrameActivated) { - bool originFrameResult = TestOriginFrame(hostname, port); - if (!originFrameResult) { - return false; - } - } else { - LOG3(("TestJoinConnection %p no origin frame check used.\n", this)); - } - - nsresult rv; - bool isJoined = false; - - nsCOMPtr securityInfo; - nsCOMPtr sslSocketControl; - - mConnection->GetSecurityInfo(getter_AddRefs(securityInfo)); - sslSocketControl = do_QueryInterface(securityInfo, &rv); - if (NS_FAILED(rv) || !sslSocketControl) { - return false; - } - - // try all the coalescable versions we support. - const SpdyInformation *info = gHttpHandler->SpdyInfo(); - for (uint32_t index = SpdyInformation::kCount; index > 0; --index) { - if (info->ProtocolEnabled(index - 1)) { - rv = sslSocketControl->TestJoinConnection(info->VersionString[index - 1], - hostname, port, &isJoined); - if (NS_SUCCEEDED(rv) && isJoined) { - return true; - } - } - } - return false; + return RealJoinConnection(hostname, port, true); } bool Http2Session::JoinConnection(const nsACString &hostname, int32_t port) { - if (!mConnection || mClosed || mShouldGoAway) { + return RealJoinConnection(hostname, port, false); +} + +bool +Http2Session::RealJoinConnection(const nsACString &hostname, int32_t port, + bool justKidding) +{ + if (!mConnection || mClosed || mShouldGoAway || !mReceivedSettings) { return false; } if (mOriginFrameActivated) { @@ -4207,6 +4181,18 @@ Http2Session::JoinConnection(const nsACString &hostname, int32_t port) LOG3(("JoinConnection %p no origin frame check used.\n", this)); } + nsAutoCString key(hostname); + key.Append(':'); + key.Append(justKidding ? 'k' : '.'); + key.AppendInt(port); + bool cachedResult; + if (mJoinConnectionCache.Get(key, &cachedResult)) { + LOG(("joinconnection [%p %s] %s result=%d cache\n", + this, ConnectionInfo()->HashKey().get(), key.get(), + cachedResult)); + return cachedResult; + } + nsresult rv; bool isJoined = false; @@ -4221,16 +4207,35 @@ Http2Session::JoinConnection(const nsACString &hostname, int32_t port) // try all the coalescable versions we support. const SpdyInformation *info = gHttpHandler->SpdyInfo(); - for (uint32_t index = SpdyInformation::kCount; index > 0; --index) { - if (info->ProtocolEnabled(index - 1)) { - rv = sslSocketControl->JoinConnection(info->VersionString[index - 1], + static_assert(SpdyInformation::kCount == 1, "assume 1 alpn version"); + bool joinedReturn = false; + if (info->ProtocolEnabled(0)) { + if (justKidding) { + rv = sslSocketControl->TestJoinConnection(info->VersionString[0], + hostname, port, &isJoined); + } else { + rv = sslSocketControl->JoinConnection(info->VersionString[0], hostname, port, &isJoined); - if (NS_SUCCEEDED(rv) && isJoined) { - return true; - } + } + if (NS_SUCCEEDED(rv) && isJoined) { + joinedReturn = true; } } - return false; + + LOG(("joinconnection [%p %s] %s result=%d lookup\n", + this, ConnectionInfo()->HashKey().get(), key.get(), joinedReturn)); + mJoinConnectionCache.Put(key, joinedReturn); + if (!justKidding) { + // cache a kidding entry too as this one is good for both + nsAutoCString key2(hostname); + key2.Append(':'); + key2.Append('k'); + key2.AppendInt(port); + if (!mJoinConnectionCache.Get(key2)) { + mJoinConnectionCache.Put(key2, joinedReturn); + } + } + return joinedReturn; } void diff --git a/netwerk/protocol/http/Http2Session.h b/netwerk/protocol/http/Http2Session.h index 50e5a94a27d7..3054de77acb8 100644 --- a/netwerk/protocol/http/Http2Session.h +++ b/netwerk/protocol/http/Http2Session.h @@ -427,6 +427,9 @@ private: // the session received a GoAway frame with a valid GoAwayID bool mCleanShutdown; + // the session received the opening SETTINGS frame from the server + bool mReceivedSettings; + // The TLS comlpiance checks are not done in the ctor beacuse of bad // exception handling - so we do them at IO time and cache the result bool mTLSProfileConfirmed; @@ -518,10 +521,13 @@ private: // The ID(s) of the stream(s) that we are getting 0RTT data from. nsTArray m0RTTStreams; + bool RealJoinConnection(const nsACString &hostname, int32_t port, bool jk); bool TestOriginFrame(const nsACString &name, int32_t port); bool mOriginFrameActivated; nsDataHashtable mOriginFrame; + nsDataHashtable mJoinConnectionCache; + private: /// connect tunnels void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);