mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-04 11:26:09 +00:00
Bug 1652655 - P3: Dispatch the transaction based on HTTPSSVC record, r=dragana
Differential Revision: https://phabricator.services.mozilla.com/D85123
This commit is contained in:
parent
a841171067
commit
10d957aaa7
@ -8316,6 +8316,12 @@
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Whether to use HTTPS RR as AltSvc
|
||||
- name: network.dns.use_https_rr_as_altsvc
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Prefs starting with "nglayout."
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -746,5 +746,9 @@ NS_IMETHODIMP ClassifierDummyChannel::GetResponseEmbedderPolicy(
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ClassifierDummyChannel::SetWaitForHTTPSSVCRecord() {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -4840,5 +4840,10 @@ void HttpBaseChannel::MaybeFlushConsoleReports() {
|
||||
|
||||
void HttpBaseChannel::DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() {}
|
||||
|
||||
NS_IMETHODIMP HttpBaseChannel::SetWaitForHTTPSSVCRecord() {
|
||||
mCaps |= NS_HTTP_WAIT_HTTPSSVC_RESULT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -340,6 +340,8 @@ class HttpBaseChannel : public nsHashPropertyBag,
|
||||
nsIHttpUpgradeListener* aListener) override;
|
||||
void DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() override;
|
||||
|
||||
NS_IMETHOD SetWaitForHTTPSSVCRecord() override;
|
||||
|
||||
// nsISupportsPriority
|
||||
NS_IMETHOD GetPriority(int32_t* value) override;
|
||||
NS_IMETHOD AdjustPriority(int32_t delta) override;
|
||||
|
@ -120,6 +120,10 @@ extern const nsCString kHttp3Versions[];
|
||||
// such as HTTP upgrade which are not supported by HTTP3.
|
||||
#define NS_HTTP_DISALLOW_HTTP3 (1 << 22)
|
||||
|
||||
// Force a transaction to stay in pending queue until the HTTPSSVC record is
|
||||
// available.
|
||||
#define NS_HTTP_WAIT_HTTPSSVC_RESULT (1 << 23)
|
||||
|
||||
#define NS_HTTP_TRR_FLAGS_FROM_MODE(x) ((static_cast<uint32_t>(x) & 3) << 19)
|
||||
|
||||
#define NS_HTTP_TRR_MODE_FROM_FLAGS(x) \
|
||||
|
@ -26,7 +26,10 @@
|
||||
#include "nsHttpConnectionMgr.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsIDNSByTypeRecord.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIRequestContext.h"
|
||||
#include "nsISocketTransport.h"
|
||||
@ -1716,6 +1719,12 @@ nsresult nsHttpConnectionMgr::TryDispatchTransaction(
|
||||
// consider pipelining scripts and revalidations
|
||||
// h1 pipelining has been removed
|
||||
|
||||
// Don't dispatch if this transaction is waiting for HTTPS RR.
|
||||
// Note that this is only used in test currently.
|
||||
if (caps & NS_HTTP_WAIT_HTTPSSVC_RESULT) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// step 4
|
||||
if (!onlyReusedConnection) {
|
||||
nsresult rv = MakeNewConnection(ent, pendingTransInfo);
|
||||
@ -5762,6 +5771,62 @@ void nsHttpConnectionMgr::MoveToWildCardConnEntry(
|
||||
}
|
||||
}
|
||||
|
||||
bool nsHttpConnectionMgr::MoveTransToHTTPSSVCConnEntry(
|
||||
nsHttpTransaction* aTrans, nsHttpConnectionInfo* aNewCI) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
LOG(("nsHttpConnectionMgr::MoveTransToHTTPSSVCConnEntry: trans=%p aNewCI=%s",
|
||||
aTrans, aNewCI->HashKey().get()));
|
||||
|
||||
bool prohibitWildCard = !!aTrans->TunnelProvider();
|
||||
bool noHttp3 = aTrans->Caps() & NS_HTTP_DISALLOW_HTTP3;
|
||||
// Step 1: Check if the new entry is the same as the old one.
|
||||
nsConnectionEntry* oldEntry = GetOrCreateConnectionEntry(
|
||||
aTrans->ConnectionInfo(), prohibitWildCard, noHttp3);
|
||||
|
||||
nsConnectionEntry* newEntry =
|
||||
GetOrCreateConnectionEntry(aNewCI, prohibitWildCard, noHttp3);
|
||||
|
||||
if (oldEntry == newEntry) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 2: Try to find the undispatched transaction.
|
||||
int32_t transIndex;
|
||||
// We will abandon all half-open sockets belonging to the given
|
||||
// transaction.
|
||||
nsTArray<RefPtr<PendingTransactionInfo>>* infoArray =
|
||||
GetTransactionPendingQHelper(oldEntry, aTrans);
|
||||
|
||||
RefPtr<PendingTransactionInfo> pendingTransInfo;
|
||||
transIndex =
|
||||
infoArray ? infoArray->IndexOf(aTrans, 0, PendingComparator()) : -1;
|
||||
if (transIndex >= 0) {
|
||||
pendingTransInfo = (*infoArray)[transIndex];
|
||||
infoArray->RemoveElementAt(transIndex);
|
||||
}
|
||||
|
||||
// It's fine we can't find the transaction. The transaction may not be added.
|
||||
if (!pendingTransInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pendingTransInfo->mTransaction == aTrans);
|
||||
|
||||
// Abandon all half-open sockets belonging to the given transaction.
|
||||
RefPtr<nsHalfOpenSocket> half = do_QueryReferent(pendingTransInfo->mHalfOpen);
|
||||
if (half) {
|
||||
half->Abandon();
|
||||
}
|
||||
pendingTransInfo->mHalfOpen = nullptr;
|
||||
pendingTransInfo->mActiveConn = nullptr;
|
||||
|
||||
// Step 3: Add the transaction to the new entry.
|
||||
aTrans->UpdateConnectionInfo(aNewCI);
|
||||
Unused << ProcessNewTransaction(aTrans);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsHttpConnectionMgr* nsHttpConnectionMgr::AsHttpConnectionMgr() { return this; }
|
||||
|
||||
HttpConnectionMgrParent* nsHttpConnectionMgr::AsHttpConnectionMgrParent() {
|
||||
|
@ -94,6 +94,12 @@ class nsHttpConnectionMgr final : public HttpConnectionMgrShell,
|
||||
nsHttpConnectionInfo* wildcardCI,
|
||||
HttpConnectionBase* conn);
|
||||
|
||||
// Move a transaction from the pendingQ of it's connection entry to another
|
||||
// one. Returns true if the transaction is moved successfully, otherwise
|
||||
// returns false.
|
||||
bool MoveTransToHTTPSSVCConnEntry(nsHttpTransaction* aTrans,
|
||||
nsHttpConnectionInfo* aNewCI);
|
||||
|
||||
[[nodiscard]] bool ProcessPendingQForEntry(nsHttpConnectionInfo*);
|
||||
|
||||
// This is used to force an idle connection to be closed and removed from
|
||||
|
@ -2964,4 +2964,8 @@ void nsHttpHandler::MaybeAddAltSvcForTesting(
|
||||
}
|
||||
}
|
||||
|
||||
bool nsHttpHandler::UseHTTPSRRAsAltSvcEnabled() const {
|
||||
return StaticPrefs::network_dns_use_https_rr_as_altsvc();
|
||||
}
|
||||
|
||||
} // namespace mozilla::net
|
||||
|
@ -502,6 +502,8 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
|
||||
nsIInterfaceRequestor* aCallbacks,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
|
||||
bool UseHTTPSRRAsAltSvcEnabled() const;
|
||||
|
||||
private:
|
||||
nsHttpHandler();
|
||||
|
||||
|
@ -28,6 +28,9 @@
|
||||
#include "nsHttpResponseHead.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsIDNSByTypeRecord.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIHttpActivityObserver.h"
|
||||
#include "nsIHttpAuthenticator.h"
|
||||
@ -424,6 +427,27 @@ nsresult nsHttpTransaction::Init(
|
||||
MOZ_ASSERT(trans);
|
||||
mPushedStream = trans->TakePushedStreamById(aPushedStreamId);
|
||||
}
|
||||
|
||||
if (gHttpHandler->UseHTTPSRRAsAltSvcEnabled()) {
|
||||
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
|
||||
nsCOMPtr<nsIEventTarget> target;
|
||||
Unused << gHttpHandler->GetSocketThreadTarget(getter_AddRefs(target));
|
||||
if (dns && target) {
|
||||
uint32_t flags =
|
||||
nsIDNSService::GetFlagsFromTRRMode(mConnInfo->GetTRRMode());
|
||||
if (mCaps & NS_HTTP_REFRESH_DNS) {
|
||||
flags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
|
||||
}
|
||||
|
||||
rv = dns->AsyncResolveNative(
|
||||
mConnInfo->GetOrigin(), nsIDNSService::RESOLVE_TYPE_HTTPSSVC, flags,
|
||||
nullptr, this, target, mConnInfo->GetOriginAttributes(),
|
||||
getter_AddRefs(mDNSRequest));
|
||||
if (NS_FAILED(rv) && (mCaps & NS_HTTP_WAIT_HTTPSSVC_RESULT)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -522,6 +546,11 @@ void nsHttpTransaction::OnActivated() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDNSRequest) {
|
||||
mDNSRequest->Cancel(NS_ERROR_ABORT);
|
||||
mDNSRequest = nullptr;
|
||||
}
|
||||
|
||||
if (mTrafficCategory != HttpTrafficCategory::eInvalid) {
|
||||
HttpTrafficAnalyzer* hta = gHttpHandler->GetHttpTrafficAnalyzer();
|
||||
if (hta) {
|
||||
@ -2364,7 +2393,7 @@ nsHttpTransaction::Release() {
|
||||
}
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE(nsHttpTransaction, nsIInputStreamCallback,
|
||||
nsIOutputStreamCallback)
|
||||
nsIOutputStreamCallback, nsIDNSListener)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpTransaction::nsIInputStreamCallback
|
||||
@ -2627,5 +2656,58 @@ void nsHttpTransaction::NotifyTransactionObserver(nsresult reason) {
|
||||
obs(std::move(result));
|
||||
}
|
||||
|
||||
void nsHttpTransaction::UpdateConnectionInfo(nsHttpConnectionInfo* aConnInfo) {
|
||||
MOZ_ASSERT(aConnInfo);
|
||||
|
||||
if (mActivated) {
|
||||
MOZ_ASSERT(false, "Should not update conn info after activated");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: maybe backup the old connection info.
|
||||
mConnInfo = aConnInfo;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHttpTransaction::OnLookupComplete(nsICancelable* aRequest,
|
||||
nsIDNSRecord* aRecord,
|
||||
nsresult aStatus) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
LOG(("nsHttpTransaction::OnLookupComplete [this=%p] mActivated=%d", this,
|
||||
mActivated));
|
||||
|
||||
mDNSRequest = nullptr;
|
||||
|
||||
MakeDontWaitHTTPSSVC();
|
||||
|
||||
if (mActivated) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDNSHTTPSSVCRecord> record = do_QueryInterface(aRecord);
|
||||
if (!record || NS_FAILED(aStatus)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISVCBRecord> svcbRecord;
|
||||
if (NS_FAILED(record->GetServiceModeRecord(mCaps & NS_HTTP_DISALLOW_SPDY,
|
||||
mCaps & NS_HTTP_DISALLOW_HTTP3,
|
||||
getter_AddRefs(svcbRecord)))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<nsHttpConnectionInfo> newInfo =
|
||||
mConnInfo->CloneAndAdoptHTTPSSVCRecord(svcbRecord);
|
||||
if (!gHttpHandler->ConnMgr()->MoveTransToHTTPSSVCConnEntry(this, newInfo)) {
|
||||
// MoveTransToHTTPSSVCConnEntry() returning fail means this transaction is
|
||||
// not in the connection entry's pending queue. This could happen if
|
||||
// OnLookupComplete() is called before this transaction is added in the
|
||||
// queue. We still need to update the connection info, so this transaction
|
||||
// can be added to the right connection entry.
|
||||
UpdateConnectionInfo(newInfo);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "EventTokenBucket.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "TimingStruct.h"
|
||||
#include "Http2Push.h"
|
||||
@ -48,13 +49,15 @@ class nsHttpTransaction final : public nsAHttpTransaction,
|
||||
public ATokenBucketEvent,
|
||||
public nsIInputStreamCallback,
|
||||
public nsIOutputStreamCallback,
|
||||
public ARefBase {
|
||||
public ARefBase,
|
||||
public nsIDNSListener {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSAHTTPTRANSACTION
|
||||
NS_DECL_HTTPTRANSACTIONSHELL
|
||||
NS_DECL_NSIINPUTSTREAMCALLBACK
|
||||
NS_DECL_NSIOUTPUTSTREAMCALLBACK
|
||||
NS_DECL_NSIDNSLISTENER
|
||||
|
||||
nsHttpTransaction();
|
||||
|
||||
@ -74,6 +77,8 @@ class nsHttpTransaction final : public nsAHttpTransaction,
|
||||
void MakeSticky() { mCaps |= NS_HTTP_STICKY_CONNECTION; }
|
||||
void MakeNonSticky() override { mCaps &= ~NS_HTTP_STICKY_CONNECTION; }
|
||||
|
||||
void MakeDontWaitHTTPSSVC() { mCaps &= ~NS_HTTP_WAIT_HTTPSSVC_RESULT; }
|
||||
|
||||
// SetPriority() may only be used by the connection manager.
|
||||
void SetPriority(int32_t priority) { mPriority = priority; }
|
||||
int32_t Priority() { return mPriority; }
|
||||
@ -144,6 +149,8 @@ class nsHttpTransaction final : public nsAHttpTransaction,
|
||||
// transaction.
|
||||
void OnPush(Http2PushedStreamWrapper* aStream);
|
||||
|
||||
void UpdateConnectionInfo(nsHttpConnectionInfo* aConnInfo);
|
||||
|
||||
private:
|
||||
friend class DeleteHttpTransaction;
|
||||
virtual ~nsHttpTransaction();
|
||||
@ -431,6 +438,8 @@ class nsHttpTransaction final : public nsAHttpTransaction,
|
||||
OnPushCallback mOnPushCallback;
|
||||
nsDataHashtable<nsUint32HashKey, RefPtr<Http2PushedStreamWrapper>>
|
||||
mIDToStreamMap;
|
||||
|
||||
nsCOMPtr<nsICancelable> mDNSRequest;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
@ -415,4 +415,10 @@ interface nsIHttpChannelInternal : nsISupports
|
||||
|
||||
[noscript, notxpcom, nostdcall]
|
||||
void DoDiagnosticAssertWhenOnStopNotCalledOnDestroy();
|
||||
|
||||
/**
|
||||
* If this is called, this channel's transaction will not be dispatched
|
||||
* until the HTTPSSVC record is available.
|
||||
*/
|
||||
[must_use] void setWaitForHTTPSSVCRecord();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user