/* 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 ConnectionEntry_h_ #define ConnectionEntry_h_ #include "ConnectionAttemptPool.h" #include "PendingTransactionInfo.h" #include "PendingTransactionQueue.h" #include "mozilla/WeakPtr.h" #include "nsTHashSet.h" namespace mozilla { namespace net { // ConnectionEntry // // nsHttpConnectionMgr::mCT maps connection info hash key to ConnectionEntry // object, which contains list of active and idle connections as well as the // list of pending transactions. class ConnectionEntry : public SupportsWeakPtr { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ConnectionEntry) ConnectionEntry(nsHttpConnectionInfo* ci, nsTHashSet& aPendingQSet); void ReschedTransaction(nsHttpTransaction* aTrans); nsTArray>* GetTransactionPendingQHelper( nsAHttpTransaction* trans); void InsertTransactionSorted( nsTArray>& pendingQ, PendingTransactionInfo* pendingTransInfo, bool aInsertAsFirstForTheSamePriority = false); void InsertTransaction(PendingTransactionInfo* aPendingTransInfo, bool aInsertAsFirstForTheSamePriority = false); size_t UrgentStartQueueLength(); bool UrgentStartQueueIsEmpty() const; void PrintPendingQ(); void Compact(); void CancelAllTransactions(nsresult reason); nsresult CloseIdleConnection(nsHttpConnection* conn); void CloseIdleConnections(); void CloseIdleConnections(uint32_t maxToClose); void CloseExtendedCONNECTConnections(); void ClosePendingConnections(); nsresult RemoveIdleConnection(nsHttpConnection* conn); bool IsInIdleConnections(HttpConnectionBase* conn); size_t IdleConnectionsLength() const { return mIdleConns.Length(); } void InsertIntoIdleConnections(nsHttpConnection* conn); already_AddRefed GetIdleConnection(bool respectUrgency, bool urgentTrans, bool* onlyUrgent); size_t ActiveConnsLength() const { return mActiveConns.Length(); } void InsertIntoActiveConns(HttpConnectionBase* conn); bool IsInActiveConns(HttpConnectionBase* conn); nsresult RemoveActiveConnection(HttpConnectionBase* conn); nsresult RemovePendingConnection(HttpConnectionBase* conn); void MakeAllDontReuseExcept(HttpConnectionBase* conn); bool FindConnToClaim(PendingTransactionInfo* pendingTransInfo); void CloseActiveConnections(); void CloseAllActiveConnsWithNullTransactcion(nsresult aCloseCode); bool IsInExtendedCONNECTConns(HttpConnectionBase* conn); void InsertIntoExtendedCONNECTConns(HttpConnectionBase* conn); void RemoveExtendedCONNECTConns(HttpConnectionBase* conn); HttpConnectionBase* GetH2orH3ActiveConn(bool aNoHttp2, bool aNoHttp3); // Find an H2 tunnel connection (nsHttpConnection with UsingSpdy()) in active // connections. This is used for WebSocket/WebTransport through H3 proxy. already_AddRefed GetH2TunnelActiveConn(); // Make an active spdy connection DontReuse. // TODO: this is a helper function and should nbe improved. bool MakeFirstActiveSpdyConnDontReuse(); void ClosePersistentConnections(); uint32_t PruneDeadConnections(); void MakeConnectionPendingAndDontReuse(HttpConnectionBase* conn); // Move any active HTTP/3 connection that can no longer take new transactions // (e.g. DontReuse'd) out of mActiveConns and into mPendingConns, so it stops // holding the single-H3-per-entry slot and is closed once its current // transaction (if any) finishes. void MoveUnusableH3ConnsToPending(); void VerifyTraffic(); void PruneNoTraffic(); uint32_t TimeoutTick(); void MoveConnection(HttpConnectionBase* proxyConn, ConnectionEntry* otherEnt); size_t DnsAndConnectSocketsLength() const { return mConnectionAttemptPool->Length(); } void RemoveConnectionAttempt(ConnectionAttempt* sock, bool abandon); void CloseAllConnectionAttempts(); void OnConnectionAttemptConnected() { mConnectionAttemptPool->OnConnectionAttemptConnected(); } HttpRetParams GetConnectionData(); Http3ConnectionStatsParams GetHttp3ConnectionStatsData(); void LogConnections(); const RefPtr mConnInfo; bool AvailableForDispatchNow(); bool MaybeProcessCoalescingKeys(nsIDNSAddrRecord* dnsRecord, bool aIsHttp3 = false); bool MaybeProcessCoalescingKeys(const nsTArray& aAddresses, bool aIsHttp3 = false); nsresult CreateDnsAndConnectSocket(nsAHttpTransaction* trans, uint32_t caps, bool speculative, bool urgentStart, bool allow1918, PendingTransactionInfo* pendingTransInfo, bool retryWithoutTRR = false); // Spdy sometimes resolves the address in the socket manager in order // to re-coalesce sharded HTTP hosts. The dotted decimal address is // combined with the Anonymous flag and OA from the connection information // to build the hash key for hosts in the same ip pool. // nsTArray mCoalescingKeys; // This is a list of addresses matching the coalescing keys. // This is necessary to check if the origin's DNS entries // contain the IP address of the active connection. nsTArray mAddresses; // To have the UsingSpdy flag means some host with the same connection // entry has done NPN=spdy/* at some point. It does not mean every // connection is currently using spdy. bool mUsingSpdy : 1; // Determines whether or not we can continue to use spdy-enabled // connections in the future. This is generally set to false either when // some connection here encounters connection-based auth (such as NTLM) // or when some connection here encounters a server that is totally // busted (such as it fails to properly perform the h2 handshake). bool mCanUseSpdy : 1; // Flags to remember our happy-eyeballs decision. // Reset only by Ctrl-F5 reload. // True when we've first connected an IPv4 server for this host, // initially false. bool mPreferIPv4 : 1; // True when we've first connected an IPv6 server for this host, // initially false. bool mPreferIPv6 : 1; // True if this connection entry has initiated a socket bool mUsedForConnection : 1; // True if a ProcessPendingQForEntry runnable is already pending for this // entry on the socket thread event queue. Prevents posting redundant // runnables when many connection events fire in rapid succession. bool mPendingQProcessingScheduled : 1; // Returns true when the entry has no connections, no pending transactions, // and no in-progress connection attempts. Used to determine whether the // entry can be removed from the connection table. bool IsEmpty() const { return IdleConnectionsLength() == 0 && ActiveConnsLength() == 0 && DnsAndConnectSocketsLength() == 0 && PendingQueueIsEmpty() && UrgentStartQueueIsEmpty() && mPendingConns.IsEmpty() && mExtendedCONNECTConns.IsEmpty(); } bool IsHttp3ProxyConnection() const { return mConnInfo->IsHttp3ProxyConnection(); } bool AllowHttp2() const { return mCanUseSpdy; } void DisallowHttp2(); void DontReuseHttp3Conn(); // Set the IP family preference flags according the connected family void RecordIPFamilyPreference(uint16_t family); // Resets all flags to their default values void ResetIPFamilyPreference(); // True iff there is currently an established IP family preference bool PreferenceKnown() const; // Return the count of pending transactions for all window ids. size_t PendingQueueLength() const; size_t PendingQueueLengthForWindow(uint64_t windowId) const; bool PendingQueueIsEmpty() const; void AppendPendingUrgentStartQ( nsTArray>& result); // Append transactions to the |result| whose window id // is equal to |windowId|. // NOTE: maxCount == 0 will get all transactions in the queue. void AppendPendingQForFocusedWindow( uint64_t windowId, nsTArray>& result, uint32_t maxCount = 0); // Append transactions whose window id isn't equal to |windowId|. // NOTE: windowId == 0 will get all transactions for both // focused and non-focused windows. void AppendPendingQForNonFocusedWindows( uint64_t windowId, nsTArray>& result, uint32_t maxCount = 0); // Remove the empty pendingQ in |mPendingTransactionTable|. void RemoveEmptyPendingQ(); void PrintDiagnostics(nsCString& log, uint32_t aMaxPersistConns); bool RestrictConnections(); // Return total active connection count, which is the sum of // active connections and unconnected half open connections. uint32_t TotalActiveConnections() const; bool HasActiveH3Connection() const; bool RemoveTransFromPendingQ(nsHttpTransaction* aTrans); // Notify that a transaction was removed directly from a per-window pending // array (not from the urgent-start queue). void OnPendingTransactionRemovedFromTable() { mPendingQ.OnPendingTransactionRemovedFromTable(); } void MaybeUpdateEchConfig(nsHttpConnectionInfo* aConnInfo); bool AllowToRetryDifferentIPFamilyForHttp3(nsresult aError); void SetRetryDifferentIPFamilyForHttp3(uint16_t aIPFamily); void SetServerCertHashes(nsTArray>&& aHashes); const nsTArray>& GetServerCertHashes(); const HashNumber& OriginFrameHashKey(); private: void MaybeRemoveFromPendingSet(); nsTHashSet& mPendingQSet; void InsertIntoIdleConnections_internal(nsHttpConnection* conn); void RemoveFromIdleConnectionsIndex(size_t inx); bool RemoveFromIdleConnections(nsHttpConnection* conn); nsTArray> mIdleConns; // idle persistent connections nsTArray> mActiveConns; // active connections // When a connection is added to this mPendingConns list, it is primarily // to keep the connection alive and to continue serving its ongoing // transaction. While in this list, the connection will not be available to // serve any new transactions and will remain here until its current // transaction is complete. nsTArray> mPendingConns; // Tunneled connections used for extended CONNECT that needs to be cleaned up // on shutdown nsTArray> mExtendedCONNECTConns; RefPtr mConnectionAttemptPool; // If serverCertificateHashes are used, these are stored here nsTArray> mServerCertHashes; PendingTransactionQueue mPendingQ; ~ConnectionEntry(); Maybe mOriginFrameHashKey; bool mRetriedDifferentIPFamilyForHttp3 = false; }; } // namespace net } // namespace mozilla #endif // !ConnectionEntry_h_