tor-browser

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

HttpConnectionBase.cpp (5585B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=4 sw=2 sts=2 et cin: */
      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 #define TLS_EARLY_DATA_NOT_AVAILABLE 0
     17 #define TLS_EARLY_DATA_AVAILABLE_BUT_NOT_USED 1
     18 #define TLS_EARLY_DATA_AVAILABLE_AND_USED 2
     19 
     20 #include "mozilla/glean/NetwerkProtocolHttpMetrics.h"
     21 #include "HttpConnectionBase.h"
     22 #include "nsHttpHandler.h"
     23 #include "nsIClassOfService.h"
     24 #include "nsIOService.h"
     25 #include "nsISocketTransport.h"
     26 #include "ConnectionEntry.h"
     27 
     28 namespace mozilla {
     29 namespace net {
     30 
     31 //-----------------------------------------------------------------------------
     32 // nsHttpConnection <public>
     33 //-----------------------------------------------------------------------------
     34 
     35 HttpConnectionBase::HttpConnectionBase() {
     36  LOG(("Creating HttpConnectionBase @%p\n", this));
     37 }
     38 
     39 void HttpConnectionBase::BootstrapTimings(TimingStruct times) {
     40  mBootstrappedTimingsSet = true;
     41  mBootstrappedTimings = times;
     42 }
     43 
     44 void HttpConnectionBase::SetSecurityCallbacks(
     45    nsIInterfaceRequestor* aCallbacks) {
     46  MutexAutoLock lock(mCallbacksLock);
     47  // This is called both on and off the main thread. For JS-implemented
     48  // callbacks, we requires that the call happen on the main thread, but
     49  // for C++-implemented callbacks we don't care. Use a pointer holder with
     50  // strict checking disabled.
     51  mCallbacks = new nsMainThreadPtrHolder<nsIInterfaceRequestor>(
     52      "nsHttpConnection::mCallbacks", aCallbacks, false);
     53 }
     54 
     55 void HttpConnectionBase::SetTrafficCategory(HttpTrafficCategory aCategory) {
     56  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     57  if (aCategory == HttpTrafficCategory::eInvalid ||
     58      mTrafficCategory.Contains(aCategory)) {
     59    return;
     60  }
     61  (void)mTrafficCategory.AppendElement(aCategory);
     62 }
     63 
     64 void HttpConnectionBase::ChangeConnectionState(ConnectionState aState) {
     65  LOG(("HttpConnectionBase::ChangeConnectionState this=%p (%d->%d)", this,
     66       static_cast<uint32_t>(mConnectionState), static_cast<uint32_t>(aState)));
     67 
     68  // The state can't move backward.
     69  if (aState <= mConnectionState) {
     70    return;
     71  }
     72 
     73  mConnectionState = aState;
     74 }
     75 
     76 void HttpConnectionBase::RecordConnectionCloseTelemetry(nsresult aReason) {
     77  /**
     78   *
     79   * The returned telemetry key has the format:
     80   * "Version_EndToEndSSL_IsTrrServiceChannel_ExperienceState_ConnectionState"
     81   *
     82   * - Version: The HTTP version of the connection.
     83   * - EndToEndSSL: Indicates whether SSL encryption is end-to-end.
     84   * - IsTrrServiceChannel: Specifies if the connection is used to send TRR
     85   *    requests.
     86   * - ExperienceState: ConnectionExperienceState
     87   * - ConnectionState: The connection state before closing.
     88   */
     89  auto key = nsPrintfCString("%d_%d_%d_%d_%d", static_cast<uint32_t>(Version()),
     90                             mConnInfo->EndToEndSSL(),
     91                             mConnInfo->GetIsTrrServiceChannel(),
     92                             static_cast<uint32_t>(mExperienceState),
     93                             static_cast<uint32_t>(mConnectionState));
     94  SetCloseReason(ToCloseReason(aReason));
     95  LOG(("RecordConnectionCloseTelemetry key=%s reason=%d\n", key.get(),
     96       static_cast<uint32_t>(mCloseReason)));
     97  glean::http::connection_close_reason.Get(key).AccumulateSingleSample(
     98      static_cast<uint32_t>(mCloseReason));
     99 }
    100 
    101 void HttpConnectionBase::RecordConnectionAddressType() {
    102  if (mAddressTypeReported) {
    103    return;
    104  }
    105 
    106  NetAddr addr;
    107  GetPeerAddr(&addr);
    108  if (addr.GetIpAddressSpace() != nsILoadInfo::IPAddressSpace::Public) {
    109    return;
    110  }
    111 
    112  if (mConnInfo->UsingProxy()) {
    113    return;
    114  }
    115 
    116  nsAutoCString key(HttpVersionToTelemetryLabel(Version()));
    117 
    118  if (addr.IsIPAddrV4()) {
    119    key.Append("_ipv4");
    120  } else {
    121    key.Append("_ipv6");
    122  }
    123 
    124  mozilla::glean::networking::connection_address_type.Get(key).Add(1);
    125  mAddressTypeReported = true;
    126 }
    127 
    128 void HttpConnectionBase::ChangeState(HttpConnectionState newState) {
    129  LOG(("HttpConnectionBase::ChangeState %d -> %d [this=%p]", mState, newState,
    130       this));
    131  mState = newState;
    132 }
    133 
    134 nsresult HttpConnectionBase::CheckTunnelIsNeeded(
    135    nsAHttpTransaction* aTransaction) {
    136  switch (mState) {
    137    case HttpConnectionState::UNINITIALIZED: {
    138      // This is is called first time. Check if we need a tunnel.
    139      if (!aTransaction->ConnectionInfo()->UsingConnect()) {
    140        ChangeState(HttpConnectionState::REQUEST);
    141        return NS_OK;
    142      }
    143      ChangeState(HttpConnectionState::SETTING_UP_TUNNEL);
    144    }
    145      [[fallthrough]];
    146    case HttpConnectionState::SETTING_UP_TUNNEL: {
    147      // When a HttpConnectionBase is in this state that means that an
    148      // authentication was needed and we are resending a CONNECT
    149      // request. This request will include authentication headers.
    150      nsresult rv = SetupProxyConnectStream();
    151      if (NS_FAILED(rv)) {
    152        ChangeState(HttpConnectionState::UNINITIALIZED);
    153      }
    154      return rv;
    155    }
    156    case HttpConnectionState::REQUEST:
    157      return NS_OK;
    158  }
    159  return NS_OK;
    160 }
    161 
    162 void HttpConnectionBase::SetOwner(ConnectionEntry* aEntry) {
    163  mOwnerEntry = aEntry;
    164 }
    165 
    166 ConnectionEntry* HttpConnectionBase::OwnerEntry() const {
    167  return mOwnerEntry.get();
    168 }
    169 
    170 }  // namespace net
    171 }  // namespace mozilla