mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1705065
- ConnectionEntry should hold reference to DnsAndConnectSocket-s r=necko-reviewers,valentin
- Remove reference to ConnecionEntry from DnsAndConnectSocket. If ConnecionEntry is needed it is obtain from nsHttpConnectionMgr. It is only needed when a final connection is being set up. - Put all functions that add and remove a DnsAndConnectSocket from the list in ConnecionEntry into one place (InsertIntoDnsAndConnectSockets, RemoveDnsAndConnectSocket, CloseAllDnsAndConnectSockets). Only these connection should remove/add DnsAndConnectSocket to ensure proper counting. - Access DnsAndConnectSocket mostly from ConnecionEntry (e.g. refactor TryClaimingDnsAndConnectSocket). - Remove some dead code (e.g. IsInDnsAndConnectSockets) - Move some function into ConnecionEntry for a better code factoring (CreateDnsAndConnectSocket, MaybeProcessCoalescingKeys) - Remove code that sets DNS flags in TransportSetup::SetupStreams because nsISocketTransport is not responsible for DNS lookups any more. Differential Revision: https://phabricator.services.mozilla.com/D113119
This commit is contained in:
parent
1679badc68
commit
34dc7af64a
@ -63,26 +63,18 @@ uint32_t ConnectionEntry::UnconnectedDnsAndConnectSockets() const {
|
||||
return unconnectedDnsAndConnectSockets;
|
||||
}
|
||||
|
||||
bool ConnectionEntry::RemoveDnsAndConnectSocket(
|
||||
DnsAndConnectSocket* dnsAndSock) {
|
||||
bool isPrimary = false;
|
||||
// A failure to create the transport object at all
|
||||
// will result in it not being present in the DnsAndConnectSockets table.
|
||||
// That's expected.
|
||||
void ConnectionEntry::InsertIntoDnsAndConnectSockets(
|
||||
DnsAndConnectSocket* sock) {
|
||||
mDnsAndConnectSockets.AppendElement(sock);
|
||||
gHttpHandler->ConnMgr()->IncreaseNumDnsAndConnectSockets();
|
||||
}
|
||||
|
||||
void ConnectionEntry::RemoveDnsAndConnectSocket(DnsAndConnectSocket* dnsAndSock,
|
||||
bool abandon) {
|
||||
if (abandon) {
|
||||
dnsAndSock->Abandon();
|
||||
}
|
||||
if (mDnsAndConnectSockets.RemoveElement(dnsAndSock)) {
|
||||
isPrimary = true;
|
||||
if (dnsAndSock->IsSpeculative()) {
|
||||
Telemetry::AutoCounter<Telemetry::HTTPCONNMGR_UNUSED_SPECULATIVE_CONN>
|
||||
unusedSpeculativeConn;
|
||||
++unusedSpeculativeConn;
|
||||
|
||||
if (dnsAndSock->IsFromPredictor()) {
|
||||
Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PRECONNECTS_UNUSED>
|
||||
totalPreconnectsUnused;
|
||||
++totalPreconnectsUnused;
|
||||
}
|
||||
}
|
||||
|
||||
gHttpHandler->ConnMgr()->DecreaseNumDnsAndConnectSockets();
|
||||
}
|
||||
|
||||
@ -97,8 +89,20 @@ bool ConnectionEntry::RemoveDnsAndConnectSocket(
|
||||
" failed to process pending queue\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isPrimary;
|
||||
void ConnectionEntry::CloseAllDnsAndConnectSockets() {
|
||||
for (const auto& dnsAndSock : mDnsAndConnectSockets) {
|
||||
dnsAndSock->Abandon();
|
||||
gHttpHandler->ConnMgr()->DecreaseNumDnsAndConnectSockets();
|
||||
}
|
||||
mDnsAndConnectSockets.Clear();
|
||||
nsresult rv = gHttpHandler->ConnMgr()->ProcessPendingQ(mConnInfo);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(
|
||||
("ConnectionEntry::CloseAllDnsAndConnectSockets\n"
|
||||
" failed to process pending queue\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionEntry::DisallowHttp2() {
|
||||
@ -519,25 +523,16 @@ void ConnectionEntry::MakeAllDontReuseExcept(HttpConnectionBase* conn) {
|
||||
|
||||
// Cancel any other pending connections - their associated transactions
|
||||
// are in the pending queue and will be dispatched onto this new connection
|
||||
for (int32_t index = DnsAndConnectSocketsLength() - 1; index >= 0; --index) {
|
||||
RefPtr<DnsAndConnectSocket> dnsAndSock = mDnsAndConnectSockets[index];
|
||||
LOG(
|
||||
("ConnectionEntry::MakeAllDontReuseExcept forcing DnsAndConnectSocket "
|
||||
"abandon %p\n",
|
||||
dnsAndSock.get()));
|
||||
mDnsAndConnectSockets[index]->Abandon();
|
||||
}
|
||||
CloseAllDnsAndConnectSockets();
|
||||
}
|
||||
|
||||
bool ConnectionEntry::FindConnToClaim(
|
||||
PendingTransactionInfo* pendingTransInfo) {
|
||||
nsHttpTransaction* trans = pendingTransInfo->Transaction();
|
||||
|
||||
uint32_t dnsAndSockLength = DnsAndConnectSocketsLength();
|
||||
for (uint32_t i = 0; i < dnsAndSockLength; i++) {
|
||||
auto* dnsAndSock = mDnsAndConnectSockets[i];
|
||||
if (dnsAndSock->AcceptsTransaction(trans) &&
|
||||
pendingTransInfo->TryClaimingDnsAndConnectSocket(dnsAndSock)) {
|
||||
for (const auto& dnsAndSock : mDnsAndConnectSockets) {
|
||||
if (dnsAndSock->AcceptsTransaction(trans) && dnsAndSock->Claim()) {
|
||||
pendingTransInfo->RememberDnsAndConnectSocket(dnsAndSock);
|
||||
// We've found a speculative connection or a connection that
|
||||
// is free to be used in the DnsAndConnectSockets list.
|
||||
// A free to be used connection is a connection that was
|
||||
@ -722,10 +717,7 @@ uint32_t ConnectionEntry::TimeoutTick() {
|
||||
TimeStamp currentTime = TimeStamp::Now();
|
||||
double maxConnectTime_ms = gHttpHandler->ConnectTimeout();
|
||||
|
||||
for (uint32_t index = mDnsAndConnectSockets.Length(); index > 0;) {
|
||||
index--;
|
||||
|
||||
DnsAndConnectSocket* dnsAndSock = mDnsAndConnectSockets[index];
|
||||
for (const auto& dnsAndSock : Reversed(mDnsAndConnectSockets)) {
|
||||
double delta = dnsAndSock->Duration(currentTime);
|
||||
// If the socket has timed out, close it so the waiting
|
||||
// transaction will get the proper signal.
|
||||
@ -740,7 +732,7 @@ uint32_t ConnectionEntry::TimeoutTick() {
|
||||
if (delta > maxConnectTime_ms + 5000) {
|
||||
LOG(("Abandon DnsAndConnectSocket to %s after %.2fms.\n",
|
||||
mConnInfo->HashKey().get(), delta));
|
||||
dnsAndSock->Abandon();
|
||||
RemoveDnsAndConnectSocket(dnsAndSock, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -770,22 +762,6 @@ void ConnectionEntry::MoveConnection(HttpConnectionBase* proxyConn,
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionEntry::InsertIntoDnsAndConnectSockets(
|
||||
DnsAndConnectSocket* sock) {
|
||||
mDnsAndConnectSockets.AppendElement(sock);
|
||||
gHttpHandler->ConnMgr()->IncreaseNumDnsAndConnectSockets();
|
||||
}
|
||||
|
||||
void ConnectionEntry::CloseAllDnsAndConnectSockets() {
|
||||
for (int32_t i = int32_t(DnsAndConnectSocketsLength()) - 1; i >= 0; i--) {
|
||||
mDnsAndConnectSockets[i]->Abandon();
|
||||
}
|
||||
}
|
||||
|
||||
bool ConnectionEntry::IsInDnsAndConnectSockets(DnsAndConnectSocket* sock) {
|
||||
return mDnsAndConnectSockets.Contains(sock);
|
||||
}
|
||||
|
||||
HttpRetParams ConnectionEntry::GetConnectionData() {
|
||||
HttpRetParams data;
|
||||
data.host = mConnInfo->Origin();
|
||||
@ -885,7 +861,11 @@ bool ConnectionEntry::RemoveTransFromPendingQ(nsHttpTransaction* aTrans) {
|
||||
}
|
||||
|
||||
// Abandon all DnsAndConnectSockets belonging to the given transaction.
|
||||
pendingTransInfo->AbandonDnsAndConnectSocketAndForgetActiveConn();
|
||||
nsWeakPtr tmp = pendingTransInfo->ForgetDnsAndConnectSocketAndActiveConn();
|
||||
RefPtr<DnsAndConnectSocket> dnsAndSock = do_QueryReferent(tmp);
|
||||
if (dnsAndSock) {
|
||||
RemoveDnsAndConnectSocket(dnsAndSock, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -911,5 +891,81 @@ void ConnectionEntry::MaybeUpdateEchConfig(nsHttpConnectionInfo* aConnInfo) {
|
||||
CloseIdleConnections();
|
||||
}
|
||||
|
||||
nsresult ConnectionEntry::CreateDnsAndConnectSocket(nsAHttpTransaction* trans, uint32_t caps,
|
||||
bool speculative, bool isFromPredictor, bool urgentStart, bool allow1918,
|
||||
PendingTransactionInfo* pendingTransInfo) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
MOZ_ASSERT((speculative && !pendingTransInfo) ||
|
||||
(!speculative && pendingTransInfo));
|
||||
|
||||
RefPtr<DnsAndConnectSocket> sock = new DnsAndConnectSocket(
|
||||
mConnInfo, trans, caps, speculative, isFromPredictor, urgentStart);
|
||||
|
||||
if (speculative) {
|
||||
sock->SetAllow1918(allow1918);
|
||||
}
|
||||
|
||||
nsresult rv = sock->Init(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
InsertIntoDnsAndConnectSockets(sock);
|
||||
|
||||
if (pendingTransInfo && sock->Claim()) {
|
||||
pendingTransInfo->RememberDnsAndConnectSocket(sock);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool ConnectionEntry::MaybeProcessCoalescingKeys(nsIDNSAddrRecord* dnsRecord) {
|
||||
if (!mConnInfo || !AllowHttp2() || !mCoalescingKeys.IsEmpty() || !dnsRecord) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<NetAddr> addressSet;
|
||||
nsresult rv = dnsRecord->GetAddresses(addressSet);
|
||||
|
||||
if (NS_FAILED(rv) || addressSet.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < addressSet.Length(); ++i) {
|
||||
if ((addressSet[i].raw.family == AF_INET &&
|
||||
addressSet[i].inet.ip == 0) ||
|
||||
(addressSet[i].raw.family == AF_INET6 &&
|
||||
addressSet[i].inet6.ip.u64[0] == 0 &&
|
||||
addressSet[i].inet6.ip.u64[1] == 0)) {
|
||||
// Bug 1680249 - Don't create the coalescing key if the ip address is
|
||||
// `0.0.0.0` or `::`.
|
||||
LOG((
|
||||
"ConnectionEntry::MaybeProcessCoalescingKeys skip creating "
|
||||
"Coalescing Key for host [%s]",
|
||||
mConnInfo->Origin()));
|
||||
continue;
|
||||
}
|
||||
nsCString* newKey = mCoalescingKeys.AppendElement(nsCString());
|
||||
newKey->SetLength(kIPv6CStrBufSize + 26);
|
||||
addressSet[i].ToStringBuffer(newKey->BeginWriting(), kIPv6CStrBufSize);
|
||||
newKey->SetLength(strlen(newKey->BeginReading()));
|
||||
if (mConnInfo->GetAnonymous()) {
|
||||
newKey->AppendLiteral("~A:");
|
||||
} else {
|
||||
newKey->AppendLiteral("~.:");
|
||||
}
|
||||
newKey->AppendInt(mConnInfo->OriginPort());
|
||||
newKey->AppendLiteral("/[");
|
||||
nsAutoCString suffix;
|
||||
mConnInfo->GetOriginAttributes().CreateSuffix(suffix);
|
||||
newKey->Append(suffix);
|
||||
newKey->AppendLiteral("]viaDNS");
|
||||
LOG((
|
||||
"ConnectionEntry::MaybeProcessCoalescingKeys "
|
||||
"Established New Coalescing Key # %d for host "
|
||||
"%s [%s]",
|
||||
i, mConnInfo->Origin(), newKey->get()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -84,8 +84,8 @@ class ConnectionEntry {
|
||||
}
|
||||
|
||||
void InsertIntoDnsAndConnectSockets(DnsAndConnectSocket* sock);
|
||||
void RemoveDnsAndConnectSocket(DnsAndConnectSocket* dnsAndSock, bool abandon);
|
||||
void CloseAllDnsAndConnectSockets();
|
||||
bool IsInDnsAndConnectSockets(DnsAndConnectSocket* sock);
|
||||
|
||||
HttpRetParams GetConnectionData();
|
||||
void LogConnections();
|
||||
@ -101,6 +101,13 @@ class ConnectionEntry {
|
||||
// Remove a particular DnsAndConnectSocket from the mDnsAndConnectSocket array
|
||||
bool RemoveDnsAndConnectSocket(DnsAndConnectSocket*);
|
||||
|
||||
nsresult CreateDnsAndConnectSocket(nsAHttpTransaction* trans, uint32_t caps,
|
||||
bool speculative, bool isFromPredictor,
|
||||
bool urgentStart, bool allow1918,
|
||||
PendingTransactionInfo* pendingTransInfo);
|
||||
|
||||
bool MaybeProcessCoalescingKeys(nsIDNSAddrRecord* dnsRecord);
|
||||
|
||||
// Spdy sometimes resolves the address in the socket manager in order
|
||||
// to re-coalesce sharded HTTP hosts. The dotted decimal address is
|
||||
// combined with the Anonymous flag and OA from the connection information
|
||||
@ -190,7 +197,7 @@ class ConnectionEntry {
|
||||
nsTArray<RefPtr<nsHttpConnection>> mIdleConns; // idle persistent connections
|
||||
nsTArray<RefPtr<HttpConnectionBase>> mActiveConns; // active connections
|
||||
|
||||
nsTArray<DnsAndConnectSocket*>
|
||||
nsTArray<RefPtr<DnsAndConnectSocket>>
|
||||
mDnsAndConnectSockets; // dns resolution and half open connections
|
||||
|
||||
PendingTransactionQueue mPendingQ;
|
||||
|
@ -41,7 +41,7 @@ NS_INTERFACE_MAP_BEGIN(DnsAndConnectSocket)
|
||||
NS_INTERFACE_MAP_ENTRY_CONCRETE(DnsAndConnectSocket)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
DnsAndConnectSocket::DnsAndConnectSocket(ConnectionEntry* ent,
|
||||
DnsAndConnectSocket::DnsAndConnectSocket(nsHttpConnectionInfo* ci,
|
||||
nsAHttpTransaction* trans,
|
||||
uint32_t caps, bool speculative,
|
||||
bool isFromPredictor, bool urgentStart)
|
||||
@ -51,13 +51,13 @@ DnsAndConnectSocket::DnsAndConnectSocket(ConnectionEntry* ent,
|
||||
mSpeculative(speculative),
|
||||
mUrgentStart(urgentStart),
|
||||
mIsFromPredictor(isFromPredictor),
|
||||
mEnt(ent),
|
||||
mConnInfo(ci),
|
||||
mBackupTransport(true) {
|
||||
MOZ_ASSERT(ent && trans, "constructor with null arguments");
|
||||
MOZ_ASSERT(ci && trans, "constructor with null arguments");
|
||||
LOG(("Creating DnsAndConnectSocket [this=%p trans=%p ent=%s key=%s]\n", this,
|
||||
trans, ent->mConnInfo->Origin(), ent->mConnInfo->HashKey().get()));
|
||||
trans, mConnInfo->Origin(), mConnInfo->HashKey().get()));
|
||||
|
||||
mIsHttp3 = mEnt->mConnInfo->IsHttp3();
|
||||
mIsHttp3 = mConnInfo->IsHttp3();
|
||||
if (speculative) {
|
||||
Telemetry::AutoCounter<Telemetry::HTTPCONNMGR_TOTAL_SPECULATIVE_CONN>
|
||||
totalSpeculativeConn;
|
||||
@ -70,7 +70,7 @@ DnsAndConnectSocket::DnsAndConnectSocket(ConnectionEntry* ent,
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mEnt);
|
||||
MOZ_ASSERT(mConnInfo);
|
||||
}
|
||||
|
||||
DnsAndConnectSocket::~DnsAndConnectSocket() {
|
||||
@ -81,45 +81,46 @@ DnsAndConnectSocket::~DnsAndConnectSocket() {
|
||||
MOZ_ASSERT(!mPrimaryTransport.mWaitingForConnect);
|
||||
MOZ_ASSERT(!mBackupTransport.mWaitingForConnect);
|
||||
// Check in case something goes wrong that we decrease
|
||||
// the nsHttpConnectionMgr active connecttion number.
|
||||
// the nsHttpConnectionMgr active connection number.
|
||||
mPrimaryTransport.MaybeSetConnectingDone();
|
||||
mBackupTransport.MaybeSetConnectingDone();
|
||||
|
||||
if (mEnt) {
|
||||
bool inqueue = mEnt->RemoveDnsAndConnectSocket(this);
|
||||
LOG((
|
||||
"Destroying DnsAndConnectSocket was in the HalfOpenList=%d [this=%p]\n",
|
||||
inqueue, this));
|
||||
if (mSpeculative) {
|
||||
Telemetry::AutoCounter<Telemetry::HTTPCONNMGR_UNUSED_SPECULATIVE_CONN>
|
||||
unusedSpeculativeConn;
|
||||
++unusedSpeculativeConn;
|
||||
|
||||
if (mIsFromPredictor) {
|
||||
Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PRECONNECTS_UNUSED>
|
||||
totalPreconnectsUnused;
|
||||
++totalPreconnectsUnused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult DnsAndConnectSocket::Init() {
|
||||
nsresult DnsAndConnectSocket::Init(ConnectionEntry* ent) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
MOZ_ASSERT(mEnt);
|
||||
MOZ_ASSERT(mState == DnsAndSocketState::INIT);
|
||||
|
||||
if (mEnt->mConnInfo->GetRoutedHost().IsEmpty()) {
|
||||
mPrimaryTransport.mHost = mEnt->mConnInfo->GetOrigin();
|
||||
mBackupTransport.mHost = mEnt->mConnInfo->GetOrigin();
|
||||
if (mConnInfo->GetRoutedHost().IsEmpty()) {
|
||||
mPrimaryTransport.mHost = mConnInfo->GetOrigin();
|
||||
mBackupTransport.mHost = mConnInfo->GetOrigin();
|
||||
} else {
|
||||
mPrimaryTransport.mHost = mEnt->mConnInfo->GetRoutedHost();
|
||||
mBackupTransport.mHost = mEnt->mConnInfo->GetRoutedHost();
|
||||
mPrimaryTransport.mHost = mConnInfo->GetRoutedHost();
|
||||
mBackupTransport.mHost = mConnInfo->GetRoutedHost();
|
||||
}
|
||||
|
||||
CheckProxyConfig();
|
||||
|
||||
if (!mSkipDnsResolution) {
|
||||
nsresult rv = SetupDnsFlags();
|
||||
nsresult rv = SetupDnsFlags(ent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return SetupEvent(SetupEvents::INIT_EVENT);
|
||||
}
|
||||
|
||||
void DnsAndConnectSocket::CheckProxyConfig() {
|
||||
const nsHttpConnectionInfo* ci = mEnt->mConnInfo;
|
||||
|
||||
if (ci->ProxyInfo()) {
|
||||
nsCOMPtr<nsProxyInfo> proxyInfo = ci->ProxyInfo();
|
||||
if (nsCOMPtr<nsProxyInfo> proxyInfo = mConnInfo->ProxyInfo()) {
|
||||
nsAutoCString proxyType(proxyInfo->Type());
|
||||
|
||||
bool proxyTransparent = false;
|
||||
@ -151,7 +152,7 @@ void DnsAndConnectSocket::CheckProxyConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
nsresult DnsAndConnectSocket::SetupDnsFlags() {
|
||||
nsresult DnsAndConnectSocket::SetupDnsFlags(ConnectionEntry* ent) {
|
||||
LOG(("DnsAndConnectSocket::SetupDnsFlags [this=%p] ", this));
|
||||
|
||||
uint32_t dnsFlags = 0;
|
||||
@ -163,10 +164,10 @@ nsresult DnsAndConnectSocket::SetupDnsFlags() {
|
||||
dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4;
|
||||
} else if (mCaps & NS_HTTP_DISABLE_IPV6) {
|
||||
dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6;
|
||||
} else if (mEnt->PreferenceKnown()) {
|
||||
if (mEnt->mPreferIPv6) {
|
||||
} else if (ent->PreferenceKnown()) {
|
||||
if (ent->mPreferIPv6) {
|
||||
dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4;
|
||||
} else if (mEnt->mPreferIPv4) {
|
||||
} else if (ent->mPreferIPv4) {
|
||||
dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6;
|
||||
}
|
||||
mPrimaryTransport.mRetryWithDifferentIPFamily = true;
|
||||
@ -180,7 +181,7 @@ nsresult DnsAndConnectSocket::SetupDnsFlags() {
|
||||
disableIpv6ForBackup = true;
|
||||
}
|
||||
|
||||
if (mEnt->mConnInfo->HasIPHintAddress()) {
|
||||
if (ent->mConnInfo->HasIPHintAddress()) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDNSService> dns =
|
||||
do_GetService("@mozilla.org/network/dns-service;1", &rv);
|
||||
@ -194,7 +195,7 @@ nsresult DnsAndConnectSocket::SetupDnsFlags() {
|
||||
nsCOMPtr<nsIDNSRecord> record;
|
||||
rv = dns->ResolveNative(
|
||||
mPrimaryTransport.mHost, nsIDNSService::RESOLVE_OFFLINE,
|
||||
mEnt->mConnInfo->GetOriginAttributes(), getter_AddRefs(record));
|
||||
mConnInfo->GetOriginAttributes(), getter_AddRefs(record));
|
||||
if (NS_FAILED(rv) || !record) {
|
||||
LOG(("Setting Socket to use IP hint address"));
|
||||
dnsFlags |= nsIDNSService::RESOLVE_IP_HINT;
|
||||
@ -230,27 +231,29 @@ nsresult DnsAndConnectSocket::SetupDnsFlags() {
|
||||
|
||||
nsresult DnsAndConnectSocket::SetupEvent(SetupEvents event) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
LOG(("DnsAndConnectSocket::SetupEvent state=%d event=%d", mState, event));
|
||||
LOG(("DnsAndConnectSocket::SetupEvent state=%d event=%d this=%p", mState,
|
||||
event, this));
|
||||
nsresult rv = NS_OK;
|
||||
switch (event) {
|
||||
case SetupEvents::INIT_EVENT: {
|
||||
case SetupEvents::INIT_EVENT:
|
||||
MOZ_ASSERT(mState == DnsAndSocketState::INIT);
|
||||
nsresult rv = mPrimaryTransport.Init(this);
|
||||
rv = mPrimaryTransport.Init(this);
|
||||
if (NS_FAILED(rv)) {
|
||||
mState = DnsAndSocketState::DONE;
|
||||
return rv;
|
||||
}
|
||||
if (mPrimaryTransport.FirstResolving()) {
|
||||
} else if (mPrimaryTransport.FirstResolving()) {
|
||||
mState = DnsAndSocketState::RESOLVING;
|
||||
} else if (!mIsHttp3 && mPrimaryTransport.ConnectingOrRetry()) {
|
||||
mState = DnsAndSocketState::CONNECTING;
|
||||
SetupBackupTimer();
|
||||
} else {
|
||||
MOZ_ASSERT(false);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
mState = DnsAndSocketState::DONE;
|
||||
Abandon();
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
case SetupEvents::RESOLVED_PRIMARY_EVENT:
|
||||
// This eventt may be posted multiple times if a DNS lookup is
|
||||
// This event may be posted multiple times if a DNS lookup is
|
||||
// retriggered, e.g with different parameter.
|
||||
if (!mIsHttp3 && (mState == DnsAndSocketState::RESOLVING)) {
|
||||
mState = DnsAndSocketState::CONNECTING;
|
||||
@ -284,11 +287,19 @@ nsresult DnsAndConnectSocket::SetupEvent(SetupEvents event) {
|
||||
}
|
||||
LOG(("DnsAndConnectSocket::SetupEvent state=%d", mState));
|
||||
|
||||
if (mState == DnsAndSocketState::DONE) {
|
||||
RefPtr<DnsAndConnectSocket> self(this);
|
||||
RefPtr<ConnectionEntry> ent =
|
||||
gHttpHandler->ConnMgr()->FindConnectionEntry(mConnInfo);
|
||||
if (ent) {
|
||||
ent->RemoveDnsAndConnectSocket(this, false);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void DnsAndConnectSocket::SetupBackupTimer() {
|
||||
MOZ_ASSERT(mEnt);
|
||||
uint16_t timeout = gHttpHandler->GetIdleSynTimeout();
|
||||
MOZ_ASSERT(!mSynTimer, "timer already initd");
|
||||
|
||||
@ -327,14 +338,12 @@ void DnsAndConnectSocket::CancelBackupTimer() {
|
||||
|
||||
void DnsAndConnectSocket::Abandon() {
|
||||
LOG(("DnsAndConnectSocket::Abandon [this=%p ent=%s] %p %p %p %p", this,
|
||||
mEnt->mConnInfo->Origin(), mPrimaryTransport.mSocketTransport.get(),
|
||||
mConnInfo->Origin(), mPrimaryTransport.mSocketTransport.get(),
|
||||
mBackupTransport.mSocketTransport.get(),
|
||||
mPrimaryTransport.mStreamOut.get(), mBackupTransport.mStreamOut.get()));
|
||||
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
RefPtr<DnsAndConnectSocket> deleteProtector(this);
|
||||
|
||||
// Tell socket (and backup socket) to forget the half open socket.
|
||||
mPrimaryTransport.Abandon();
|
||||
mBackupTransport.Abandon();
|
||||
@ -343,13 +352,6 @@ void DnsAndConnectSocket::Abandon() {
|
||||
CancelBackupTimer();
|
||||
|
||||
mState = DnsAndSocketState::DONE;
|
||||
|
||||
// Remove the half open from the connection entry.
|
||||
if (mEnt) {
|
||||
mEnt->mDoNotDestroy = false;
|
||||
mEnt->RemoveDnsAndConnectSocket(this);
|
||||
}
|
||||
mEnt = nullptr;
|
||||
}
|
||||
|
||||
double DnsAndConnectSocket::Duration(TimeStamp epoch) {
|
||||
@ -368,7 +370,6 @@ DnsAndConnectSocket::Notify(nsITimer* timer) {
|
||||
MOZ_ASSERT(!mBackupTransport.mDNSRequest);
|
||||
MOZ_ASSERT(!mBackupTransport.mSocketTransport);
|
||||
MOZ_ASSERT(mSynTimer);
|
||||
MOZ_ASSERT(mEnt);
|
||||
|
||||
DebugOnly<nsresult> rv = SetupEvent(BACKUP_TIMER_FIRED_EVENT);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
@ -414,7 +415,7 @@ DnsAndConnectSocket::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
|
||||
// remember if it was primary because TransportSetups will delete the ref to
|
||||
// the DNS request and check cannot be performed later.
|
||||
bool isPrimary = IsPrimary(request);
|
||||
if (IsPrimary(request)) {
|
||||
if (isPrimary) {
|
||||
rv = mPrimaryTransport.OnLookupComplete(this, rec, status);
|
||||
if ((!mIsHttp3 && mPrimaryTransport.ConnectingOrRetry()) ||
|
||||
(mIsHttp3 && mPrimaryTransport.Resolved())) {
|
||||
@ -425,7 +426,21 @@ DnsAndConnectSocket::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || mIsHttp3) {
|
||||
// Before calling SetupConn we need to hold reference to this, i.e. a
|
||||
// delete protector, because the corresponding ConnectionEntry may be
|
||||
// abandoned and that will abandon this DnsAndConnectSocket.
|
||||
SetupConn(isPrimary, rv);
|
||||
// During a connection dispatch that will happen in SetupConn,
|
||||
// a ConnectionEntry may be abandon and that will abandon this
|
||||
// DnsAndConnectSocket. In that case mState will already be
|
||||
// DnsAndSocketState::DONE and we do not need to set it again.
|
||||
if (mState != DnsAndSocketState::DONE) {
|
||||
if (isPrimary) {
|
||||
SetupEvent(SetupEvents::PRIMARY_DONE_EVENT);
|
||||
} else {
|
||||
SetupEvent(SetupEvents::BACKUP_DONE_EVENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -437,12 +452,11 @@ DnsAndConnectSocket::OnOutputStreamReady(nsIAsyncOutputStream* out) {
|
||||
MOZ_ASSERT(mPrimaryTransport.mSocketTransport ||
|
||||
mBackupTransport.mSocketTransport);
|
||||
MOZ_ASSERT(IsPrimary(out) || IsBackup(out), "stream mismatch");
|
||||
MOZ_ASSERT(mEnt);
|
||||
|
||||
RefPtr<DnsAndConnectSocket> deleteProtector(this);
|
||||
|
||||
LOG(("DnsAndConnectSocket::OnOutputStreamReady [this=%p ent=%s %s]\n", this,
|
||||
mEnt->mConnInfo->Origin(), IsPrimary(out) ? "primary" : "backup"));
|
||||
mConnInfo->Origin(), IsPrimary(out) ? "primary" : "backup"));
|
||||
|
||||
// Remember if it was primary or backup reuest.
|
||||
bool isPrimary = IsPrimary(out);
|
||||
@ -478,27 +492,43 @@ DnsAndConnectSocket::OnOutputStreamReady(nsIAsyncOutputStream* out) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
mEnt->mDoNotDestroy = true;
|
||||
|
||||
// Before calling SetupConn we need to hold a reference to this, i.e. a
|
||||
// delete protector, because the corresponding ConnectionEntry may be
|
||||
// abandoned and that will abandon this DnsAndConnectSocket.
|
||||
rv = SetupConn(isPrimary, rv);
|
||||
if (mEnt) {
|
||||
mEnt->mDoNotDestroy = false;
|
||||
if (mState != DnsAndSocketState::DONE) {
|
||||
// During a connection dispatch that will happen in SetupConn,
|
||||
// a ConnectionEntry may be abandon and that will abandon this
|
||||
// DnsAndConnectSocket. In that case mState will already be
|
||||
// DnsAndSocketState::DONE and we do not need to set it again.
|
||||
if (isPrimary) {
|
||||
SetupEvent(SetupEvents::PRIMARY_DONE_EVENT);
|
||||
} else {
|
||||
SetupEvent(SetupEvents::BACKUP_DONE_EVENT);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult DnsAndConnectSocket::SetupConn(bool isPrimary, nsresult status) {
|
||||
// assign the new socket to the http connection
|
||||
|
||||
RefPtr<ConnectionEntry> ent =
|
||||
gHttpHandler->ConnMgr()->FindConnectionEntry(mConnInfo);
|
||||
MOZ_DIAGNOSTIC_ASSERT(ent);
|
||||
if (!ent) {
|
||||
Abandon();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<HttpConnectionBase> conn;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (isPrimary) {
|
||||
SetupEvent(SetupEvents::PRIMARY_DONE_EVENT);
|
||||
rv = mPrimaryTransport.SetupConn(mTransaction, mEnt, status, mCaps,
|
||||
rv = mPrimaryTransport.SetupConn(mTransaction, ent, status, mCaps,
|
||||
getter_AddRefs(conn));
|
||||
} else {
|
||||
SetupEvent(SetupEvents::BACKUP_DONE_EVENT);
|
||||
rv = mBackupTransport.SetupConn(mTransaction, mEnt, status, mCaps,
|
||||
rv = mBackupTransport.SetupConn(mTransaction, ent, status, mCaps,
|
||||
getter_AddRefs(conn));
|
||||
}
|
||||
|
||||
@ -514,12 +544,12 @@ nsresult DnsAndConnectSocket::SetupConn(bool isPrimary, nsresult status) {
|
||||
if (nsHttpTransaction* trans = mTransaction->QueryHttpTransaction()) {
|
||||
if (mIsHttp3) {
|
||||
trans->DisableHttp3();
|
||||
gHttpHandler->ExcludeHttp3(mEnt->mConnInfo);
|
||||
gHttpHandler->ExcludeHttp3(mConnInfo);
|
||||
}
|
||||
// The transaction's connection info is changed after DisableHttp3(), so
|
||||
// this is the only point we can remove this transaction from its conn
|
||||
// entry.
|
||||
mEnt->RemoveTransFromPendingQ(trans);
|
||||
ent->RemoveTransFromPendingQ(trans);
|
||||
}
|
||||
mTransaction->Close(rv);
|
||||
|
||||
@ -532,11 +562,11 @@ nsresult DnsAndConnectSocket::SetupConn(bool isPrimary, nsresult status) {
|
||||
|
||||
// if this is still in the pending list, remove it and dispatch it
|
||||
RefPtr<PendingTransactionInfo> pendingTransInfo =
|
||||
gHttpHandler->ConnMgr()->FindTransactionHelper(true, mEnt, mTransaction);
|
||||
gHttpHandler->ConnMgr()->FindTransactionHelper(true, ent, mTransaction);
|
||||
if (pendingTransInfo) {
|
||||
MOZ_ASSERT(!mSpeculative, "Speculative Half Open found mTransaction");
|
||||
|
||||
mEnt->InsertIntoActiveConns(conn);
|
||||
ent->InsertIntoActiveConns(conn);
|
||||
if (mIsHttp3) {
|
||||
// Each connection must have a ConnectionHandle wrapper.
|
||||
// In case of Http < 2 the a ConnectionHandle is created for each
|
||||
@ -555,7 +585,7 @@ nsresult DnsAndConnectSocket::SetupConn(bool isPrimary, nsresult status) {
|
||||
pendingTransInfo->Transaction()->SetConnection(handle);
|
||||
}
|
||||
rv = gHttpHandler->ConnMgr()->DispatchTransaction(
|
||||
mEnt, pendingTransInfo->Transaction(), conn);
|
||||
ent, pendingTransInfo->Transaction(), conn);
|
||||
} else {
|
||||
// this transaction was dispatched off the pending q before all the
|
||||
// sockets established themselves.
|
||||
@ -576,8 +606,8 @@ nsresult DnsAndConnectSocket::SetupConn(bool isPrimary, nsresult status) {
|
||||
// Http3 cannot be dispatched using OnMsgReclaimConnection (see below),
|
||||
// therefore we need to use a Nulltransaction.
|
||||
if (!connTCP ||
|
||||
(mEnt->mConnInfo->FirstHopSSL() && !mEnt->UrgentStartQueueLength() &&
|
||||
!mEnt->PendingQueueLength() && !mEnt->mConnInfo->UsingConnect())) {
|
||||
(ent->mConnInfo->FirstHopSSL() && !ent->UrgentStartQueueLength() &&
|
||||
!ent->PendingQueueLength() && !ent->mConnInfo->UsingConnect())) {
|
||||
LOG(
|
||||
("DnsAndConnectSocket::SetupConn null transaction will "
|
||||
"be used to finish SSL handshake on conn %p\n",
|
||||
@ -589,11 +619,11 @@ nsresult DnsAndConnectSocket::SetupConn(bool isPrimary, nsresult status) {
|
||||
mDispatchedMTransaction = true;
|
||||
trans = mTransaction;
|
||||
} else {
|
||||
trans = new NullHttpTransaction(mEnt->mConnInfo, callbacks, mCaps);
|
||||
trans = new NullHttpTransaction(mConnInfo, callbacks, mCaps);
|
||||
}
|
||||
|
||||
mEnt->InsertIntoActiveConns(conn);
|
||||
rv = gHttpHandler->ConnMgr()->DispatchAbstractTransaction(mEnt, trans,
|
||||
ent->InsertIntoActiveConns(conn);
|
||||
rv = gHttpHandler->ConnMgr()->DispatchAbstractTransaction(ent, trans,
|
||||
mCaps, conn, 0);
|
||||
} else {
|
||||
// otherwise just put this in the persistent connection pool
|
||||
@ -610,24 +640,22 @@ nsresult DnsAndConnectSocket::SetupConn(bool isPrimary, nsresult status) {
|
||||
// idle queue.
|
||||
// If the connection is in the idle queue but it is using ssl, make
|
||||
// a nulltransaction for it to finish ssl handshake!
|
||||
|
||||
// !!! It can be that mEnt is null after OnMsgReclaimConnection.!!!
|
||||
if (mEnt && mEnt->mConnInfo->FirstHopSSL() &&
|
||||
!mEnt->mConnInfo->UsingConnect()) {
|
||||
if (ent->mConnInfo->FirstHopSSL() &&
|
||||
!ent->mConnInfo->UsingConnect()) {
|
||||
RefPtr<nsHttpConnection> connTCP = do_QueryObject(conn);
|
||||
// If RemoveIdleConnection succeeds that means that conn is in the
|
||||
// idle queue.
|
||||
if (connTCP && NS_SUCCEEDED(mEnt->RemoveIdleConnection(connTCP))) {
|
||||
if (connTCP && NS_SUCCEEDED(ent->RemoveIdleConnection(connTCP))) {
|
||||
RefPtr<nsAHttpTransaction> trans;
|
||||
if (mTransaction->IsNullTransaction() && !mDispatchedMTransaction) {
|
||||
mDispatchedMTransaction = true;
|
||||
trans = mTransaction;
|
||||
} else {
|
||||
trans = new NullHttpTransaction(mEnt->mConnInfo, callbacks, mCaps);
|
||||
trans = new NullHttpTransaction(ent->mConnInfo, callbacks, mCaps);
|
||||
}
|
||||
mEnt->InsertIntoActiveConns(conn);
|
||||
ent->InsertIntoActiveConns(conn);
|
||||
rv = gHttpHandler->ConnMgr()->DispatchAbstractTransaction(
|
||||
mEnt, trans, mCaps, conn, 0);
|
||||
ent, trans, mCaps, conn, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -649,7 +677,6 @@ DnsAndConnectSocket::OnTransportStatus(nsITransport* trans, nsresult status,
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
MOZ_ASSERT(IsPrimary(trans) || IsBackup(trans));
|
||||
MOZ_ASSERT(mEnt);
|
||||
if (mTransaction) {
|
||||
if (IsPrimary(trans) ||
|
||||
(IsBackup(trans) && (status == NS_NET_STATUS_CONNECTED_TO) &&
|
||||
@ -685,55 +712,18 @@ DnsAndConnectSocket::OnTransportStatus(nsITransport* trans, nsresult status,
|
||||
// for this entry before then make the hash key if our dns lookup
|
||||
// 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_CONNECTING_TO && gHttpHandler->IsSpdyEnabled() &&
|
||||
gHttpHandler->CoalesceSpdy() && mEnt && mEnt->mConnInfo &&
|
||||
mEnt->mConnInfo->EndToEndSSL() && mEnt->AllowHttp2() &&
|
||||
!mEnt->mConnInfo->UsingProxy() && mEnt->mCoalescingKeys.IsEmpty()) {
|
||||
nsCOMPtr<nsIDNSAddrRecord> dnsRecord(
|
||||
nsCOMPtr<nsIDNSAddrRecord> dnsRecord(
|
||||
do_GetInterface(mPrimaryTransport.mSocketTransport));
|
||||
nsTArray<NetAddr> addressSet;
|
||||
nsresult rv = NS_ERROR_NOT_AVAILABLE;
|
||||
if (dnsRecord) {
|
||||
rv = dnsRecord->GetAddresses(addressSet);
|
||||
}
|
||||
if (status == NS_NET_STATUS_CONNECTING_TO && gHttpHandler->IsSpdyEnabled() &&
|
||||
gHttpHandler->CoalesceSpdy() && mConnInfo && mConnInfo->EndToEndSSL() &&
|
||||
!mConnInfo->UsingProxy() && dnsRecord) {
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !addressSet.IsEmpty()) {
|
||||
for (uint32_t i = 0; i < addressSet.Length(); ++i) {
|
||||
if ((addressSet[i].raw.family == AF_INET &&
|
||||
addressSet[i].inet.ip == 0) ||
|
||||
(addressSet[i].raw.family == AF_INET6 &&
|
||||
addressSet[i].inet6.ip.u64[0] == 0 &&
|
||||
addressSet[i].inet6.ip.u64[1] == 0)) {
|
||||
// Bug 1680249 - Don't create the coalescing key if the ip address is
|
||||
// `0.0.0.0` or `::`.
|
||||
LOG((
|
||||
"DnsAndConnectSocket: skip creating Coalescing Key for host [%s]",
|
||||
mEnt->mConnInfo->Origin()));
|
||||
continue;
|
||||
}
|
||||
nsCString* newKey = mEnt->mCoalescingKeys.AppendElement(nsCString());
|
||||
newKey->SetLength(kIPv6CStrBufSize + 26);
|
||||
addressSet[i].ToStringBuffer(newKey->BeginWriting(), kIPv6CStrBufSize);
|
||||
newKey->SetLength(strlen(newKey->BeginReading()));
|
||||
if (mEnt->mConnInfo->GetAnonymous()) {
|
||||
newKey->AppendLiteral("~A:");
|
||||
} else {
|
||||
newKey->AppendLiteral("~.:");
|
||||
}
|
||||
newKey->AppendInt(mEnt->mConnInfo->OriginPort());
|
||||
newKey->AppendLiteral("/[");
|
||||
nsAutoCString suffix;
|
||||
mEnt->mConnInfo->GetOriginAttributes().CreateSuffix(suffix);
|
||||
newKey->Append(suffix);
|
||||
newKey->AppendLiteral("]viaDNS");
|
||||
LOG((
|
||||
"DnsAndConnectSocket::OnTransportStatus "
|
||||
"STATUS_CONNECTING_TO Established New Coalescing Key # %d for host "
|
||||
"%s [%s]",
|
||||
i, mEnt->mConnInfo->Origin(), newKey->get()));
|
||||
RefPtr<ConnectionEntry> ent = gHttpHandler->ConnMgr()->FindConnectionEntry(mConnInfo);
|
||||
MOZ_DIAGNOSTIC_ASSERT(ent);
|
||||
if (ent) {
|
||||
if (ent->MaybeProcessCoalescingKeys(dnsRecord)) {
|
||||
gHttpHandler->ConnMgr()->ProcessSpdyPendingQ(ent);
|
||||
}
|
||||
gHttpHandler->ConnMgr()->ProcessSpdyPendingQ(mEnt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -807,7 +797,7 @@ bool DnsAndConnectSocket::Claim() {
|
||||
|
||||
// Http3 has its own syn-retransmission, therefore it does not need a
|
||||
// backup connection.
|
||||
if (mPrimaryTransport.ConnectingOrRetry() && mEnt &&
|
||||
if (mPrimaryTransport.ConnectingOrRetry() &&
|
||||
!mBackupTransport.mSocketTransport && !mSynTimer && !mIsHttp3) {
|
||||
SetupBackupTimer();
|
||||
}
|
||||
@ -1025,6 +1015,7 @@ nsresult DnsAndConnectSocket::TransportSetup::SetupConn(
|
||||
NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) {
|
||||
ent->RecordIPFamilyPreference(peeraddr.raw.family);
|
||||
}
|
||||
|
||||
conn.forget(connection);
|
||||
mSocketTransport = nullptr;
|
||||
mStreamOut = nullptr;
|
||||
@ -1037,10 +1028,9 @@ nsresult DnsAndConnectSocket::TransportSetup::SetupStreams(
|
||||
DnsAndConnectSocket* dnsAndSock) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
MOZ_ASSERT(dnsAndSock->mEnt);
|
||||
nsresult rv;
|
||||
nsTArray<nsCString> socketTypes;
|
||||
const nsHttpConnectionInfo* ci = dnsAndSock->mEnt->mConnInfo;
|
||||
const nsHttpConnectionInfo* ci = dnsAndSock->mConnInfo;
|
||||
if (dnsAndSock->mIsHttp3) {
|
||||
socketTypes.AppendElement("quic"_ns);
|
||||
} else {
|
||||
@ -1138,7 +1128,7 @@ nsresult DnsAndConnectSocket::TransportSetup::SetupStreams(
|
||||
// record is in cache before setting USE_IP_HINT_ADDRESS.
|
||||
nsCOMPtr<nsIDNSRecord> record;
|
||||
rv = dns->ResolveNative(mHost, nsIDNSService::RESOLVE_OFFLINE,
|
||||
dnsAndSock->mEnt->mConnInfo->GetOriginAttributes(),
|
||||
dnsAndSock->mConnInfo->GetOriginAttributes(),
|
||||
getter_AddRefs(record));
|
||||
if (NS_FAILED(rv) || !record) {
|
||||
LOG(("Setting Socket to use IP hint address"));
|
||||
@ -1146,21 +1136,7 @@ nsresult DnsAndConnectSocket::TransportSetup::SetupStreams(
|
||||
}
|
||||
}
|
||||
|
||||
if (dnsAndSock->mCaps & NS_HTTP_DISABLE_IPV4) {
|
||||
tmpFlags |= nsISocketTransport::DISABLE_IPV4;
|
||||
} else if (dnsAndSock->mCaps & NS_HTTP_DISABLE_IPV6) {
|
||||
tmpFlags |= nsISocketTransport::DISABLE_IPV6;
|
||||
} else if (dnsAndSock->mEnt->PreferenceKnown()) {
|
||||
if (dnsAndSock->mEnt->mPreferIPv6) {
|
||||
tmpFlags |= nsISocketTransport::DISABLE_IPV4;
|
||||
} else if (dnsAndSock->mEnt->mPreferIPv4) {
|
||||
tmpFlags |= nsISocketTransport::DISABLE_IPV6;
|
||||
}
|
||||
|
||||
// In case the host is no longer accessible via the preferred IP family,
|
||||
// try the opposite one and potentially restate the preference.
|
||||
tmpFlags |= nsISocketTransport::RETRY_WITH_DIFFERENT_IP_FAMILY;
|
||||
|
||||
if (mRetryWithDifferentIPFamily) {
|
||||
// From the same reason, let the backup socket fail faster to try the other
|
||||
// family.
|
||||
uint16_t fallbackTimeout =
|
||||
@ -1169,27 +1145,16 @@ nsresult DnsAndConnectSocket::TransportSetup::SetupStreams(
|
||||
socketTransport->SetTimeout(nsISocketTransport::TIMEOUT_CONNECT,
|
||||
fallbackTimeout);
|
||||
}
|
||||
} else if (mIsBackup && gHttpHandler->FastFallbackToIPv4()) {
|
||||
// For backup connections, we disable IPv6. That's because some users have
|
||||
// broken IPv6 connectivity (leading to very long timeouts), and disabling
|
||||
// IPv6 on the backup connection gives them a much better user experience
|
||||
// with dual-stack hosts, though they still pay the 250ms delay for each new
|
||||
// connection. This strategy is also known as "happy eyeballs".
|
||||
tmpFlags |= nsISocketTransport::DISABLE_IPV6;
|
||||
}
|
||||
|
||||
if (!dnsAndSock->Allow1918()) {
|
||||
tmpFlags |= nsISocketTransport::DISABLE_RFC1918;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!(tmpFlags & nsISocketTransport::DISABLE_IPV4) ||
|
||||
!(tmpFlags & nsISocketTransport::DISABLE_IPV6),
|
||||
"Both types should not be disabled at the same time.");
|
||||
socketTransport->SetConnectionFlags(tmpFlags);
|
||||
socketTransport->SetTlsFlags(ci->GetTlsFlags());
|
||||
|
||||
const OriginAttributes& originAttributes =
|
||||
dnsAndSock->mEnt->mConnInfo->GetOriginAttributes();
|
||||
const OriginAttributes& originAttributes = dnsAndSock->mConnInfo->GetOriginAttributes();
|
||||
if (originAttributes != OriginAttributes()) {
|
||||
socketTransport->SetOriginAttributes(originAttributes);
|
||||
}
|
||||
@ -1207,9 +1172,13 @@ nsresult DnsAndConnectSocket::TransportSetup::SetupStreams(
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::HTTP_CONNECTION_ENTRY_CACHE_HIT_1,
|
||||
dnsAndSock->mEnt->mUsedForConnection);
|
||||
dnsAndSock->mEnt->mUsedForConnection = true;
|
||||
RefPtr<ConnectionEntry> ent = gHttpHandler->ConnMgr()->FindConnectionEntry(ci);
|
||||
MOZ_DIAGNOSTIC_ASSERT(ent);
|
||||
if (ent) {
|
||||
Telemetry::Accumulate(Telemetry::HTTP_CONNECTION_ENTRY_CACHE_HIT_1,
|
||||
ent->mUsedForConnection);
|
||||
ent->mUsedForConnection = true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIOutputStream> sout;
|
||||
rv = socketTransport->OpenOutputStream(nsITransport::OPEN_UNBUFFERED, 0, 0,
|
||||
@ -1252,14 +1221,14 @@ nsresult DnsAndConnectSocket::TransportSetup::ResolveHost(
|
||||
nsresult rv = dns->AsyncResolveNative(
|
||||
mHost, nsIDNSService::RESOLVE_TYPE_DEFAULT, mDnsFlags, nullptr,
|
||||
dnsAndSock, gSocketTransportService,
|
||||
dnsAndSock->mEnt->mConnInfo->GetOriginAttributes(),
|
||||
dnsAndSock->mConnInfo->GetOriginAttributes(),
|
||||
getter_AddRefs(mDNSRequest));
|
||||
if (NS_FAILED(rv) && (mDnsFlags & nsIDNSService::RESOLVE_IP_HINT)) {
|
||||
mDnsFlags &= ~nsIDNSService::RESOLVE_IP_HINT;
|
||||
return dns->AsyncResolveNative(
|
||||
mHost, nsIDNSService::RESOLVE_TYPE_DEFAULT, mDnsFlags, nullptr,
|
||||
dnsAndSock, gSocketTransportService,
|
||||
dnsAndSock->mEnt->mConnInfo->GetOriginAttributes(),
|
||||
dnsAndSock->mConnInfo->GetOriginAttributes(),
|
||||
getter_AddRefs(mDNSRequest));
|
||||
}
|
||||
|
||||
@ -1273,7 +1242,7 @@ nsresult DnsAndConnectSocket::TransportSetup::OnLookupComplete(
|
||||
mDNSRecord = do_QueryInterface(rec);
|
||||
MOZ_ASSERT(mDNSRecord);
|
||||
|
||||
if (dnsAndSock->mEnt->mConnInfo->IsHttp3()) {
|
||||
if (dnsAndSock->mConnInfo->IsHttp3()) {
|
||||
mState = TransportSetup::TransportSetupState::RESOLVED;
|
||||
return status;
|
||||
} else {
|
||||
|
@ -52,19 +52,17 @@ class DnsAndConnectSocket final : public nsIOutputStreamCallback,
|
||||
NS_DECL_NSINAMED
|
||||
NS_DECL_NSIDNSLISTENER
|
||||
|
||||
DnsAndConnectSocket(ConnectionEntry* ent, nsAHttpTransaction* trans,
|
||||
DnsAndConnectSocket(nsHttpConnectionInfo* ci, nsAHttpTransaction* trans,
|
||||
uint32_t caps, bool speculative, bool isFromPredictor,
|
||||
bool urgentStart);
|
||||
|
||||
[[nodiscard]] nsresult Init();
|
||||
[[nodiscard]] nsresult Init(ConnectionEntry* ent);
|
||||
void Abandon();
|
||||
double Duration(TimeStamp epoch);
|
||||
void CloseTransports(nsresult error);
|
||||
|
||||
bool IsSpeculative() { return mSpeculative; }
|
||||
|
||||
bool IsFromPredictor() { return mIsFromPredictor; }
|
||||
|
||||
bool Allow1918() { return mAllow1918; }
|
||||
void SetAllow1918(bool val) { mAllow1918 = val; }
|
||||
|
||||
@ -201,7 +199,7 @@ class DnsAndConnectSocket final : public nsIOutputStreamCallback,
|
||||
bool removeWhenFound);
|
||||
|
||||
void CheckProxyConfig();
|
||||
nsresult SetupDnsFlags();
|
||||
nsresult SetupDnsFlags(ConnectionEntry* ent);
|
||||
nsresult SetupEvent(SetupEvents event);
|
||||
|
||||
RefPtr<nsAHttpTransaction> mTransaction;
|
||||
@ -242,7 +240,7 @@ class DnsAndConnectSocket final : public nsIOutputStreamCallback,
|
||||
// transactions.
|
||||
bool mFreeToUse = true;
|
||||
|
||||
RefPtr<ConnectionEntry> mEnt;
|
||||
RefPtr<nsHttpConnectionInfo> mConnInfo;
|
||||
nsCOMPtr<nsITimer> mSynTimer;
|
||||
TransportSetup mBackupTransport;
|
||||
|
||||
|
@ -95,24 +95,18 @@ bool PendingTransactionInfo::IsAlreadyClaimedInitializingConn() {
|
||||
return alreadyDnsAndSockOrWaitingForTLS;
|
||||
}
|
||||
|
||||
void PendingTransactionInfo::AbandonDnsAndConnectSocketAndForgetActiveConn() {
|
||||
// Abandon all DnsAndConnectSockets belonging to the given transaction.
|
||||
RefPtr<DnsAndConnectSocket> dnsAndSock = do_QueryReferent(mDnsAndSock);
|
||||
if (dnsAndSock) {
|
||||
dnsAndSock->Abandon();
|
||||
}
|
||||
nsWeakPtr PendingTransactionInfo::ForgetDnsAndConnectSocketAndActiveConn() {
|
||||
nsWeakPtr dnsAndSock = mDnsAndSock;
|
||||
|
||||
mDnsAndSock = nullptr;
|
||||
mActiveConn = nullptr;
|
||||
return dnsAndSock;
|
||||
}
|
||||
|
||||
bool PendingTransactionInfo::TryClaimingDnsAndConnectSocket(
|
||||
void PendingTransactionInfo::RememberDnsAndConnectSocket(
|
||||
DnsAndConnectSocket* sock) {
|
||||
if (sock->Claim()) {
|
||||
mDnsAndSock =
|
||||
do_GetWeakReference(static_cast<nsISupportsWeakReference*>(sock));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
mDnsAndSock =
|
||||
do_GetWeakReference(static_cast<nsISupportsWeakReference*>(sock));
|
||||
}
|
||||
|
||||
bool PendingTransactionInfo::TryClaimingActiveConn(HttpConnectionBase* conn) {
|
||||
|
@ -24,11 +24,14 @@ class PendingTransactionInfo final : public ARefBase {
|
||||
// a connection in TLS handshake phase.
|
||||
bool IsAlreadyClaimedInitializingConn();
|
||||
|
||||
void AbandonDnsAndConnectSocketAndForgetActiveConn();
|
||||
// This function return a weak poointer to DnsAndConnectSocket.
|
||||
// The pointer is used by the caller(ConnectionEntry) to remove the
|
||||
// DnsAndConnectSocket from the internal list. PendingTransactionInfo
|
||||
// cannot perform this opereation.
|
||||
[[nodiscard]] nsWeakPtr ForgetDnsAndConnectSocketAndActiveConn();
|
||||
|
||||
// Try to claim a halfOpen socket. We can only claim it if it is not
|
||||
// claimed yet.
|
||||
bool TryClaimingDnsAndConnectSocket(DnsAndConnectSocket* sock);
|
||||
// Remember associated DnsAndConnectSocket.
|
||||
void RememberDnsAndConnectSocket(DnsAndConnectSocket* sock);
|
||||
// Similar as above, but for a ActiveConn that is performing a TLS handshake
|
||||
// and has only a NullTransaction associated.
|
||||
bool TryClaimingActiveConn(HttpConnectionBase* conn);
|
||||
|
@ -1232,15 +1232,15 @@ nsresult nsHttpConnectionMgr::MakeNewConnection(
|
||||
if (AtActiveConnectionLimit(ent, trans->Caps()))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsresult rv =
|
||||
CreateTransport(ent, trans, trans->Caps(), false, false,
|
||||
trans->ClassOfService() & nsIClassOfService::UrgentStart,
|
||||
true, pendingTransInfo);
|
||||
nsresult rv = ent->CreateDnsAndConnectSocket(
|
||||
trans, trans->Caps(), false, false,
|
||||
trans->ClassOfService() & nsIClassOfService::UrgentStart, true,
|
||||
pendingTransInfo);
|
||||
if (NS_FAILED(rv)) {
|
||||
/* hard failure */
|
||||
LOG(
|
||||
("nsHttpConnectionMgr::MakeNewConnection [ci = %s trans = %p] "
|
||||
"CreateTransport() hard failure.\n",
|
||||
"CreateDnsAndConnectSocket() hard failure.\n",
|
||||
ent->mConnInfo->HashKey().get(), trans));
|
||||
trans->Close(rv);
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) rv = NS_ERROR_FAILURE;
|
||||
@ -1738,36 +1738,6 @@ void nsHttpConnectionMgr::RecvdConnect() {
|
||||
ConditionallyStopTimeoutTick();
|
||||
}
|
||||
|
||||
nsresult nsHttpConnectionMgr::CreateTransport(
|
||||
ConnectionEntry* ent, nsAHttpTransaction* trans, uint32_t caps,
|
||||
bool speculative, bool isFromPredictor, bool urgentStart, bool allow1918,
|
||||
PendingTransactionInfo* pendingTransInfo) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
MOZ_ASSERT((speculative && !pendingTransInfo) ||
|
||||
(!speculative && pendingTransInfo));
|
||||
|
||||
RefPtr<DnsAndConnectSocket> sock = new DnsAndConnectSocket(
|
||||
ent, trans, caps, speculative, isFromPredictor, urgentStart);
|
||||
|
||||
if (speculative) {
|
||||
sock->SetAllow1918(allow1918);
|
||||
}
|
||||
// The socket stream holds the reference to the half open
|
||||
// socket - so if the stream fails to init the half open
|
||||
// will go away.
|
||||
nsresult rv = sock->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (pendingTransInfo) {
|
||||
DebugOnly<bool> claimed =
|
||||
pendingTransInfo->TryClaimingDnsAndConnectSocket(sock);
|
||||
MOZ_ASSERT(claimed);
|
||||
}
|
||||
|
||||
ent->InsertIntoDnsAndConnectSockets(sock);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsHttpConnectionMgr::DispatchSpdyPendingQ(
|
||||
nsTArray<RefPtr<PendingTransactionInfo>>& pendingQ, ConnectionEntry* ent,
|
||||
HttpConnectionBase* connH2, HttpConnectionBase* connH3) {
|
||||
@ -3298,7 +3268,7 @@ void nsHttpConnectionMgr::DoSpeculativeConnection(
|
||||
Unused << aTrans->FetchHTTPSRR();
|
||||
}
|
||||
DebugOnly<nsresult> rv =
|
||||
CreateTransport(ent, aTrans, aTrans->Caps(), true, isFromPredictor,
|
||||
ent->CreateDnsAndConnectSocket(aTrans, aTrans->Caps(), true, isFromPredictor,
|
||||
false, allow1918, nullptr);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
} else {
|
||||
@ -3506,6 +3476,11 @@ nsHttpConnectionMgr::FindTransactionHelper(bool removeWhenFound,
|
||||
return info.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ConnectionEntry>
|
||||
nsHttpConnectionMgr::FindConnectionEntry(const nsHttpConnectionInfo* ci) {
|
||||
return mCT.Get(ci->HashKey());
|
||||
}
|
||||
|
||||
nsHttpConnectionMgr* nsHttpConnectionMgr::AsHttpConnectionMgr() { return this; }
|
||||
|
||||
HttpConnectionMgrParent* nsHttpConnectionMgr::AsHttpConnectionMgrParent() {
|
||||
|
@ -171,6 +171,9 @@ class nsHttpConnectionMgr final : public HttpConnectionMgrShell,
|
||||
already_AddRefed<PendingTransactionInfo> FindTransactionHelper(
|
||||
bool removeWhenFound, ConnectionEntry* aEnt, nsAHttpTransaction* aTrans);
|
||||
|
||||
already_AddRefed<ConnectionEntry> FindConnectionEntry(
|
||||
const nsHttpConnectionInfo* ci);
|
||||
|
||||
public:
|
||||
static nsAHttpConnection* MakeConnectionHandle(HttpConnectionBase* aWrapped);
|
||||
void RegisterOriginCoalescingKey(HttpConnectionBase*, const nsACString& host,
|
||||
@ -255,9 +258,6 @@ class nsHttpConnectionMgr final : public HttpConnectionMgrShell,
|
||||
[[nodiscard]] nsresult ProcessNewTransaction(nsHttpTransaction*);
|
||||
[[nodiscard]] nsresult EnsureSocketThreadTarget();
|
||||
void ReportProxyTelemetry(ConnectionEntry* ent);
|
||||
[[nodiscard]] nsresult CreateTransport(
|
||||
ConnectionEntry*, nsAHttpTransaction*, uint32_t, bool, bool, bool, bool,
|
||||
PendingTransactionInfo* pendingTransInfo);
|
||||
void StartedConnect();
|
||||
void RecvdConnect();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user