mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-22 02:09:28 +00:00
bug 1129571 - h2/spdy coalsescing by full DNS rrset r=hurley
This commit is contained in:
parent
811d8614fd
commit
c2d290654c
@ -1988,11 +1988,13 @@ NS_IMPL_ISUPPORTS(nsSocketTransport,
|
||||
nsISocketTransport,
|
||||
nsITransport,
|
||||
nsIDNSListener,
|
||||
nsIClassInfo)
|
||||
nsIClassInfo,
|
||||
nsIInterfaceRequestor)
|
||||
NS_IMPL_CI_INTERFACE_GETTER(nsSocketTransport,
|
||||
nsISocketTransport,
|
||||
nsITransport,
|
||||
nsIDNSListener)
|
||||
nsIDNSListener,
|
||||
nsIInterfaceRequestor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::OpenInputStream(uint32_t flags,
|
||||
@ -2419,6 +2421,17 @@ nsSocketTransport::OnLookupComplete(nsICancelable *request,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIInterfaceRequestor
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::GetInterface(const nsIID &iid, void **result)
|
||||
{
|
||||
if (iid.Equals(NS_GET_IID(nsIDNSRecord))) {
|
||||
return mDNSRecord ?
|
||||
mDNSRecord->QueryInterface(iid, result) : NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
return this->QueryInterface(iid, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::GetInterfaces(uint32_t *count, nsIID * **array)
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsISocketTransport.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
@ -108,6 +109,7 @@ class nsSocketTransport MOZ_FINAL : public nsASocketHandler
|
||||
, public nsISocketTransport
|
||||
, public nsIDNSListener
|
||||
, public nsIClassInfo
|
||||
, public nsIInterfaceRequestor
|
||||
{
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
@ -117,6 +119,7 @@ public:
|
||||
NS_DECL_NSISOCKETTRANSPORT
|
||||
NS_DECL_NSIDNSLISTENER
|
||||
NS_DECL_NSICLASSINFO
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
nsSocketTransport();
|
||||
|
||||
|
@ -94,6 +94,13 @@ ChildDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChildDNSRecord::GetAddresses(nsTArray<NetAddr> & aAddressArray)
|
||||
{
|
||||
aAddressArray = mAddresses;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// shamelessly copied from nsDNSRecord
|
||||
NS_IMETHODIMP
|
||||
ChildDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr **result)
|
||||
|
@ -172,6 +172,46 @@ nsDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSRecord::GetAddresses(nsTArray<NetAddr> & aAddressArray)
|
||||
{
|
||||
if (mDone) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
mHostRecord->addr_info_lock.Lock();
|
||||
if (mHostRecord->addr_info) {
|
||||
for (NetAddrElement *iter = mHostRecord->addr_info->mAddresses.getFirst();
|
||||
iter; iter = iter->getNext()) {
|
||||
if (mHostRecord->Blacklisted(&iter->mAddress)) {
|
||||
continue;
|
||||
}
|
||||
NetAddr *addr = aAddressArray.AppendElement(NetAddr());
|
||||
memcpy(addr, &iter->mAddress, sizeof(NetAddr));
|
||||
if (addr->raw.family == AF_INET) {
|
||||
addr->inet.port = 0;
|
||||
} else if (addr->raw.family == AF_INET6) {
|
||||
addr->inet6.port = 0;
|
||||
}
|
||||
}
|
||||
mHostRecord->addr_info_lock.Unlock();
|
||||
} else {
|
||||
mHostRecord->addr_info_lock.Unlock();
|
||||
|
||||
if (!mHostRecord->addr) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
NetAddr *addr = aAddressArray.AppendElement(NetAddr());
|
||||
memcpy(addr, mHostRecord->addr, sizeof(NetAddr));
|
||||
if (addr->raw.family == AF_INET) {
|
||||
addr->inet.port = 0;
|
||||
} else if (addr->raw.family == AF_INET6) {
|
||||
addr->inet6.port = 0;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr * *result)
|
||||
{
|
||||
|
@ -10,8 +10,10 @@ namespace net {
|
||||
union NetAddr;
|
||||
}
|
||||
}
|
||||
template<class T> class nsTArray;
|
||||
%}
|
||||
native NetAddr(mozilla::net::NetAddr);
|
||||
[ref] native nsNetAddrTArrayRef(nsTArray<mozilla::net::NetAddr>);
|
||||
interface nsINetAddr;
|
||||
|
||||
/**
|
||||
@ -22,7 +24,7 @@ interface nsINetAddr;
|
||||
* like an enumerator, allowing the caller to easily step through the
|
||||
* list of IP addresses.
|
||||
*/
|
||||
[scriptable, uuid(95ced6f3-44b4-4427-a149-c9a1e033d852)]
|
||||
[scriptable, uuid(f92228ae-c417-4188-a604-0830a95e7eb9)]
|
||||
interface nsIDNSRecord : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -45,6 +47,15 @@ interface nsIDNSRecord : nsISupports
|
||||
*/
|
||||
[noscript] NetAddr getNextAddr(in uint16_t aPort);
|
||||
|
||||
/**
|
||||
* this function copies the value of all working members of the RR
|
||||
* set into the output array.
|
||||
*
|
||||
* @param aAddressArray
|
||||
* The result set
|
||||
*/
|
||||
[noscript] void getAddresses(out nsNetAddrTArrayRef aAddressArray);
|
||||
|
||||
/**
|
||||
* this function returns the value of the next IP address as a
|
||||
* scriptable address and increments the internal address iterator.
|
||||
|
@ -70,10 +70,10 @@ nsHttpConnectionMgr::PrintDiagnosticsCB(const nsACString &key,
|
||||
ent->mIdleConns.Length());
|
||||
self->mLogData.AppendPrintf(" Half Opens Length = %u\n",
|
||||
ent->mHalfOpens.Length());
|
||||
self->mLogData.AppendPrintf(" Coalescing Key = %s\n",
|
||||
ent->mCoalescingKey.get());
|
||||
self->mLogData.AppendPrintf(" Coalescing Keys Length = %u\n",
|
||||
ent->mCoalescingKeys.Length());
|
||||
self->mLogData.AppendPrintf(" Spdy using = %d, tested = %d, preferred = %d\n",
|
||||
ent->mUsingSpdy, ent->mTestedSpdy, ent->mSpdyPreferred);
|
||||
ent->mUsingSpdy, ent->mTestedSpdy, ent->mInPreferredHash);
|
||||
self->mLogData.AppendPrintf(" pipelinestate = %d penalty = %d\n",
|
||||
ent->mPipelineState, ent->mPipeliningPenalty);
|
||||
for (i = 0; i < nsAHttpTransaction::CLASS_MAX; ++i) {
|
||||
@ -96,7 +96,10 @@ nsHttpConnectionMgr::PrintDiagnosticsCB(const nsACString &key,
|
||||
self->mLogData.AppendPrintf(" :: Pending Transaction #%u\n", i);
|
||||
ent->mPendingQ[i]->PrintDiagnostics(self->mLogData);
|
||||
}
|
||||
|
||||
for (i = 0; i < ent->mCoalescingKeys.Length(); ++i) {
|
||||
self->mLogData.AppendPrintf(" :: Coalescing Key #%u %s\n",
|
||||
i, ent->mCoalescingKeys[i].get());
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/net/DashboardTypes.h"
|
||||
#include "NullHttpTransaction.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsISocketTransportService.h"
|
||||
#include <algorithm>
|
||||
@ -569,6 +570,46 @@ nsHttpConnectionMgr::ClearConnectionHistory()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsHttpConnectionMgr::nsConnectionEntry *
|
||||
nsHttpConnectionMgr::LookupPreferredHash(nsHttpConnectionMgr::nsConnectionEntry *ent)
|
||||
{
|
||||
nsConnectionEntry *preferred = nullptr;
|
||||
uint32_t len = ent->mCoalescingKeys.Length();
|
||||
for (uint32_t i = 0; !preferred && (i < len); ++i) {
|
||||
preferred = mSpdyPreferredHash.Get(ent->mCoalescingKeys[i]);
|
||||
}
|
||||
return preferred;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::StorePreferredHash(nsHttpConnectionMgr::nsConnectionEntry *ent)
|
||||
{
|
||||
if (ent->mCoalescingKeys.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ent->mInPreferredHash = true;
|
||||
uint32_t len = ent->mCoalescingKeys.Length();
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
mSpdyPreferredHash.Put(ent->mCoalescingKeys[i], ent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::RemovePreferredHash(nsHttpConnectionMgr::nsConnectionEntry *ent)
|
||||
{
|
||||
if (!ent->mInPreferredHash || ent->mCoalescingKeys.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ent->mInPreferredHash = false;
|
||||
uint32_t len = ent->mCoalescingKeys.Length();
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
mSpdyPreferredHash.Remove(ent->mCoalescingKeys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Given a nsHttpConnectionInfo find the connection entry object that
|
||||
// contains either the nshttpconnection or nshttptransaction parameter.
|
||||
// Normally this is done by the hashkey lookup of connectioninfo,
|
||||
@ -587,13 +628,13 @@ nsHttpConnectionMgr::LookupConnectionEntry(nsHttpConnectionInfo *ci,
|
||||
|
||||
// If there is no sign of coalescing (or it is disabled) then just
|
||||
// return the primary hash lookup
|
||||
if (!ent || !ent->mUsingSpdy || ent->mCoalescingKey.IsEmpty())
|
||||
if (!ent || !ent->mUsingSpdy || ent->mCoalescingKeys.IsEmpty())
|
||||
return ent;
|
||||
|
||||
// If there is no preferred coalescing entry for this host (or the
|
||||
// preferred entry is the one that matched the mCT hash lookup) then
|
||||
// there is only option
|
||||
nsConnectionEntry *preferred = mSpdyPreferredHash.Get(ent->mCoalescingKey);
|
||||
nsConnectionEntry *preferred = LookupPreferredHash(ent);
|
||||
if (!preferred || (preferred == ent))
|
||||
return ent;
|
||||
|
||||
@ -674,18 +715,15 @@ nsHttpConnectionMgr::ReportSpdyConnection(nsHttpConnection *conn,
|
||||
// lookup. Filtering on that has to be done at the time of use
|
||||
// rather than the time of registration (i.e. now).
|
||||
nsConnectionEntry *joinedConnection;
|
||||
nsConnectionEntry *preferred =
|
||||
mSpdyPreferredHash.Get(ent->mCoalescingKey);
|
||||
nsConnectionEntry *preferred = LookupPreferredHash(ent);
|
||||
|
||||
LOG(("ReportSpdyConnection %s %s ent=%p preferred=%p\n",
|
||||
ent->mConnInfo->Host(), ent->mCoalescingKey.get(),
|
||||
ent, preferred));
|
||||
LOG(("ReportSpdyConnection %p,%s prefers %p,%s\n",
|
||||
ent, ent->mConnInfo->Host(), preferred,
|
||||
preferred ? preferred->mConnInfo->Host() : ""));
|
||||
|
||||
if (!preferred) {
|
||||
if (!ent->mCoalescingKey.IsEmpty()) {
|
||||
mSpdyPreferredHash.Put(ent->mCoalescingKey, ent);
|
||||
ent->mSpdyPreferred = true;
|
||||
}
|
||||
// this becomes the preferred entry
|
||||
StorePreferredHash(ent);
|
||||
} else if ((preferred != ent) &&
|
||||
(joinedConnection = GetSpdyPreferredEnt(ent)) &&
|
||||
(joinedConnection != ent)) {
|
||||
@ -775,11 +813,11 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry)
|
||||
{
|
||||
if (!gHttpHandler->IsSpdyEnabled() ||
|
||||
!gHttpHandler->CoalesceSpdy() ||
|
||||
aOriginalEntry->mCoalescingKey.IsEmpty())
|
||||
aOriginalEntry->mCoalescingKeys.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsConnectionEntry *preferred =
|
||||
mSpdyPreferredHash.Get(aOriginalEntry->mCoalescingKey);
|
||||
nsConnectionEntry *preferred = LookupPreferredHash(aOriginalEntry);
|
||||
|
||||
// if there is no redirection no cert validation is required
|
||||
if (preferred == aOriginalEntry)
|
||||
@ -807,8 +845,7 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry)
|
||||
if (!activeSpdy) {
|
||||
// remove the preferred status of this entry if it cannot be
|
||||
// used for pooling.
|
||||
preferred->mSpdyPreferred = false;
|
||||
RemoveSpdyPreferredEnt(preferred->mCoalescingKey);
|
||||
RemovePreferredHash(preferred);
|
||||
LOG(("nsHttpConnectionMgr::GetSpdyPreferredConnection "
|
||||
"preferred host mapping %s to %s removed due to inactivity.\n",
|
||||
aOriginalEntry->mConnInfo->Host(),
|
||||
@ -872,15 +909,6 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry)
|
||||
return preferred;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::RemoveSpdyPreferredEnt(nsACString &aHashKey)
|
||||
{
|
||||
if (aHashKey.IsEmpty())
|
||||
return;
|
||||
|
||||
mSpdyPreferredHash.Remove(aHashKey);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// enumeration callbacks
|
||||
|
||||
@ -2749,8 +2777,7 @@ nsHttpConnectionMgr::OnMsgUpdateParam(int32_t, void *param)
|
||||
nsHttpConnectionMgr::nsConnectionEntry::~nsConnectionEntry()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsConnectionEntry);
|
||||
if (mSpdyPreferred)
|
||||
gHttpHandler->ConnMgr()->RemoveSpdyPreferredEnt(mCoalescingKey);
|
||||
gHttpHandler->ConnMgr()->RemovePreferredHash(this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3469,32 +3496,36 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans,
|
||||
// just completed. We can't do coalescing if using a proxy because the
|
||||
// ip addresses are not available to the client.
|
||||
|
||||
if (status == NS_NET_STATUS_CONNECTED_TO &&
|
||||
if (status == NS_NET_STATUS_CONNECTING_TO &&
|
||||
gHttpHandler->IsSpdyEnabled() &&
|
||||
gHttpHandler->CoalesceSpdy() &&
|
||||
mEnt && mEnt->mConnInfo && mEnt->mConnInfo->EndToEndSSL() &&
|
||||
!mEnt->mConnInfo->UsingProxy() &&
|
||||
mEnt->mCoalescingKey.IsEmpty()) {
|
||||
mEnt->mCoalescingKeys.IsEmpty()) {
|
||||
|
||||
NetAddr addr;
|
||||
nsresult rv = mSocketTransport->GetPeerAddr(&addr);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mEnt->mCoalescingKey.SetCapacity(kIPv6CStrBufSize + 26);
|
||||
NetAddrToString(&addr, mEnt->mCoalescingKey.BeginWriting(), kIPv6CStrBufSize);
|
||||
mEnt->mCoalescingKey.SetLength(
|
||||
strlen(mEnt->mCoalescingKey.BeginReading()));
|
||||
|
||||
if (mEnt->mConnInfo->GetAnonymous())
|
||||
mEnt->mCoalescingKey.AppendLiteral("~A:");
|
||||
else
|
||||
mEnt->mCoalescingKey.AppendLiteral("~.:");
|
||||
mEnt->mCoalescingKey.AppendInt(mEnt->mConnInfo->Port());
|
||||
|
||||
LOG(("nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus "
|
||||
"STATUS_CONNECTED_TO Established New Coalescing Key for host "
|
||||
"%s [%s]", mEnt->mConnInfo->Host(),
|
||||
mEnt->mCoalescingKey.get()));
|
||||
nsCOMPtr<nsIDNSRecord> dnsRecord(do_GetInterface(mSocketTransport));
|
||||
nsTArray<NetAddr> addressSet;
|
||||
nsresult rv = NS_ERROR_NOT_AVAILABLE;
|
||||
if (dnsRecord) {
|
||||
rv = dnsRecord->GetAddresses(addressSet);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !addressSet.IsEmpty()) {
|
||||
for (uint32_t i = 0; i < addressSet.Length(); ++i) {
|
||||
nsCString *newKey = mEnt->mCoalescingKeys.AppendElement(nsCString());
|
||||
newKey->SetCapacity(kIPv6CStrBufSize + 26);
|
||||
NetAddrToString(&addressSet[i], newKey->BeginWriting(), kIPv6CStrBufSize);
|
||||
newKey->SetLength(strlen(newKey->BeginReading()));
|
||||
if (mEnt->mConnInfo->GetAnonymous()) {
|
||||
newKey->AppendLiteral("~A:");
|
||||
} else {
|
||||
newKey->AppendLiteral("~.:");
|
||||
}
|
||||
newKey->AppendInt(mEnt->mConnInfo->Port());
|
||||
LOG(("nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus "
|
||||
"STATUS_CONNECTING_TO Established New Coalescing Key # %d for host "
|
||||
"%s [%s]", i, mEnt->mConnInfo->Host(), newKey->get()));
|
||||
}
|
||||
gHttpHandler->ConnMgr()->ProcessSpdyPendingQ(mEnt);
|
||||
}
|
||||
}
|
||||
@ -3585,7 +3616,7 @@ nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci)
|
||||
, mSpdyCWND(0)
|
||||
, mUsingSpdy(false)
|
||||
, mTestedSpdy(false)
|
||||
, mSpdyPreferred(false)
|
||||
, mInPreferredHash(false)
|
||||
, mPreferIPv4(false)
|
||||
, mPreferIPv6(false)
|
||||
{
|
||||
|
@ -364,7 +364,7 @@ private:
|
||||
// mSpdyPreferred. The mapping is maintained in the connection mananger
|
||||
// mSpdyPreferred hash.
|
||||
//
|
||||
nsCString mCoalescingKey;
|
||||
nsTArray<nsCString> mCoalescingKeys;
|
||||
|
||||
// The value of a recevied SPDY settings type 5 previously received
|
||||
// for this connection entry and the time it was set.
|
||||
@ -382,7 +382,7 @@ private:
|
||||
// minimized so that we can multiplex on a single spdy connection.
|
||||
bool mTestedSpdy;
|
||||
|
||||
bool mSpdyPreferred;
|
||||
bool mInPreferredHash;
|
||||
|
||||
// Flags to remember our happy-eyeballs decision.
|
||||
// Reset only by Ctrl-F5 reload.
|
||||
@ -589,7 +589,9 @@ private:
|
||||
|
||||
// Manage the preferred spdy connection entry for this address
|
||||
nsConnectionEntry *GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry);
|
||||
void RemoveSpdyPreferredEnt(nsACString &aDottedDecimal);
|
||||
nsConnectionEntry *LookupPreferredHash(nsConnectionEntry *ent);
|
||||
void StorePreferredHash(nsConnectionEntry *ent);
|
||||
void RemovePreferredHash(nsConnectionEntry *ent);
|
||||
nsHttpConnection *GetSpdyPreferredConn(nsConnectionEntry *ent);
|
||||
nsDataHashtable<nsCStringHashKey, nsConnectionEntry *> mSpdyPreferredHash;
|
||||
nsConnectionEntry *LookupConnectionEntry(nsHttpConnectionInfo *ci,
|
||||
|
Loading…
x
Reference in New Issue
Block a user