summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/nsHttpConnectionInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--netwerk/protocol/http/nsHttpConnectionInfo.cpp570
1 files changed, 570 insertions, 0 deletions
diff --git a/netwerk/protocol/http/nsHttpConnectionInfo.cpp b/netwerk/protocol/http/nsHttpConnectionInfo.cpp
new file mode 100644
index 0000000000..e91128d85a
--- /dev/null
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.cpp
@@ -0,0 +1,570 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// HttpLog.h should generally be included first
+#include "HttpLog.h"
+
+// Log on level :5, instead of default :4.
+#undef LOG
+#define LOG(args) LOG5(args)
+#undef LOG_ENABLED
+#define LOG_ENABLED() LOG5_ENABLED()
+
+#include "nsHttpConnectionInfo.h"
+
+#include "mozilla/net/DNS.h"
+#include "mozilla/net/NeckoChannelParams.h"
+#include "nsComponentManagerUtils.h"
+#include "nsICryptoHash.h"
+#include "nsIDNSByTypeRecord.h"
+#include "nsIProtocolProxyService.h"
+#include "nsHttpHandler.h"
+#include "nsNetCID.h"
+#include "nsProxyInfo.h"
+#include "prnetdb.h"
+
+static nsresult SHA256(const char* aPlainText, nsAutoCString& aResult) {
+ nsresult rv;
+ nsCOMPtr<nsICryptoHash> hasher =
+ do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) {
+ LOG(("nsHttpDigestAuth: no crypto hash!\n"));
+ return rv;
+ }
+ rv = hasher->Init(nsICryptoHash::SHA256);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = hasher->Update((unsigned char*)aPlainText, strlen(aPlainText));
+ NS_ENSURE_SUCCESS(rv, rv);
+ return hasher->Finish(false, aResult);
+}
+
+namespace mozilla {
+namespace net {
+
+nsHttpConnectionInfo::nsHttpConnectionInfo(
+ const nsACString& originHost, int32_t originPort,
+ const nsACString& npnToken, const nsACString& username,
+ nsProxyInfo* proxyInfo, const OriginAttributes& originAttributes,
+ bool endToEndSSL, bool aIsHttp3, bool aWebTransport)
+ : mRoutedPort(443), mLessThanTls13(false) {
+ Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes,
+ endToEndSSL, aIsHttp3, aWebTransport);
+}
+
+nsHttpConnectionInfo::nsHttpConnectionInfo(
+ const nsACString& originHost, int32_t originPort,
+ const nsACString& npnToken, const nsACString& username,
+ nsProxyInfo* proxyInfo, const OriginAttributes& originAttributes,
+ const nsACString& routedHost, int32_t routedPort, bool aIsHttp3,
+ bool aWebTransport)
+ : mLessThanTls13(false) {
+ mEndToEndSSL = true; // so DefaultPort() works
+ mRoutedPort = routedPort == -1 ? DefaultPort() : routedPort;
+
+ if (!originHost.Equals(routedHost) || (originPort != routedPort) ||
+ aIsHttp3) {
+ mRoutedHost = routedHost;
+ }
+ Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes,
+ true, aIsHttp3, aWebTransport);
+}
+
+void nsHttpConnectionInfo::Init(const nsACString& host, int32_t port,
+ const nsACString& npnToken,
+ const nsACString& username,
+ nsProxyInfo* proxyInfo,
+ const OriginAttributes& originAttributes,
+ bool e2eSSL, bool aIsHttp3,
+ bool aWebTransport) {
+ LOG(("Init nsHttpConnectionInfo @%p\n", this));
+
+ MOZ_RELEASE_ASSERT(!aWebTransport || aIsHttp3);
+
+ mUsername = username;
+ mProxyInfo = proxyInfo;
+ mEndToEndSSL = e2eSSL;
+ mUsingConnect = false;
+ mNPNToken = npnToken;
+ mIsHttp3 = aIsHttp3;
+ mWebTransport = aWebTransport;
+ mOriginAttributes = originAttributes;
+ mTlsFlags = 0x0;
+ mIsTrrServiceChannel = false;
+ mTRRMode = nsIRequest::TRR_DEFAULT_MODE;
+ mIPv4Disabled = false;
+ mIPv6Disabled = false;
+ mHasIPHintAddress = false;
+
+ mUsingHttpsProxy = (proxyInfo && proxyInfo->IsHTTPS());
+ mUsingHttpProxy = mUsingHttpsProxy || (proxyInfo && proxyInfo->IsHTTP());
+
+ if (mUsingHttpProxy) {
+ mUsingConnect = mEndToEndSSL; // SSL always uses CONNECT
+ uint32_t resolveFlags = 0;
+ if (NS_SUCCEEDED(mProxyInfo->GetResolveFlags(&resolveFlags)) &&
+ resolveFlags & nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL) {
+ mUsingConnect = true;
+ }
+ }
+
+ SetOriginServer(host, port);
+}
+
+void nsHttpConnectionInfo::BuildHashKey() {
+ //
+ // build hash key:
+ //
+ // the hash key uniquely identifies the connection type. two connections
+ // are "equal" if they end up talking the same protocol to the same server
+ // and are both used for anonymous or non-anonymous connection only;
+ // anonymity of the connection is setup later from nsHttpChannel::AsyncOpen
+ // where we know we use anonymous connection (LOAD_ANONYMOUS load flag)
+ //
+
+ const char* keyHost;
+ int32_t keyPort;
+
+ if (mUsingHttpProxy && !mUsingConnect) {
+ keyHost = ProxyHost();
+ keyPort = ProxyPort();
+ } else {
+ keyHost = Origin();
+ keyPort = OriginPort();
+ }
+
+ // The hashkey has 9 fields followed by host connection info
+ // byte 0 is P/T/. {P,T} for Plaintext/TLS Proxy over HTTP
+ // byte 1 is S/. S is for end to end ssl such as https:// uris
+ // byte 2 is A/. A is for an anonymous channel (no cookies, etc..)
+ // byte 3 is P/. P is for a private browising channel
+ // byte 4 is I/. I is for insecure scheme on TLS for http:// uris
+ // byte 5 is X/. X is for disallow_spdy flag
+ // byte 6 is C/. C is for be Conservative
+ // byte 7 is B/. B is for allowing client certs on an anonymous channel
+ // byte 8 is F/. F is for indicating a fallback connection
+ // byte 9 is W/. W is for indicating a webTransport
+ // Note: when adding/removing fields from this list which do not have
+ // corresponding data fields on the object itself, you may also need to
+ // modify RebuildHashKey.
+
+ const auto keyTemplate =
+ std::string(UnderlyingIndex(HashKeyIndex::End), '.') +
+ std::string("[tlsflags0x00000000]");
+ mHashKey.Assign(keyTemplate.c_str());
+
+ mHashKey.Append(keyHost);
+ mHashKey.Append(':');
+ mHashKey.AppendInt(keyPort);
+ if (!mUsername.IsEmpty()) {
+ mHashKey.Append('[');
+ mHashKey.Append(mUsername);
+ mHashKey.Append(']');
+ }
+
+ if (mUsingHttpsProxy) {
+ SetHashCharAt('T', HashKeyIndex::Proxy);
+ } else if (mUsingHttpProxy) {
+ SetHashCharAt('P', HashKeyIndex::Proxy);
+ }
+ if (mEndToEndSSL) {
+ SetHashCharAt('S', HashKeyIndex::EndToEndSSL);
+ }
+
+ if (mWebTransport) {
+ SetHashCharAt('W', HashKeyIndex::WebTransport);
+ }
+
+ // NOTE: for transparent proxies (e.g., SOCKS) we need to encode the proxy
+ // info in the hash key (this ensures that we will continue to speak the
+ // right protocol even if our proxy preferences change).
+ //
+ // NOTE: for SSL tunnels add the proxy information to the cache key.
+ // We cannot use the proxy as the host parameter (as we do for non SSL)
+ // because this is a single host tunnel, but we need to include the proxy
+ // information so that a change in proxy config will mean this connection
+ // is not reused
+
+ // NOTE: Adding the username and the password provides a means to isolate
+ // keep-alive to the URL bar domain as well: If the username is the URL bar
+ // domain, keep-alive connections are not reused by resources bound to
+ // different URL bar domains as the respective hash keys are not matching.
+
+ if ((!mUsingHttpProxy && ProxyHost()) || (mUsingHttpProxy && mUsingConnect)) {
+ mHashKey.AppendLiteral(" (");
+ mHashKey.Append(ProxyType());
+ mHashKey.Append(':');
+ mHashKey.Append(ProxyHost());
+ mHashKey.Append(':');
+ mHashKey.AppendInt(ProxyPort());
+ mHashKey.Append(')');
+ mHashKey.Append('[');
+ mHashKey.Append(ProxyUsername());
+ mHashKey.Append(':');
+ const char* password = ProxyPassword();
+ if (strlen(password) > 0) {
+ nsAutoCString digestedPassword;
+ nsresult rv = SHA256(password, digestedPassword);
+ if (rv == NS_OK) {
+ mHashKey.Append(digestedPassword);
+ }
+ }
+ mHashKey.Append(']');
+ }
+
+ if (!mRoutedHost.IsEmpty()) {
+ mHashKey.AppendLiteral(" <ROUTE-via ");
+ mHashKey.Append(mRoutedHost);
+ mHashKey.Append(':');
+ mHashKey.AppendInt(mRoutedPort);
+ mHashKey.Append('>');
+ }
+
+ if (!mNPNToken.IsEmpty()) {
+ mHashKey.AppendLiteral(" {NPN-TOKEN ");
+ mHashKey.Append(mNPNToken);
+ mHashKey.AppendLiteral("}");
+ }
+
+ if (GetTRRMode() != nsIRequest::TRR_DEFAULT_MODE) {
+ // When connecting with another TRR mode, we enforce a separate connection
+ // hashkey so that we also can trigger a fresh DNS resolver that then
+ // doesn't use TRR as the previous connection might have.
+ mHashKey.AppendLiteral("[TRR:");
+ mHashKey.AppendInt(GetTRRMode());
+ mHashKey.AppendLiteral("]");
+ }
+
+ if (GetIPv4Disabled()) {
+ mHashKey.AppendLiteral("[!v4]");
+ }
+
+ if (GetIPv6Disabled()) {
+ mHashKey.AppendLiteral("[!v6]");
+ }
+
+ if (mProxyInfo) {
+ const nsCString& connectionIsolationKey =
+ mProxyInfo->ConnectionIsolationKey();
+ if (!connectionIsolationKey.IsEmpty()) {
+ mHashKey.AppendLiteral("{CIK ");
+ mHashKey.Append(connectionIsolationKey);
+ mHashKey.AppendLiteral("}");
+ }
+ if (mProxyInfo->Flags() & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
+ mHashKey.AppendLiteral("{TPRH}");
+ }
+ }
+
+ nsAutoCString originAttributes;
+ mOriginAttributes.CreateSuffix(originAttributes);
+ mHashKey.Append(originAttributes);
+}
+
+void nsHttpConnectionInfo::RebuildHashKey() {
+ // Create copies of all properties stored in our hash key.
+ bool isAnonymous = GetAnonymous();
+ bool isPrivate = GetPrivate();
+ bool isInsecureScheme = GetInsecureScheme();
+ bool isNoSpdy = GetNoSpdy();
+ bool isBeConservative = GetBeConservative();
+ bool isAnonymousAllowClientCert = GetAnonymousAllowClientCert();
+ bool isFallback = GetFallbackConnection();
+
+ BuildHashKey();
+
+ // Restore all of those properties.
+ SetAnonymous(isAnonymous);
+ SetPrivate(isPrivate);
+ SetInsecureScheme(isInsecureScheme);
+ SetNoSpdy(isNoSpdy);
+ SetBeConservative(isBeConservative);
+ SetAnonymousAllowClientCert(isAnonymousAllowClientCert);
+ SetFallbackConnection(isFallback);
+}
+
+void nsHttpConnectionInfo::SetOriginServer(const nsACString& host,
+ int32_t port) {
+ mOrigin = host;
+ mOriginPort = port == -1 ? DefaultPort() : port;
+ // Use BuildHashKey() since this can only be called when constructing an
+ // nsHttpConnectionInfo object.
+ MOZ_DIAGNOSTIC_ASSERT(mHashKey.IsEmpty());
+ BuildHashKey();
+}
+
+// Note that this function needs to be synced with
+// nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs to make sure
+// nsHttpConnectionInfo can be serialized/deserialized.
+already_AddRefed<nsHttpConnectionInfo> nsHttpConnectionInfo::Clone() const {
+ RefPtr<nsHttpConnectionInfo> clone;
+ if (mRoutedHost.IsEmpty()) {
+ clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
+ mProxyInfo, mOriginAttributes,
+ mEndToEndSSL, mIsHttp3, mWebTransport);
+ } else {
+ MOZ_ASSERT(mEndToEndSSL);
+ clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
+ mProxyInfo, mOriginAttributes, mRoutedHost,
+ mRoutedPort, mIsHttp3, mWebTransport);
+ }
+
+ // Make sure the anonymous, insecure-scheme, and private flags are transferred
+ clone->SetAnonymous(GetAnonymous());
+ clone->SetPrivate(GetPrivate());
+ clone->SetInsecureScheme(GetInsecureScheme());
+ clone->SetNoSpdy(GetNoSpdy());
+ clone->SetBeConservative(GetBeConservative());
+ clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
+ clone->SetFallbackConnection(GetFallbackConnection());
+ clone->SetTlsFlags(GetTlsFlags());
+ clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
+ clone->SetTRRMode(GetTRRMode());
+ clone->SetIPv4Disabled(GetIPv4Disabled());
+ clone->SetIPv6Disabled(GetIPv6Disabled());
+ clone->SetHasIPHintAddress(HasIPHintAddress());
+ clone->SetEchConfig(GetEchConfig());
+ MOZ_ASSERT(clone->Equals(this));
+
+ return clone.forget();
+}
+
+already_AddRefed<nsHttpConnectionInfo>
+nsHttpConnectionInfo::CloneAndAdoptHTTPSSVCRecord(
+ nsISVCBRecord* aRecord) const {
+ MOZ_ASSERT(aRecord);
+
+ // Get the domain name of this HTTPS RR. This name will be assigned to
+ // mRoutedHost in the new connection info.
+ nsAutoCString name;
+ aRecord->GetName(name);
+
+ // Try to get the port and Alpn. If this record has SvcParamKeyPort defined,
+ // the new port will be used as mRoutedPort.
+ Maybe<uint16_t> port = aRecord->GetPort();
+ Maybe<std::tuple<nsCString, SupportedAlpnRank>> alpn = aRecord->GetAlpn();
+
+ // Let the new conn info learn h3 will be used.
+ bool isHttp3 = alpn ? mozilla::net::IsHttp3(std::get<1>(*alpn)) : false;
+
+ LOG(("HTTPSSVC: use new routed host (%s) and new npnToken (%s)", name.get(),
+ alpn ? std::get<0>(*alpn).get() : "None"));
+
+ RefPtr<nsHttpConnectionInfo> clone;
+ if (name.IsEmpty()) {
+ clone = new nsHttpConnectionInfo(
+ mOrigin, mOriginPort, alpn ? std::get<0>(*alpn) : EmptyCString(),
+ mUsername, mProxyInfo, mOriginAttributes, mEndToEndSSL, isHttp3);
+ } else {
+ MOZ_ASSERT(mEndToEndSSL);
+ clone = new nsHttpConnectionInfo(
+ mOrigin, mOriginPort, alpn ? std::get<0>(*alpn) : EmptyCString(),
+ mUsername, mProxyInfo, mOriginAttributes, name,
+ port ? *port : mOriginPort, isHttp3, mWebTransport);
+ }
+
+ // Make sure the anonymous, insecure-scheme, and private flags are transferred
+ clone->SetAnonymous(GetAnonymous());
+ clone->SetPrivate(GetPrivate());
+ clone->SetInsecureScheme(GetInsecureScheme());
+ clone->SetNoSpdy(GetNoSpdy());
+ clone->SetBeConservative(GetBeConservative());
+ clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
+ clone->SetFallbackConnection(GetFallbackConnection());
+ clone->SetTlsFlags(GetTlsFlags());
+ clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
+ clone->SetTRRMode(GetTRRMode());
+ clone->SetIPv4Disabled(GetIPv4Disabled());
+ clone->SetIPv6Disabled(GetIPv6Disabled());
+
+ bool hasIPHint = false;
+ Unused << aRecord->GetHasIPHintAddress(&hasIPHint);
+ if (hasIPHint) {
+ clone->SetHasIPHintAddress(hasIPHint);
+ }
+
+ nsAutoCString echConfig;
+ Unused << aRecord->GetEchConfig(echConfig);
+ clone->SetEchConfig(echConfig);
+
+ return clone.forget();
+}
+
+/* static */
+void nsHttpConnectionInfo::SerializeHttpConnectionInfo(
+ nsHttpConnectionInfo* aInfo, HttpConnectionInfoCloneArgs& aArgs) {
+ aArgs.host() = aInfo->GetOrigin();
+ aArgs.port() = aInfo->OriginPort();
+ aArgs.npnToken() = aInfo->GetNPNToken();
+ aArgs.username() = aInfo->GetUsername();
+ aArgs.originAttributes() = aInfo->GetOriginAttributes();
+ aArgs.endToEndSSL() = aInfo->EndToEndSSL();
+ aArgs.routedHost() = aInfo->GetRoutedHost();
+ aArgs.routedPort() = aInfo->RoutedPort();
+ aArgs.anonymous() = aInfo->GetAnonymous();
+ aArgs.aPrivate() = aInfo->GetPrivate();
+ aArgs.insecureScheme() = aInfo->GetInsecureScheme();
+ aArgs.noSpdy() = aInfo->GetNoSpdy();
+ aArgs.beConservative() = aInfo->GetBeConservative();
+ aArgs.anonymousAllowClientCert() = aInfo->GetAnonymousAllowClientCert();
+ aArgs.tlsFlags() = aInfo->GetTlsFlags();
+ aArgs.isTrrServiceChannel() = aInfo->GetTRRMode();
+ aArgs.trrMode() = aInfo->GetTRRMode();
+ aArgs.isIPv4Disabled() = aInfo->GetIPv4Disabled();
+ aArgs.isIPv6Disabled() = aInfo->GetIPv6Disabled();
+ aArgs.isHttp3() = aInfo->IsHttp3();
+ aArgs.hasIPHintAddress() = aInfo->HasIPHintAddress();
+ aArgs.echConfig() = aInfo->GetEchConfig();
+ aArgs.webTransport() = aInfo->GetWebTransport();
+
+ if (!aInfo->ProxyInfo()) {
+ return;
+ }
+
+ nsTArray<ProxyInfoCloneArgs> proxyInfoArray;
+ nsProxyInfo::SerializeProxyInfo(aInfo->ProxyInfo(), proxyInfoArray);
+ aArgs.proxyInfo() = std::move(proxyInfoArray);
+}
+
+// This function needs to be synced with nsHttpConnectionInfo::Clone.
+/* static */
+already_AddRefed<nsHttpConnectionInfo>
+nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs(
+ const HttpConnectionInfoCloneArgs& aInfoArgs) {
+ nsProxyInfo* pi = nsProxyInfo::DeserializeProxyInfo(aInfoArgs.proxyInfo());
+ RefPtr<nsHttpConnectionInfo> cinfo;
+ if (aInfoArgs.routedHost().IsEmpty()) {
+ cinfo = new nsHttpConnectionInfo(
+ aInfoArgs.host(), aInfoArgs.port(), aInfoArgs.npnToken(),
+ aInfoArgs.username(), pi, aInfoArgs.originAttributes(),
+ aInfoArgs.endToEndSSL(), aInfoArgs.isHttp3(), aInfoArgs.webTransport());
+ } else {
+ MOZ_ASSERT(aInfoArgs.endToEndSSL());
+ cinfo = new nsHttpConnectionInfo(
+ aInfoArgs.host(), aInfoArgs.port(), aInfoArgs.npnToken(),
+ aInfoArgs.username(), pi, aInfoArgs.originAttributes(),
+ aInfoArgs.routedHost(), aInfoArgs.routedPort(), aInfoArgs.isHttp3(),
+ aInfoArgs.webTransport());
+ }
+
+ // Make sure the anonymous, insecure-scheme, and private flags are transferred
+ cinfo->SetAnonymous(aInfoArgs.anonymous());
+ cinfo->SetPrivate(aInfoArgs.aPrivate());
+ cinfo->SetInsecureScheme(aInfoArgs.insecureScheme());
+ cinfo->SetNoSpdy(aInfoArgs.noSpdy());
+ cinfo->SetBeConservative(aInfoArgs.beConservative());
+ cinfo->SetAnonymousAllowClientCert(aInfoArgs.anonymousAllowClientCert());
+ cinfo->SetFallbackConnection(aInfoArgs.fallbackConnection());
+ cinfo->SetTlsFlags(aInfoArgs.tlsFlags());
+ cinfo->SetIsTrrServiceChannel(aInfoArgs.isTrrServiceChannel());
+ cinfo->SetTRRMode(static_cast<nsIRequest::TRRMode>(aInfoArgs.trrMode()));
+ cinfo->SetIPv4Disabled(aInfoArgs.isIPv4Disabled());
+ cinfo->SetIPv6Disabled(aInfoArgs.isIPv6Disabled());
+ cinfo->SetHasIPHintAddress(aInfoArgs.hasIPHintAddress());
+ cinfo->SetEchConfig(aInfoArgs.echConfig());
+
+ return cinfo.forget();
+}
+
+void nsHttpConnectionInfo::CloneAsDirectRoute(nsHttpConnectionInfo** outCI) {
+ // Explicitly use an empty npnToken when |mIsHttp3| is true, since we want to
+ // create a non-http3 connection info.
+ RefPtr<nsHttpConnectionInfo> clone = new nsHttpConnectionInfo(
+ mOrigin, mOriginPort,
+ (mRoutedHost.IsEmpty() && !mIsHttp3) ? mNPNToken : ""_ns, mUsername,
+ mProxyInfo, mOriginAttributes, mEndToEndSSL, false, mWebTransport);
+ // Make sure the anonymous, insecure-scheme, and private flags are transferred
+ clone->SetAnonymous(GetAnonymous());
+ clone->SetPrivate(GetPrivate());
+ clone->SetInsecureScheme(GetInsecureScheme());
+ clone->SetNoSpdy(GetNoSpdy());
+ clone->SetBeConservative(GetBeConservative());
+ clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
+ clone->SetFallbackConnection(GetFallbackConnection());
+ clone->SetTlsFlags(GetTlsFlags());
+ clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
+ clone->SetTRRMode(GetTRRMode());
+ clone->SetIPv4Disabled(GetIPv4Disabled());
+ clone->SetIPv6Disabled(GetIPv6Disabled());
+ clone->SetHasIPHintAddress(HasIPHintAddress());
+ clone->SetEchConfig(GetEchConfig());
+
+ clone.forget(outCI);
+}
+
+nsresult nsHttpConnectionInfo::CreateWildCard(nsHttpConnectionInfo** outParam) {
+ // T???mozilla.org:443 (https:proxy.ducksong.com:3128) [specifc form]
+ // TS??*:0 (https:proxy.ducksong.com:3128) [wildcard form]
+
+ if (!mUsingHttpsProxy) {
+ MOZ_ASSERT(false);
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ RefPtr<nsHttpConnectionInfo> clone;
+ clone = new nsHttpConnectionInfo("*"_ns, 0, mNPNToken, mUsername, mProxyInfo,
+ mOriginAttributes, true, mIsHttp3,
+ mWebTransport);
+ // Make sure the anonymous and private flags are transferred!
+ clone->SetAnonymous(GetAnonymous());
+ clone->SetPrivate(GetPrivate());
+ clone.forget(outParam);
+ return NS_OK;
+}
+
+void nsHttpConnectionInfo::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
+ if (mTRRMode != aTRRMode) {
+ mTRRMode = aTRRMode;
+ RebuildHashKey();
+ }
+}
+
+void nsHttpConnectionInfo::SetIPv4Disabled(bool aNoIPv4) {
+ if (mIPv4Disabled != aNoIPv4) {
+ mIPv4Disabled = aNoIPv4;
+ RebuildHashKey();
+ }
+}
+
+void nsHttpConnectionInfo::SetIPv6Disabled(bool aNoIPv6) {
+ if (mIPv6Disabled != aNoIPv6) {
+ mIPv6Disabled = aNoIPv6;
+ RebuildHashKey();
+ }
+}
+
+void nsHttpConnectionInfo::SetWebTransport(bool aWebTransport) {
+ if (mWebTransport != aWebTransport) {
+ mWebTransport = aWebTransport;
+ RebuildHashKey();
+ }
+}
+
+void nsHttpConnectionInfo::SetTlsFlags(uint32_t aTlsFlags) {
+ mTlsFlags = aTlsFlags;
+ const uint32_t tlsFlagsLength = 8;
+ const uint32_t tlsFlagsIndex =
+ UnderlyingIndex(HashKeyIndex::End) + strlen("[tlsflags0x");
+ mHashKey.Replace(tlsFlagsIndex, tlsFlagsLength,
+ nsPrintfCString("%08x", mTlsFlags));
+}
+
+bool nsHttpConnectionInfo::UsingProxy() {
+ if (!mProxyInfo) return false;
+ return !mProxyInfo->IsDirect();
+}
+
+bool nsHttpConnectionInfo::HostIsLocalIPLiteral() const {
+ NetAddr netAddr;
+ // If the host/proxy host is not an IP address literal, return false.
+ nsAutoCString host(ProxyHost() ? ProxyHost() : Origin());
+ if (NS_FAILED(netAddr.InitFromString(host))) {
+ return false;
+ }
+ return netAddr.IsIPAddrLocal();
+}
+
+} // namespace net
+} // namespace mozilla