зеркало из https://github.com/mozilla/pjs.git
bug 528288 - HTTP Alternate-Protocol header for transitioning from http to spdy r=honzab
patch 2
This commit is contained in:
Родитель
d2a1f4ee74
Коммит
6ffb7859e6
|
@ -56,6 +56,7 @@ HTTP_ATOM(Accept_Language, "Accept-Language")
|
|||
HTTP_ATOM(Accept_Ranges, "Accept-Ranges")
|
||||
HTTP_ATOM(Age, "Age")
|
||||
HTTP_ATOM(Allow, "Allow")
|
||||
HTTP_ATOM(Alternate_Protocol, "Alternate-Protocol")
|
||||
HTTP_ATOM(Authentication, "Authentication")
|
||||
HTTP_ATOM(Authorization, "Authorization")
|
||||
HTTP_ATOM(Cache_Control, "Cache-Control")
|
||||
|
|
|
@ -209,6 +209,18 @@ nsHttpChannel::Connect(bool firstTime)
|
|||
LOG(("nsHttpChannel::Connect() STS permissions found\n"));
|
||||
return AsyncCall(&nsHttpChannel::HandleAsyncRedirectChannelToHttps);
|
||||
}
|
||||
|
||||
// Check for a previous SPDY Alternate-Protocol directive
|
||||
if (gHttpHandler->IsSpdyEnabled()) {
|
||||
nsCAutoString hostPort;
|
||||
|
||||
if (NS_SUCCEEDED(mURI->GetHostPort(hostPort)) &&
|
||||
gHttpHandler->ConnMgr()->GetSpdyAlternateProtocol(hostPort)) {
|
||||
LOG(("nsHttpChannel::Connect() Alternate-Protocol found\n"));
|
||||
return AsyncCall(
|
||||
&nsHttpChannel::HandleAsyncRedirectChannelToHttps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that we are using a valid hostname
|
||||
|
@ -4091,6 +4103,16 @@ nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
|||
mSecurityInfo = mTransaction->SecurityInfo();
|
||||
}
|
||||
|
||||
if (gHttpHandler->IsSpdyEnabled() && !mCachePump && NS_FAILED(mStatus) &&
|
||||
(mLoadFlags & LOAD_REPLACE) && mOriginalURI) {
|
||||
// For sanity's sake we may want to cancel an alternate protocol
|
||||
// redirection involving the original host name
|
||||
|
||||
nsCAutoString hostPort;
|
||||
if (NS_SUCCEEDED(mOriginalURI->GetHostPort(hostPort)))
|
||||
gHttpHandler->ConnMgr()->RemoveSpdyAlternateProtocol(hostPort);
|
||||
}
|
||||
|
||||
// don't enter this block if we're reading from the cache...
|
||||
if (NS_SUCCEEDED(mStatus) && !mCachePump && mTransaction) {
|
||||
// mTransactionPump doesn't hit OnInputStreamReady and call this until
|
||||
|
|
|
@ -320,6 +320,32 @@ nsHttpConnection::SetupNPN(PRUint8 caps)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnection::HandleAlternateProtocol(nsHttpResponseHead *responseHead)
|
||||
{
|
||||
// Look for the Alternate-Protocol header. Alternate-Protocol is
|
||||
// essentially a way to rediect future transactions from http to
|
||||
// spdy.
|
||||
//
|
||||
|
||||
if (!gHttpHandler->IsSpdyEnabled() || mUsingSpdy)
|
||||
return;
|
||||
|
||||
const char *val = responseHead->PeekHeader(nsHttp::Alternate_Protocol);
|
||||
if (!val)
|
||||
return;
|
||||
|
||||
// The spec allows redirections to any port, but due to concerns over
|
||||
// silently redirecting to stealth ports we only allow port 443
|
||||
//
|
||||
// Alternate-Protocol: 5678:somethingelse, 443:npn-spdy/2
|
||||
|
||||
if (nsHttp::FindToken(val, "443:npn-spdy/2", HTTP_HEADER_VALUE_SEPS)) {
|
||||
LOG(("Connection %p Transaction %p found Alternate-Protocol "
|
||||
"header %s", this, mTransaction.get(), val));
|
||||
gHttpHandler->ConnMgr()->ReportSpdyAlternateProtocol(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpConnection::AddTransaction(nsAHttpTransaction *httpTransaction,
|
||||
|
@ -615,6 +641,9 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans,
|
|||
LOG(("Connection can be reused [this=%x idle-timeout=%u]\n", this, mIdleTimeout));
|
||||
}
|
||||
|
||||
if (!mProxyConnectStream)
|
||||
HandleAlternateProtocol(responseHead);
|
||||
|
||||
// if we're doing an SSL proxy connect, then we need to check whether or not
|
||||
// the connect was successful. if so, then we have to reset the transaction
|
||||
// and step-up the socket connection to SSL. finally, we have to wake up the
|
||||
|
|
|
@ -176,6 +176,10 @@ private:
|
|||
bool EnsureNPNComplete();
|
||||
void SetupNPN(PRUint8 caps);
|
||||
|
||||
// Inform the connection manager of any SPDY Alternate-Protocol
|
||||
// redirections
|
||||
void HandleAlternateProtocol(nsHttpResponseHead *);
|
||||
|
||||
// Directly Add a transaction to an active connection for SPDY
|
||||
nsresult AddTransaction(nsAHttpTransaction *, PRInt32);
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ nsHttpConnectionMgr::nsHttpConnectionMgr()
|
|||
{
|
||||
LOG(("Creating nsHttpConnectionMgr @%x\n", this));
|
||||
mCT.Init();
|
||||
mAlternateProtocolHash.Init(16);
|
||||
}
|
||||
|
||||
nsHttpConnectionMgr::~nsHttpConnectionMgr()
|
||||
|
@ -466,6 +467,68 @@ nsHttpConnectionMgr::ReportSpdyConnection(nsHttpConnection *conn,
|
|||
ProcessSpdyPendingQ();
|
||||
}
|
||||
|
||||
bool
|
||||
nsHttpConnectionMgr::GetSpdyAlternateProtocol(nsACString &hostPortKey)
|
||||
{
|
||||
// The Alternate Protocol hash is protected under the monitor because
|
||||
// it is read from both the main and the network thread.
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
return mAlternateProtocolHash.Contains(hostPortKey);
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::ReportSpdyAlternateProtocol(nsHttpConnection *conn)
|
||||
{
|
||||
// For now lets not bypass proxies due to the alternate-protocol header
|
||||
if (conn->ConnectionInfo()->UsingHttpProxy())
|
||||
return;
|
||||
|
||||
nsCString hostPortKey(conn->ConnectionInfo()->Host());
|
||||
if (conn->ConnectionInfo()->Port() != 80) {
|
||||
hostPortKey.Append(NS_LITERAL_CSTRING(":"));
|
||||
hostPortKey.AppendInt(conn->ConnectionInfo()->Port());
|
||||
}
|
||||
|
||||
// The Alternate Protocol hash is protected under the monitor because
|
||||
// it is read from both the main and the network thread.
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
// Check to see if this is already present
|
||||
if (mAlternateProtocolHash.Contains(hostPortKey))
|
||||
return;
|
||||
|
||||
if (mAlternateProtocolHash.mHashTable.entryCount > 2000)
|
||||
PL_DHashTableEnumerate(&mAlternateProtocolHash.mHashTable,
|
||||
&nsHttpConnectionMgr::TrimAlternateProtocolHash,
|
||||
this);
|
||||
|
||||
mAlternateProtocolHash.Put(hostPortKey);
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::RemoveSpdyAlternateProtocol(nsACString &hostPortKey)
|
||||
{
|
||||
// The Alternate Protocol hash is protected under the monitor because
|
||||
// it is read from both the main and the network thread.
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
return mAlternateProtocolHash.Remove(hostPortKey);
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsHttpConnectionMgr::TrimAlternateProtocolHash(PLDHashTable *table,
|
||||
PLDHashEntryHdr *hdr,
|
||||
PRUint32 number,
|
||||
void *closure)
|
||||
{
|
||||
nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
|
||||
|
||||
if (self->mAlternateProtocolHash.mHashTable.entryCount > 2000)
|
||||
return PL_DHASH_REMOVE;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
nsHttpConnectionMgr::nsConnectionEntry *
|
||||
nsHttpConnectionMgr::GetSpdyPreferred(nsACString &aDottedDecimal)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "nsISocketTransportService.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsHashSets.h"
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
|
@ -133,6 +134,11 @@ public:
|
|||
// been initialized.
|
||||
nsresult UpdateParam(nsParamName name, PRUint16 value);
|
||||
|
||||
// Lookup/Cancel HTTP->SPDY redirections
|
||||
bool GetSpdyAlternateProtocol(nsACString &key);
|
||||
void ReportSpdyAlternateProtocol(nsHttpConnection *);
|
||||
void RemoveSpdyAlternateProtocol(nsACString &key);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// NOTE: functions below may be called only on the socket thread.
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -405,6 +411,13 @@ private:
|
|||
// nsConnectionEntry object.
|
||||
//
|
||||
nsClassHashtable<nsCStringHashKey, nsConnectionEntry> mCT;
|
||||
|
||||
// this table is protected by the monitor
|
||||
nsCStringHashSet mAlternateProtocolHash;
|
||||
static PLDHashOperator TrimAlternateProtocolHash(PLDHashTable *table,
|
||||
PLDHashEntryHdr *hdr,
|
||||
PRUint32 number,
|
||||
void *closure);
|
||||
};
|
||||
|
||||
#endif // !nsHttpConnectionMgr_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче