summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/DnsAndConnectSocket.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/DnsAndConnectSocket.h')
-rw-r--r--netwerk/protocol/http/DnsAndConnectSocket.h274
1 files changed, 274 insertions, 0 deletions
diff --git a/netwerk/protocol/http/DnsAndConnectSocket.h b/netwerk/protocol/http/DnsAndConnectSocket.h
new file mode 100644
index 0000000000..8409de3d08
--- /dev/null
+++ b/netwerk/protocol/http/DnsAndConnectSocket.h
@@ -0,0 +1,274 @@
+/* vim:set ts=4 sw=2 sts=2 et cin: */
+/* 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/. */
+
+#ifndef DnsAndConnectSocket_h__
+#define DnsAndConnectSocket_h__
+
+#include "mozilla/TimeStamp.h"
+#include "mozilla/UniquePtr.h"
+#include "nsAHttpConnection.h"
+#include "nsHttpConnection.h"
+#include "nsHttpTransaction.h"
+#include "nsIAsyncOutputStream.h"
+#include "nsICancelable.h"
+#include "nsIDNSListener.h"
+#include "nsIDNSRecord.h"
+#include "nsIDNSService.h"
+#include "nsINamed.h"
+#include "nsITransport.h"
+#include "nsWeakReference.h"
+
+namespace mozilla {
+namespace net {
+
+// 8d411b53-54bc-4a99-8b78-ff125eab1564
+#define NS_DNSANDCONNECTSOCKET_IID \
+ { \
+ 0x8d411b53, 0x54bc, 0x4a99, { \
+ 0x8b, 0x78, 0xff, 0x12, 0x5e, 0xab, 0x15, 0x64 \
+ } \
+ }
+
+class PendingTransactionInfo;
+class ConnectionEntry;
+
+class DnsAndConnectSocket final : public nsIOutputStreamCallback,
+ public nsITransportEventSink,
+ public nsIInterfaceRequestor,
+ public nsITimerCallback,
+ public nsINamed,
+ public nsSupportsWeakReference,
+ public nsIDNSListener {
+ ~DnsAndConnectSocket();
+
+ public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_DNSANDCONNECTSOCKET_IID)
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIOUTPUTSTREAMCALLBACK
+ NS_DECL_NSITRANSPORTEVENTSINK
+ NS_DECL_NSIINTERFACEREQUESTOR
+ NS_DECL_NSITIMERCALLBACK
+ NS_DECL_NSINAMED
+ NS_DECL_NSIDNSLISTENER
+
+ DnsAndConnectSocket(nsHttpConnectionInfo* ci, nsAHttpTransaction* trans,
+ uint32_t caps, bool speculative, bool isFromPredictor,
+ bool urgentStart);
+
+ [[nodiscard]] nsresult Init(ConnectionEntry* ent);
+ void Abandon();
+ double Duration(TimeStamp epoch);
+ void CloseTransports(nsresult error);
+
+ bool IsSpeculative() { return mSpeculative; }
+
+ bool Allow1918() { return mAllow1918; }
+ void SetAllow1918(bool val) { mAllow1918 = val; }
+
+ bool HasConnected() { return mHasConnected; }
+
+ void PrintDiagnostics(nsCString& log);
+
+ // Checks whether the transaction can be dispatched using this
+ // half-open's connection. If this half-open is marked as urgent-start,
+ // it only accepts urgent start transactions. Call only before Claim().
+ bool AcceptsTransaction(nsHttpTransaction* trans);
+ bool Claim();
+ void Unclaim();
+
+ private:
+ // This performs checks that the DnsAndConnectSocket has been properly cleand
+ // up.
+ void CheckIsDone();
+
+ /**
+ * State:
+ * INIT: initial state. From this state:
+ * 1) change the state to RESOLVING and start the primary DNS lookup
+ * if mSkipDnsResolution is false,
+ * 2) or the lookup is skip and the state changes to CONNECTING and
+ * start the backup timer.
+ * 3) or changes to DONE in case of an error.
+ * RESOLVING: the primary DNS resolution is in progress. From this state
+ * we transition into CONNECTING or DONE.
+ * CONNECTING: We change to this state when the primary connection has
+ * started. At that point the backup timer is started.
+ * ONE_CONNECTED: We change into this state when one of the connections
+ * is connected and the second is in progres.
+ * DONE
+ *
+ * Events:
+ * INIT_EVENT: Start the primary dns resolution (if mSkipDnsResolution is
+ * false), otherwise start the primary connection.
+ * RESOLVED_PRIMARY_EVENT: the primary DNS resolution is done. This event
+ * may be resent due to DNS retries
+ * CONNECTED_EVENT: A connecion (primary or backup) is done
+ */
+ enum DnsAndSocketState {
+ INIT,
+ RESOLVING,
+ CONNECTING,
+ ONE_CONNECTED,
+ DONE
+ } mState = INIT;
+
+ enum SetupEvents {
+ INIT_EVENT,
+ RESOLVED_PRIMARY_EVENT,
+ PRIMARY_DONE_EVENT,
+ BACKUP_DONE_EVENT,
+ BACKUP_TIMER_FIRED_EVENT
+ };
+
+ // This structure is responsible for performing DNS lookup, creating socket
+ // and connecting the socket.
+ struct TransportSetup {
+ enum TransportSetupState {
+ INIT,
+ RESOLVING,
+ RESOLVED,
+ RETRY_RESOLVING,
+ CONNECTING,
+ CONNECTING_DONE,
+ DONE
+ } mState;
+
+ bool FirstResolving() {
+ return mState == TransportSetup::TransportSetupState::RESOLVING;
+ }
+ bool ConnectingOrRetry() {
+ return (mState == TransportSetup::TransportSetupState::CONNECTING) ||
+ (mState == TransportSetup::TransportSetupState::RETRY_RESOLVING) ||
+ (mState == TransportSetup::TransportSetupState::CONNECTING_DONE);
+ }
+ bool Resolved() {
+ return mState == TransportSetup::TransportSetupState::RESOLVED;
+ }
+ bool DoneConnecting() {
+ return (mState == TransportSetup::TransportSetupState::CONNECTING_DONE) ||
+ (mState == TransportSetup::TransportSetupState::DONE);
+ }
+
+ nsCString mHost;
+ nsCOMPtr<nsICancelable> mDNSRequest;
+ nsCOMPtr<nsIDNSAddrRecord> mDNSRecord;
+ nsIDNSService::DNSFlags mDnsFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
+ bool mRetryWithDifferentIPFamily = false;
+ bool mResetFamilyPreference = false;
+ bool mSkipDnsResolution = false;
+
+ nsCOMPtr<nsISocketTransport> mSocketTransport;
+ nsCOMPtr<nsIAsyncOutputStream> mStreamOut;
+ nsCOMPtr<nsIAsyncInputStream> mStreamIn;
+ TimeStamp mSynStarted;
+ bool mConnectedOK = false;
+ bool mIsBackup;
+
+ bool mWaitingForConnect = false;
+ void SetConnecting();
+ void MaybeSetConnectingDone();
+
+ nsresult Init(DnsAndConnectSocket* dnsAndSock);
+ void CancelDnsResolution();
+ void Abandon();
+ void CloseAll();
+ nsresult SetupConn(nsAHttpTransaction* transaction, ConnectionEntry* ent,
+ nsresult status, uint32_t cap,
+ HttpConnectionBase** connection);
+ [[nodiscard]] nsresult SetupStreams(DnsAndConnectSocket* dnsAndSock);
+ nsresult ResolveHost(DnsAndConnectSocket* dnsAndSock);
+ bool ShouldRetryDNS();
+ nsresult OnLookupComplete(DnsAndConnectSocket* dnsAndSock,
+ nsIDNSRecord* rec, nsresult status);
+ nsresult CheckConnectedResult(DnsAndConnectSocket* dnsAndSock);
+
+ protected:
+ explicit TransportSetup(bool isBackup);
+ };
+
+ struct PrimaryTransportSetup final : TransportSetup {
+ PrimaryTransportSetup() : TransportSetup(false) {}
+ };
+
+ struct BackupTransportSetup final : TransportSetup {
+ BackupTransportSetup() : TransportSetup(true) {}
+ };
+
+ nsresult SetupConn(bool isPrimary, nsresult status);
+ void SetupBackupTimer();
+ void CancelBackupTimer();
+
+ bool IsPrimary(nsITransport* trans);
+ bool IsPrimary(nsIAsyncOutputStream* out);
+ bool IsPrimary(nsICancelable* dnsRequest);
+ bool IsBackup(nsITransport* trans);
+ bool IsBackup(nsIAsyncOutputStream* out);
+ bool IsBackup(nsICancelable* dnsRequest);
+
+ // To find out whether |mTransaction| is still in the connection entry's
+ // pending queue. If the transaction is found and |removeWhenFound| is
+ // true, the transaction will be removed from the pending queue.
+ already_AddRefed<PendingTransactionInfo> FindTransactionHelper(
+ bool removeWhenFound);
+
+ void CheckProxyConfig();
+ nsresult SetupDnsFlags(ConnectionEntry* ent);
+ nsresult SetupEvent(SetupEvents event);
+
+ RefPtr<nsAHttpTransaction> mTransaction;
+ bool mDispatchedMTransaction = false;
+
+ PrimaryTransportSetup mPrimaryTransport;
+ uint32_t mCaps;
+
+ // mSpeculative is set if the socket was created from
+ // SpeculativeConnect(). It is cleared when a transaction would normally
+ // start a new connection from scratch but instead finds this one in
+ // the half open list and claims it for its own use. (which due to
+ // the vagaries of scheduling from the pending queue might not actually
+ // match up - but it prevents a speculative connection from opening
+ // more connections that are needed.)
+ bool mSpeculative;
+
+ // If created with a non-null urgent transaction, remember it, so we can
+ // mark the connection as urgent rightaway it's created.
+ bool mUrgentStart;
+
+ // mIsFromPredictor is set if the socket originated from the network
+ // Predictor. It is used to gather telemetry data on used speculative
+ // connections from the predictor.
+ bool mIsFromPredictor;
+
+ bool mAllow1918 = true;
+
+ // mHasConnected tracks whether one of the sockets has completed the
+ // connection process. It may have completed unsuccessfully.
+ bool mHasConnected = false;
+
+ bool mBackupConnStatsSet = false;
+
+ // A DnsAndConnectSocket can be made for a concrete non-null transaction,
+ // but the transaction can be dispatch to another connection. In that
+ // case we can free this transaction to be claimed by other
+ // transactions.
+ bool mFreeToUse = true;
+
+ RefPtr<nsHttpConnectionInfo> mConnInfo;
+ nsCOMPtr<nsITimer> mSynTimer;
+ BackupTransportSetup mBackupTransport;
+
+ bool mIsHttp3;
+
+ bool mSkipDnsResolution = false;
+ bool mProxyNotTransparent = false;
+ bool mProxyTransparentResolvesHost = false;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(DnsAndConnectSocket, NS_DNSANDCONNECTSOCKET_IID)
+
+} // namespace net
+} // namespace mozilla
+
+#endif // DnsAndConnectSocket_h__