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