tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsHttpConnectionInfo.cpp (22941B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set sw=2 ts=8 et tw=80 : */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // HttpLog.h should generally be included first
      8 #include "HttpLog.h"
      9 
     10 // Log on level :5, instead of default :4.
     11 #undef LOG
     12 #define LOG(args) LOG5(args)
     13 #undef LOG_ENABLED
     14 #define LOG_ENABLED() LOG5_ENABLED()
     15 
     16 #include "nsHttpConnectionInfo.h"
     17 
     18 #include "mozilla/net/DNS.h"
     19 #include "mozilla/net/NeckoChannelParams.h"
     20 #include "nsComponentManagerUtils.h"
     21 #include "nsICryptoHash.h"
     22 #include "nsIDNSByTypeRecord.h"
     23 #include "nsIProtocolProxyService.h"
     24 #include "nsHttpHandler.h"
     25 #include "nsNetCID.h"
     26 #include "nsProxyInfo.h"
     27 #include "prnetdb.h"
     28 
     29 static nsresult SHA256(const char* aPlainText, nsAutoCString& aResult) {
     30  nsresult rv;
     31  nsCOMPtr<nsICryptoHash> hasher =
     32      do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
     33  if (NS_FAILED(rv)) {
     34    LOG(("nsHttpDigestAuth: no crypto hash!\n"));
     35    return rv;
     36  }
     37  rv = hasher->Init(nsICryptoHash::SHA256);
     38  NS_ENSURE_SUCCESS(rv, rv);
     39  rv = hasher->Update((unsigned char*)aPlainText, strlen(aPlainText));
     40  NS_ENSURE_SUCCESS(rv, rv);
     41  return hasher->Finish(false, aResult);
     42 }
     43 
     44 namespace mozilla {
     45 namespace net {
     46 
     47 nsHttpConnectionInfo::nsHttpConnectionInfo(
     48    const nsACString& originHost, int32_t originPort,
     49    const nsACString& npnToken, const nsACString& username,
     50    nsProxyInfo* proxyInfo, const OriginAttributes& originAttributes,
     51    bool endToEndSSL, bool aIsHttp3, bool aWebTransport)
     52    : mRoutedPort(443), mLessThanTls13(false) {
     53  Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes,
     54       endToEndSSL, aIsHttp3, aWebTransport);
     55 }
     56 
     57 nsHttpConnectionInfo::nsHttpConnectionInfo(
     58    const nsACString& originHost, int32_t originPort,
     59    const nsACString& npnToken, const nsACString& username,
     60    nsProxyInfo* proxyInfo, const OriginAttributes& originAttributes,
     61    const nsACString& routedHost, int32_t routedPort, bool aIsHttp3,
     62    bool aWebTransport)
     63    : mLessThanTls13(false) {
     64  mEndToEndSSL = true;  // so DefaultPort() works
     65  mRoutedPort = routedPort == -1 ? DefaultPort() : routedPort;
     66 
     67  if (!originHost.Equals(routedHost) || (originPort != routedPort) ||
     68      aIsHttp3) {
     69    mRoutedHost = routedHost;
     70  }
     71  Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes,
     72       true, aIsHttp3, aWebTransport);
     73 }
     74 
     75 // static
     76 uint64_t nsHttpConnectionInfo::GenerateNewWebTransportId() {
     77  // Used for generating unique IDSs for dedicated connections, currently used
     78  // by WebTransport
     79  MOZ_ASSERT(XRE_IsParentProcess());
     80  static Atomic<uint64_t> id(0);
     81  return ++id;
     82 }
     83 
     84 void nsHttpConnectionInfo::Init(const nsACString& host, int32_t port,
     85                                const nsACString& npnToken,
     86                                const nsACString& username,
     87                                nsProxyInfo* proxyInfo,
     88                                const OriginAttributes& originAttributes,
     89                                bool e2eSSL, bool aIsHttp3,
     90                                bool aWebTransport) {
     91  LOG(("Init nsHttpConnectionInfo @%p\n", this));
     92 
     93  mUsername = username;
     94  mProxyInfo = proxyInfo;
     95  mEndToEndSSL = e2eSSL;
     96  mUsingConnect = false;
     97  mNPNToken = npnToken;
     98  mIsHttp3 = aIsHttp3;
     99  mWebTransport = aWebTransport;
    100  mOriginAttributes = originAttributes;
    101  mTlsFlags = 0x0;
    102  mIsTrrServiceChannel = false;
    103  mTRRMode = nsIRequest::TRR_DEFAULT_MODE;
    104  mIPv4Disabled = false;
    105  mIPv6Disabled = false;
    106  mHasIPHintAddress = false;
    107 
    108  mUsingHttpsProxy = (proxyInfo && proxyInfo->IsHTTPS());
    109  mUsingHttpProxy = mUsingHttpsProxy || (proxyInfo && proxyInfo->IsHTTP());
    110 
    111  if (mUsingHttpProxy) {
    112    mUsingConnect = mEndToEndSSL || proxyInfo->IsHttp3Proxy();
    113    if (!mUsingConnect) {
    114      uint32_t resolveFlags = 0;
    115      if (NS_SUCCEEDED(mProxyInfo->GetResolveFlags(&resolveFlags)) &&
    116          resolveFlags & nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL) {
    117        mUsingConnect = true;
    118      }
    119    }
    120  }
    121 
    122  if (mUsingHttpsProxy) {
    123    mIsHttp3ProxyConnection = "masque"_ns.Equals(proxyInfo->Type());
    124    if (mIsHttp3ProxyConnection) {
    125      mProxyNPNToken = "h3"_ns;
    126    }
    127  }
    128 
    129  SetOriginServer(host, port);
    130 }
    131 
    132 void nsHttpConnectionInfo::BuildHashKey() {
    133  //
    134  // build hash key:
    135  //
    136  // the hash key uniquely identifies the connection type.  two connections
    137  // are "equal" if they end up talking the same protocol to the same server
    138  // and are both used for anonymous or non-anonymous connection only;
    139  // anonymity of the connection is setup later from nsHttpChannel::AsyncOpen
    140  // where we know we use anonymous connection (LOAD_ANONYMOUS load flag)
    141  //
    142 
    143  const char* keyHost;
    144  int32_t keyPort;
    145 
    146  if (mUsingHttpProxy && !mUsingConnect) {
    147    keyHost = ProxyHost();
    148    keyPort = ProxyPort();
    149  } else {
    150    keyHost = Origin();
    151    keyPort = OriginPort();
    152  }
    153 
    154  // The hashkey has 9 fields followed by host connection info
    155  // byte 0 is P/T/. {P,T} for Plaintext/TLS Proxy over HTTP
    156  // byte 1 is S/. S is for end to end ssl such as https:// uris
    157  // byte 2 is A/. A is for an anonymous channel (no cookies, etc..)
    158  // byte 3 is P/. P is for a private browising channel
    159  // byte 4 is I/. I is for insecure scheme on TLS for http:// uris
    160  // byte 5 is X/. X is for disallow_spdy flag
    161  // byte 6 is C/. C is for be Conservative
    162  // byte 7 is B/. B is for allowing client certs on an anonymous channel
    163  // byte 8 is F/. F is for indicating a fallback connection
    164  // byte 9 is W/. W is for indicating a webTransport
    165  // Note: when adding/removing fields from this list which do not have
    166  // corresponding data fields on the object itself, you may also need to
    167  // modify RebuildHashKey.
    168 
    169  const auto keyTemplate =
    170      std::string(UnderlyingIndex(HashKeyIndex::End), '.') +
    171      std::string("[tlsflags0x00000000]");
    172  mHashKey.Assign(keyTemplate.c_str());
    173 
    174  mHashKey.Append(keyHost);
    175  mHashKey.Append(':');
    176  mHashKey.AppendInt(keyPort);
    177  if (!mUsername.IsEmpty()) {
    178    mHashKey.Append('[');
    179    mHashKey.Append(mUsername);
    180    mHashKey.Append(']');
    181  }
    182 
    183  if (mUsingHttpsProxy) {
    184    SetHashCharAt('T', HashKeyIndex::Proxy);
    185  } else if (mUsingHttpProxy) {
    186    SetHashCharAt('P', HashKeyIndex::Proxy);
    187  }
    188  if (mEndToEndSSL) {
    189    SetHashCharAt('S', HashKeyIndex::EndToEndSSL);
    190  }
    191 
    192  if (mWebTransport) {
    193    SetHashCharAt('W', HashKeyIndex::WebTransport);
    194  }
    195 
    196  // NOTE: for transparent proxies (e.g., SOCKS) we need to encode the proxy
    197  // info in the hash key (this ensures that we will continue to speak the
    198  // right protocol even if our proxy preferences change).
    199  //
    200  // NOTE: for SSL tunnels add the proxy information to the cache key.
    201  // We cannot use the proxy as the host parameter (as we do for non SSL)
    202  // because this is a single host tunnel, but we need to include the proxy
    203  // information so that a change in proxy config will mean this connection
    204  // is not reused
    205 
    206  // NOTE: Adding the username and the password provides a means to isolate
    207  // keep-alive to the URL bar domain as well: If the username is the URL bar
    208  // domain, keep-alive connections are not reused by resources bound to
    209  // different URL bar domains as the respective hash keys are not matching.
    210 
    211  if ((!mUsingHttpProxy && ProxyHost()) || (mUsingHttpProxy && mUsingConnect)) {
    212    mHashKey.AppendLiteral(" (");
    213    mHashKey.Append(ProxyType());
    214    mHashKey.Append(':');
    215    mHashKey.Append(ProxyHost());
    216    mHashKey.Append(':');
    217    mHashKey.AppendInt(ProxyPort());
    218    mHashKey.Append(')');
    219    mHashKey.Append('[');
    220    mHashKey.Append(ProxyUsername());
    221    mHashKey.Append(':');
    222    const char* password = ProxyPassword();
    223    if (strlen(password) > 0) {
    224      nsAutoCString digestedPassword;
    225      nsresult rv = SHA256(password, digestedPassword);
    226      if (rv == NS_OK) {
    227        mHashKey.Append(digestedPassword);
    228      }
    229    }
    230    mHashKey.Append(']');
    231  }
    232 
    233  if (!mRoutedHost.IsEmpty()) {
    234    mHashKey.AppendLiteral(" <ROUTE-via ");
    235    mHashKey.Append(mRoutedHost);
    236    mHashKey.Append(':');
    237    mHashKey.AppendInt(mRoutedPort);
    238    mHashKey.Append('>');
    239  }
    240 
    241  if (!mNPNToken.IsEmpty()) {
    242    mHashKey.AppendLiteral(" {NPN-TOKEN ");
    243    mHashKey.Append(mNPNToken);
    244    mHashKey.AppendLiteral("}");
    245  }
    246 
    247  if (GetTRRMode() != nsIRequest::TRR_DEFAULT_MODE) {
    248    // When connecting with another TRR mode, we enforce a separate connection
    249    // hashkey so that we also can trigger a fresh DNS resolver that then
    250    // doesn't use TRR as the previous connection might have.
    251    mHashKey.AppendLiteral("[TRR:");
    252    mHashKey.AppendInt(GetTRRMode());
    253    mHashKey.AppendLiteral("]");
    254  }
    255 
    256  if (GetIPv4Disabled()) {
    257    mHashKey.AppendLiteral("[!v4]");
    258  }
    259 
    260  if (GetIPv6Disabled()) {
    261    mHashKey.AppendLiteral("[!v6]");
    262  }
    263 
    264  if (mProxyInfo) {
    265    const nsCString& connectionIsolationKey =
    266        mProxyInfo->ConnectionIsolationKey();
    267    if (!connectionIsolationKey.IsEmpty()) {
    268      mHashKey.AppendLiteral("{CIK ");
    269      mHashKey.Append(connectionIsolationKey);
    270      mHashKey.AppendLiteral("}");
    271    }
    272    if (mProxyInfo->Flags() & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
    273      mHashKey.AppendLiteral("{TPRH}");
    274    }
    275  }
    276 
    277  if (mWebTransportId) {
    278    mHashKey.AppendLiteral("{wId");
    279    mHashKey.AppendInt(mWebTransportId, 16);
    280    mHashKey.AppendLiteral("}");
    281  }
    282 
    283  nsAutoCString originAttributes;
    284  mOriginAttributes.CreateSuffix(originAttributes);
    285  mHashKey.Append(originAttributes);
    286 }
    287 
    288 void nsHttpConnectionInfo::RebuildHashKey() {
    289  // Create copies of all properties stored in our hash key.
    290  bool isAnonymous = GetAnonymous();
    291  bool isPrivate = GetPrivate();
    292  bool isInsecureScheme = GetInsecureScheme();
    293  bool isNoSpdy = GetNoSpdy();
    294  bool isBeConservative = GetBeConservative();
    295  bool isAnonymousAllowClientCert = GetAnonymousAllowClientCert();
    296  bool isFallback = GetFallbackConnection();
    297 
    298  BuildHashKey();
    299 
    300  // Restore all of those properties.
    301  SetAnonymous(isAnonymous);
    302  SetPrivate(isPrivate);
    303  SetInsecureScheme(isInsecureScheme);
    304  SetNoSpdy(isNoSpdy);
    305  SetBeConservative(isBeConservative);
    306  SetAnonymousAllowClientCert(isAnonymousAllowClientCert);
    307  SetFallbackConnection(isFallback);
    308  SetTlsFlags(mTlsFlags);
    309 }
    310 
    311 void nsHttpConnectionInfo::SetOriginServer(const nsACString& host,
    312                                           int32_t port) {
    313  mOrigin = host;
    314  mOriginPort = port == -1 ? DefaultPort() : port;
    315  // Use BuildHashKey() since this can only be called when constructing an
    316  // nsHttpConnectionInfo object.
    317  MOZ_DIAGNOSTIC_ASSERT(mHashKey.IsEmpty());
    318  BuildHashKey();
    319 }
    320 
    321 // Note that this function needs to be synced with
    322 // nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs to make sure
    323 // nsHttpConnectionInfo can be serialized/deserialized.
    324 already_AddRefed<nsHttpConnectionInfo> nsHttpConnectionInfo::Clone() const {
    325  RefPtr<nsHttpConnectionInfo> clone;
    326  if (mRoutedHost.IsEmpty()) {
    327    clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
    328                                     mProxyInfo, mOriginAttributes,
    329                                     mEndToEndSSL, mIsHttp3, mWebTransport);
    330  } else {
    331    MOZ_ASSERT(mEndToEndSSL);
    332    clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
    333                                     mProxyInfo, mOriginAttributes, mRoutedHost,
    334                                     mRoutedPort, mIsHttp3, mWebTransport);
    335  }
    336 
    337  // Make sure the anonymous, insecure-scheme, and private flags are transferred
    338  clone->SetAnonymous(GetAnonymous());
    339  clone->SetPrivate(GetPrivate());
    340  clone->SetInsecureScheme(GetInsecureScheme());
    341  clone->SetNoSpdy(GetNoSpdy());
    342  clone->SetBeConservative(GetBeConservative());
    343  clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
    344  clone->SetFallbackConnection(GetFallbackConnection());
    345  clone->SetTlsFlags(GetTlsFlags());
    346  clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
    347  clone->SetTRRMode(GetTRRMode());
    348  clone->SetIPv4Disabled(GetIPv4Disabled());
    349  clone->SetIPv6Disabled(GetIPv6Disabled());
    350  clone->SetHasIPHintAddress(HasIPHintAddress());
    351  clone->SetEchConfig(GetEchConfig());
    352  clone->SetWebTransportId(GetWebTransportId());
    353  MOZ_ASSERT(clone->Equals(this));
    354 
    355  return clone.forget();
    356 }
    357 
    358 already_AddRefed<nsHttpConnectionInfo>
    359 nsHttpConnectionInfo::CloneAndAdoptHTTPSSVCRecord(
    360    nsISVCBRecord* aRecord) const {
    361  MOZ_ASSERT(aRecord);
    362 
    363  // Get the domain name of this HTTPS RR. This name will be assigned to
    364  // mRoutedHost in the new connection info.
    365  nsAutoCString name;
    366  aRecord->GetName(name);
    367 
    368  // Try to get the port and Alpn. If this record has SvcParamKeyPort defined,
    369  // the new port will be used as mRoutedPort.
    370  Maybe<uint16_t> port = aRecord->GetPort();
    371  Maybe<std::tuple<nsCString, SupportedAlpnRank>> alpn = aRecord->GetAlpn();
    372 
    373  // Let the new conn info learn h3 will be used.
    374  bool isHttp3 = alpn ? mozilla::net::IsHttp3(std::get<1>(*alpn)) : false;
    375 
    376  LOG(("HTTPSSVC: use new routed host (%s) and new npnToken (%s)", name.get(),
    377       alpn ? std::get<0>(*alpn).get() : "None"));
    378 
    379  RefPtr<nsHttpConnectionInfo> clone;
    380  if (name.IsEmpty()) {
    381    clone = new nsHttpConnectionInfo(
    382        mOrigin, mOriginPort, alpn ? std::get<0>(*alpn) : EmptyCString(),
    383        mUsername, mProxyInfo, mOriginAttributes, mEndToEndSSL, isHttp3);
    384  } else {
    385    MOZ_ASSERT(mEndToEndSSL);
    386    clone = new nsHttpConnectionInfo(
    387        mOrigin, mOriginPort, alpn ? std::get<0>(*alpn) : EmptyCString(),
    388        mUsername, mProxyInfo, mOriginAttributes, name,
    389        port ? *port : mOriginPort, isHttp3, mWebTransport);
    390  }
    391 
    392  // Make sure the anonymous, insecure-scheme, and private flags are transferred
    393  clone->SetAnonymous(GetAnonymous());
    394  clone->SetPrivate(GetPrivate());
    395  clone->SetInsecureScheme(GetInsecureScheme());
    396  clone->SetNoSpdy(GetNoSpdy());
    397  clone->SetBeConservative(GetBeConservative());
    398  clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
    399  clone->SetFallbackConnection(GetFallbackConnection());
    400  clone->SetTlsFlags(GetTlsFlags());
    401  clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
    402  clone->SetTRRMode(GetTRRMode());
    403  clone->SetIPv4Disabled(GetIPv4Disabled());
    404  clone->SetIPv6Disabled(GetIPv6Disabled());
    405 
    406  bool hasIPHint = false;
    407  (void)aRecord->GetHasIPHintAddress(&hasIPHint);
    408  if (hasIPHint) {
    409    clone->SetHasIPHintAddress(hasIPHint);
    410  }
    411 
    412  nsAutoCString echConfig;
    413  (void)aRecord->GetEchConfig(echConfig);
    414  clone->SetEchConfig(echConfig);
    415 
    416  return clone.forget();
    417 }
    418 
    419 /* static */
    420 void nsHttpConnectionInfo::SerializeHttpConnectionInfo(
    421    nsHttpConnectionInfo* aInfo, HttpConnectionInfoCloneArgs& aArgs) {
    422  aArgs.host() = aInfo->GetOrigin();
    423  aArgs.port() = aInfo->OriginPort();
    424  aArgs.npnToken() = aInfo->GetNPNToken();
    425  aArgs.username() = aInfo->GetUsername();
    426  aArgs.originAttributes() = aInfo->GetOriginAttributes();
    427  aArgs.endToEndSSL() = aInfo->EndToEndSSL();
    428  aArgs.routedHost() = aInfo->GetRoutedHost();
    429  aArgs.routedPort() = aInfo->RoutedPort();
    430  aArgs.anonymous() = aInfo->GetAnonymous();
    431  aArgs.aPrivate() = aInfo->GetPrivate();
    432  aArgs.insecureScheme() = aInfo->GetInsecureScheme();
    433  aArgs.noSpdy() = aInfo->GetNoSpdy();
    434  aArgs.beConservative() = aInfo->GetBeConservative();
    435  aArgs.anonymousAllowClientCert() = aInfo->GetAnonymousAllowClientCert();
    436  aArgs.tlsFlags() = aInfo->GetTlsFlags();
    437  aArgs.isTrrServiceChannel() = aInfo->GetTRRMode();
    438  aArgs.trrMode() = aInfo->GetTRRMode();
    439  aArgs.isIPv4Disabled() = aInfo->GetIPv4Disabled();
    440  aArgs.isIPv6Disabled() = aInfo->GetIPv6Disabled();
    441  aArgs.isHttp3() = aInfo->IsHttp3();
    442  aArgs.hasIPHintAddress() = aInfo->HasIPHintAddress();
    443  aArgs.echConfig() = aInfo->GetEchConfig();
    444  aArgs.webTransport() = aInfo->GetWebTransport();
    445  aArgs.webTransportId() = aInfo->GetWebTransportId();
    446 
    447  if (!aInfo->ProxyInfo()) {
    448    return;
    449  }
    450 
    451  nsTArray<ProxyInfoCloneArgs> proxyInfoArray;
    452  nsProxyInfo::SerializeProxyInfo(aInfo->ProxyInfo(), proxyInfoArray);
    453  aArgs.proxyInfo() = std::move(proxyInfoArray);
    454 }
    455 
    456 // This function needs to be synced with nsHttpConnectionInfo::Clone.
    457 /* static */
    458 already_AddRefed<nsHttpConnectionInfo>
    459 nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs(
    460    const HttpConnectionInfoCloneArgs& aInfoArgs) {
    461  nsProxyInfo* pi = nsProxyInfo::DeserializeProxyInfo(aInfoArgs.proxyInfo());
    462  RefPtr<nsHttpConnectionInfo> cinfo;
    463  if (aInfoArgs.routedHost().IsEmpty()) {
    464    cinfo = new nsHttpConnectionInfo(
    465        aInfoArgs.host(), aInfoArgs.port(), aInfoArgs.npnToken(),
    466        aInfoArgs.username(), pi, aInfoArgs.originAttributes(),
    467        aInfoArgs.endToEndSSL(), aInfoArgs.isHttp3(), aInfoArgs.webTransport());
    468  } else {
    469    MOZ_ASSERT(aInfoArgs.endToEndSSL());
    470    cinfo = new nsHttpConnectionInfo(
    471        aInfoArgs.host(), aInfoArgs.port(), aInfoArgs.npnToken(),
    472        aInfoArgs.username(), pi, aInfoArgs.originAttributes(),
    473        aInfoArgs.routedHost(), aInfoArgs.routedPort(), aInfoArgs.isHttp3(),
    474        aInfoArgs.webTransport());
    475  }
    476  // Transfer Webtransport ids
    477  cinfo->SetWebTransportId(aInfoArgs.webTransportId());
    478 
    479  // Make sure the anonymous, insecure-scheme, and private flags are transferred
    480  cinfo->SetAnonymous(aInfoArgs.anonymous());
    481  cinfo->SetPrivate(aInfoArgs.aPrivate());
    482  cinfo->SetInsecureScheme(aInfoArgs.insecureScheme());
    483  cinfo->SetNoSpdy(aInfoArgs.noSpdy());
    484  cinfo->SetBeConservative(aInfoArgs.beConservative());
    485  cinfo->SetAnonymousAllowClientCert(aInfoArgs.anonymousAllowClientCert());
    486  cinfo->SetFallbackConnection(aInfoArgs.fallbackConnection());
    487  cinfo->SetTlsFlags(aInfoArgs.tlsFlags());
    488  cinfo->SetIsTrrServiceChannel(aInfoArgs.isTrrServiceChannel());
    489  cinfo->SetTRRMode(static_cast<nsIRequest::TRRMode>(aInfoArgs.trrMode()));
    490  cinfo->SetIPv4Disabled(aInfoArgs.isIPv4Disabled());
    491  cinfo->SetIPv6Disabled(aInfoArgs.isIPv6Disabled());
    492  cinfo->SetHasIPHintAddress(aInfoArgs.hasIPHintAddress());
    493  cinfo->SetEchConfig(aInfoArgs.echConfig());
    494 
    495  return cinfo.forget();
    496 }
    497 
    498 void nsHttpConnectionInfo::CloneAsDirectRoute(nsHttpConnectionInfo** outCI,
    499                                              nsProxyInfo* aProxyInfo) {
    500  // Explicitly use an empty npnToken when |mIsHttp3| is true, since we want to
    501  // create a non-http3 connection info.
    502  RefPtr<nsHttpConnectionInfo> clone = new nsHttpConnectionInfo(
    503      mOrigin, mOriginPort,
    504      (mRoutedHost.IsEmpty() && !mIsHttp3) ? mNPNToken : ""_ns, mUsername,
    505      aProxyInfo ? aProxyInfo : mProxyInfo.get(), mOriginAttributes,
    506      mEndToEndSSL, false, mWebTransport);
    507  // Make sure the anonymous, insecure-scheme, and private flags are transferred
    508  clone->SetAnonymous(GetAnonymous());
    509  clone->SetPrivate(GetPrivate());
    510  clone->SetInsecureScheme(GetInsecureScheme());
    511  clone->SetNoSpdy(GetNoSpdy());
    512  clone->SetBeConservative(GetBeConservative());
    513  clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
    514  clone->SetFallbackConnection(GetFallbackConnection());
    515  clone->SetTlsFlags(GetTlsFlags());
    516  clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
    517  clone->SetTRRMode(GetTRRMode());
    518  clone->SetIPv4Disabled(GetIPv4Disabled());
    519  clone->SetIPv6Disabled(GetIPv6Disabled());
    520  clone->SetHasIPHintAddress(HasIPHintAddress());
    521  clone->SetEchConfig(GetEchConfig());
    522 
    523  clone.forget(outCI);
    524 }
    525 
    526 already_AddRefed<nsHttpConnectionInfo>
    527 nsHttpConnectionInfo::CreateConnectUDPFallbackConnInfo() {
    528  if (!mProxyInfo || !mProxyInfo->IsHttp3Proxy()) {
    529    return nullptr;
    530  }
    531 
    532  RefPtr<nsProxyInfo> proxyInfo = mProxyInfo->CreateFallbackProxyInfo();
    533  RefPtr<nsHttpConnectionInfo> clone;
    534  CloneAsDirectRoute(getter_AddRefs(clone), proxyInfo);
    535  return clone.forget();
    536 }
    537 
    538 nsresult nsHttpConnectionInfo::CreateWildCard(nsHttpConnectionInfo** outParam) {
    539  // T???mozilla.org:443 (https:proxy.ducksong.com:3128) [specifc form]
    540  // TS??*:0 (https:proxy.ducksong.com:3128)   [wildcard form]
    541 
    542  if (!mUsingHttpsProxy) {
    543    MOZ_ASSERT(false);
    544    return NS_ERROR_NOT_IMPLEMENTED;
    545  }
    546 
    547  RefPtr<nsHttpConnectionInfo> clone;
    548  clone = new nsHttpConnectionInfo("*"_ns, 0, mNPNToken, mUsername, mProxyInfo,
    549                                   mOriginAttributes, true, mIsHttp3,
    550                                   mWebTransport);
    551  // Make sure the anonymous and private flags are transferred!
    552  clone->SetAnonymous(GetAnonymous());
    553  clone->SetPrivate(GetPrivate());
    554  clone->SetFallbackConnection(GetFallbackConnection());
    555  clone.forget(outParam);
    556  return NS_OK;
    557 }
    558 
    559 void nsHttpConnectionInfo::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
    560  if (mTRRMode != aTRRMode) {
    561    mTRRMode = aTRRMode;
    562    RebuildHashKey();
    563  }
    564 }
    565 
    566 void nsHttpConnectionInfo::SetIPv4Disabled(bool aNoIPv4) {
    567  if (mIPv4Disabled != aNoIPv4) {
    568    mIPv4Disabled = aNoIPv4;
    569    RebuildHashKey();
    570  }
    571 }
    572 
    573 void nsHttpConnectionInfo::SetIPv6Disabled(bool aNoIPv6) {
    574  if (mIPv6Disabled != aNoIPv6) {
    575    mIPv6Disabled = aNoIPv6;
    576    RebuildHashKey();
    577  }
    578 }
    579 
    580 void nsHttpConnectionInfo::SetWebTransport(bool aWebTransport) {
    581  if (mWebTransport != aWebTransport) {
    582    mWebTransport = aWebTransport;
    583    RebuildHashKey();
    584  }
    585 }
    586 
    587 void nsHttpConnectionInfo::SetWebTransportId(uint64_t id) {
    588  if (mWebTransportId != id) {
    589    mWebTransportId = id;
    590    RebuildHashKey();
    591  }
    592 }
    593 
    594 void nsHttpConnectionInfo::SetTlsFlags(uint32_t aTlsFlags) {
    595  mTlsFlags = aTlsFlags;
    596  const uint32_t tlsFlagsLength = 8;
    597  const uint32_t tlsFlagsIndex =
    598      UnderlyingIndex(HashKeyIndex::End) + strlen("[tlsflags0x");
    599  mHashKey.Replace(tlsFlagsIndex, tlsFlagsLength,
    600                   nsPrintfCString("%08x", mTlsFlags));
    601 }
    602 
    603 bool nsHttpConnectionInfo::UsingProxy() {
    604  if (!mProxyInfo) return false;
    605  return !mProxyInfo->IsDirect();
    606 }
    607 
    608 bool nsHttpConnectionInfo::HostIsLocalIPLiteral() const {
    609  NetAddr netAddr;
    610  // If the host/proxy host is not an IP address literal, return false.
    611  nsAutoCString host(ProxyHost() ? ProxyHost() : Origin());
    612  if (NS_FAILED(netAddr.InitFromString(host))) {
    613    return false;
    614  }
    615  return netAddr.IsIPAddrLocal();
    616 }
    617 
    618 // static
    619 void nsHttpConnectionInfo::BuildOriginFrameHashKey(nsACString& newKey,
    620                                                   nsHttpConnectionInfo* ci,
    621                                                   const nsACString& host,
    622                                                   int32_t port) {
    623  newKey.Assign(host);
    624  if (ci->GetAnonymous()) {
    625    newKey.AppendLiteral("~A:");
    626  } else {
    627    newKey.AppendLiteral("~.:");
    628  }
    629  if (ci->GetFallbackConnection()) {
    630    newKey.AppendLiteral("~F:");
    631  } else {
    632    newKey.AppendLiteral("~.:");
    633  }
    634  newKey.AppendInt(port);
    635  newKey.AppendLiteral("/[");
    636  nsAutoCString suffix;
    637  ci->GetOriginAttributes().CreateSuffix(suffix);
    638  newKey.Append(suffix);
    639  newKey.AppendLiteral("]viaORIGIN.FRAME");
    640 }
    641 
    642 }  // namespace net
    643 }  // namespace mozilla