DnsAndConnectSocket.h (9242B)
1 /* vim:set ts=4 sw=2 sts=2 et cin: */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef DnsAndConnectSocket_h__ 7 #define DnsAndConnectSocket_h__ 8 9 #include "mozilla/TimeStamp.h" 10 #include "nsAHttpConnection.h" 11 #include "nsHttpConnection.h" 12 #include "nsHttpTransaction.h" 13 #include "nsIAsyncOutputStream.h" 14 #include "nsICancelable.h" 15 #include "nsIDNSListener.h" 16 #include "nsIDNSRecord.h" 17 #include "nsIDNSService.h" 18 #include "nsINamed.h" 19 #include "nsITransport.h" 20 #include "nsWeakReference.h" 21 22 namespace mozilla { 23 namespace net { 24 25 // 8d411b53-54bc-4a99-8b78-ff125eab1564 26 #define NS_DNSANDCONNECTSOCKET_IID \ 27 {0x8d411b53, 0x54bc, 0x4a99, {0x8b, 0x78, 0xff, 0x12, 0x5e, 0xab, 0x15, 0x64}} 28 29 class PendingTransactionInfo; 30 class ConnectionEntry; 31 32 class DnsAndConnectSocket final : public nsIOutputStreamCallback, 33 public nsITransportEventSink, 34 public nsIInterfaceRequestor, 35 public nsITimerCallback, 36 public nsINamed, 37 public nsSupportsWeakReference, 38 public nsIDNSListener { 39 ~DnsAndConnectSocket(); 40 41 public: 42 NS_INLINE_DECL_STATIC_IID(NS_DNSANDCONNECTSOCKET_IID) 43 NS_DECL_THREADSAFE_ISUPPORTS 44 NS_DECL_NSIOUTPUTSTREAMCALLBACK 45 NS_DECL_NSITRANSPORTEVENTSINK 46 NS_DECL_NSIINTERFACEREQUESTOR 47 NS_DECL_NSITIMERCALLBACK 48 NS_DECL_NSINAMED 49 NS_DECL_NSIDNSLISTENER 50 51 DnsAndConnectSocket(nsHttpConnectionInfo* ci, nsAHttpTransaction* trans, 52 uint32_t caps, bool speculative, bool urgentStart); 53 54 [[nodiscard]] nsresult Init(ConnectionEntry* ent); 55 void Abandon(); 56 double Duration(TimeStamp epoch); 57 void CloseTransports(nsresult error); 58 59 bool IsSpeculative() { return mSpeculative; } 60 61 bool Allow1918() { return mAllow1918; } 62 void SetAllow1918(bool val) { mAllow1918 = val; } 63 64 bool HasConnected() { return mHasConnected; } 65 66 void PrintDiagnostics(nsCString& log); 67 68 // Checks whether the transaction can be dispatched using this 69 // half-open's connection. If this half-open is marked as urgent-start, 70 // it only accepts urgent start transactions. Call only before Claim(). 71 bool AcceptsTransaction(nsHttpTransaction* trans); 72 bool Claim(); 73 void Unclaim(); 74 75 private: 76 // This performs checks that the DnsAndConnectSocket has been properly cleand 77 // up. 78 void CheckIsDone(); 79 80 /** 81 * State: 82 * INIT: initial state. From this state: 83 * 1) change the state to RESOLVING and start the primary DNS lookup 84 * if mSkipDnsResolution is false, 85 * 2) or the lookup is skip and the state changes to CONNECTING and 86 * start the backup timer. 87 * 3) or changes to DONE in case of an error. 88 * RESOLVING: the primary DNS resolution is in progress. From this state 89 * we transition into CONNECTING or DONE. 90 * CONNECTING: We change to this state when the primary connection has 91 * started. At that point the backup timer is started. 92 * ONE_CONNECTED: We change into this state when one of the connections 93 * is connected and the second is in progres. 94 * DONE 95 * 96 * Events: 97 * INIT_EVENT: Start the primary dns resolution (if mSkipDnsResolution is 98 * false), otherwise start the primary connection. 99 * RESOLVED_PRIMARY_EVENT: the primary DNS resolution is done. This event 100 * may be resent due to DNS retries 101 * CONNECTED_EVENT: A connecion (primary or backup) is done 102 */ 103 enum DnsAndSocketState { 104 INIT, 105 RESOLVING, 106 CONNECTING, 107 ONE_CONNECTED, 108 DONE 109 } mState = INIT; 110 111 enum SetupEvents { 112 INIT_EVENT, 113 RESOLVED_PRIMARY_EVENT, 114 PRIMARY_DONE_EVENT, 115 BACKUP_DONE_EVENT, 116 BACKUP_TIMER_FIRED_EVENT 117 }; 118 119 // This structure is responsible for performing DNS lookup, creating socket 120 // and connecting the socket. 121 struct TransportSetup { 122 enum TransportSetupState { 123 INIT, 124 RESOLVING, 125 RESOLVED, 126 RETRY_RESOLVING, 127 CONNECTING, 128 CONNECTING_DONE, 129 DONE 130 } mState; 131 132 bool FirstResolving() { 133 return mState == TransportSetup::TransportSetupState::RESOLVING; 134 } 135 bool ConnectingOrRetry() { 136 return (mState == TransportSetup::TransportSetupState::CONNECTING) || 137 (mState == TransportSetup::TransportSetupState::RETRY_RESOLVING) || 138 (mState == TransportSetup::TransportSetupState::CONNECTING_DONE); 139 } 140 bool Resolved() { 141 return mState == TransportSetup::TransportSetupState::RESOLVED; 142 } 143 bool DoneConnecting() { 144 return (mState == TransportSetup::TransportSetupState::CONNECTING_DONE) || 145 (mState == TransportSetup::TransportSetupState::DONE); 146 } 147 148 nsCString mHost; 149 nsCOMPtr<nsICancelable> mDNSRequest; 150 nsCOMPtr<nsIDNSAddrRecord> mDNSRecord; 151 nsIDNSService::DNSFlags mDnsFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS; 152 bool mRetryWithDifferentIPFamily = false; 153 bool mResetFamilyPreference = false; 154 bool mSkipDnsResolution = false; 155 156 nsCOMPtr<nsISocketTransport> mSocketTransport; 157 nsCOMPtr<nsIAsyncOutputStream> mStreamOut; 158 nsCOMPtr<nsIAsyncInputStream> mStreamIn; 159 TimeStamp mSynStarted; 160 bool mConnectedOK = false; 161 bool mIsBackup; 162 163 bool mWaitingForConnect = false; 164 void SetConnecting(); 165 void MaybeSetConnectingDone(); 166 167 nsresult Init(DnsAndConnectSocket* dnsAndSock); 168 void CancelDnsResolution(); 169 void Abandon(); 170 void CloseAll(); 171 nsresult SetupConn(DnsAndConnectSocket* dnsAndSock, 172 nsAHttpTransaction* transaction, ConnectionEntry* ent, 173 nsresult status, uint32_t cap, 174 HttpConnectionBase** connection); 175 [[nodiscard]] nsresult SetupStreams(DnsAndConnectSocket* dnsAndSock); 176 nsresult ResolveHost(DnsAndConnectSocket* dnsAndSock); 177 bool ShouldRetryDNS(); 178 nsresult OnLookupComplete(DnsAndConnectSocket* dnsAndSock, 179 nsIDNSRecord* rec, nsresult status); 180 nsresult CheckConnectedResult(DnsAndConnectSocket* dnsAndSock); 181 // Toggles the IP family flags (RESOLVE_DISABLE_IPV6 and 182 // RESOLVE_DISABLE_IPV4) in mDnsFlags if retrying with a different IP family 183 // is enabled. 184 bool ToggleIpFamilyFlagsIfRetryEnabled(); 185 186 protected: 187 explicit TransportSetup(bool isBackup); 188 }; 189 190 struct PrimaryTransportSetup final : TransportSetup { 191 PrimaryTransportSetup() : TransportSetup(false) {} 192 }; 193 194 struct BackupTransportSetup final : TransportSetup { 195 BackupTransportSetup() : TransportSetup(true) {} 196 }; 197 198 nsresult SetupConn(bool isPrimary, nsresult status); 199 void SetupBackupTimer(); 200 void CancelBackupTimer(); 201 202 bool IsPrimary(nsITransport* trans); 203 bool IsPrimary(nsIAsyncOutputStream* out); 204 bool IsPrimary(nsICancelable* dnsRequest); 205 bool IsBackup(nsITransport* trans); 206 bool IsBackup(nsIAsyncOutputStream* out); 207 bool IsBackup(nsICancelable* dnsRequest); 208 209 // To find out whether |mTransaction| is still in the connection entry's 210 // pending queue. If the transaction is found and |removeWhenFound| is 211 // true, the transaction will be removed from the pending queue. 212 already_AddRefed<PendingTransactionInfo> FindTransactionHelper( 213 bool removeWhenFound); 214 215 void CheckProxyConfig(); 216 nsresult SetupDnsFlags(ConnectionEntry* ent); 217 nsresult SetupEvent(SetupEvents event); 218 219 RefPtr<nsAHttpTransaction> mTransaction; 220 bool mDispatchedMTransaction = false; 221 222 PrimaryTransportSetup mPrimaryTransport; 223 uint32_t mCaps; 224 225 // mSpeculative is set if the socket was created from 226 // SpeculativeConnect(). It is cleared when a transaction would normally 227 // start a new connection from scratch but instead finds this one in 228 // the half open list and claims it for its own use. (which due to 229 // the vagaries of scheduling from the pending queue might not actually 230 // match up - but it prevents a speculative connection from opening 231 // more connections that are needed.) 232 bool mSpeculative; 233 234 // If created with a non-null urgent transaction, remember it, so we can 235 // mark the connection as urgent rightaway it's created. 236 bool mUrgentStart; 237 238 bool mAllow1918 = true; 239 240 // mHasConnected tracks whether one of the sockets has completed the 241 // connection process. It may have completed unsuccessfully. 242 bool mHasConnected = false; 243 244 bool mBackupConnStatsSet = false; 245 246 // A DnsAndConnectSocket can be made for a concrete non-null transaction, 247 // but the transaction can be dispatch to another connection. In that 248 // case we can free this transaction to be claimed by other 249 // transactions. 250 bool mFreeToUse = true; 251 252 RefPtr<nsHttpConnectionInfo> mConnInfo; 253 nsCOMPtr<nsITimer> mSynTimer; 254 BackupTransportSetup mBackupTransport; 255 256 bool mIsHttp3 = false; 257 258 bool mSkipDnsResolution = false; 259 bool mProxyNotTransparent = false; 260 bool mProxyTransparentResolvesHost = false; 261 }; 262 263 } // namespace net 264 } // namespace mozilla 265 266 #endif // DnsAndConnectSocket_h__