summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/ConnectionEntry.h
blob: 693289d8b3d7b97484a23d5dfa455e4a6bdadcf4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/* 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 ConnectionEntry_h__
#define ConnectionEntry_h__

#include "PendingTransactionInfo.h"
#include "PendingTransactionQueue.h"
#include "DnsAndConnectSocket.h"
#include "DashboardTypes.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:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ConnectionEntry)
  explicit ConnectionEntry(nsHttpConnectionInfo* ci);

  void ReschedTransaction(nsHttpTransaction* aTrans);

  nsTArray<RefPtr<PendingTransactionInfo>>* GetTransactionPendingQHelper(
      nsAHttpTransaction* trans);

  void InsertTransactionSorted(
      nsTArray<RefPtr<PendingTransactionInfo>>& pendingQ,
      PendingTransactionInfo* pendingTransInfo,
      bool aInsertAsFirstForTheSamePriority = false);

  void InsertTransaction(PendingTransactionInfo* aPendingTransInfo,
                         bool aInsertAsFirstForTheSamePriority = false);

  size_t UrgentStartQueueLength();

  void PrintPendingQ();

  void Compact();

  void CancelAllTransactions(nsresult reason);

  nsresult CloseIdleConnection(nsHttpConnection* conn);
  void CloseIdleConnections();
  void CloseIdleConnections(uint32_t maxToClose);
  void CloseH2WebsocketConnections();
  nsresult RemoveIdleConnection(nsHttpConnection* conn);
  bool IsInIdleConnections(HttpConnectionBase* conn);
  size_t IdleConnectionsLength() const { return mIdleConns.Length(); }
  void InsertIntoIdleConnections(nsHttpConnection* conn);
  already_AddRefed<nsHttpConnection> 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);
  void MakeAllDontReuseExcept(HttpConnectionBase* conn);
  bool FindConnToClaim(PendingTransactionInfo* pendingTransInfo);
  void CloseActiveConnections();
  void CloseAllActiveConnsWithNullTransactcion(nsresult aCloseCode);

  bool IsInH2WebsocketConns(HttpConnectionBase* conn);
  void InsertIntoH2WebsocketConns(HttpConnectionBase* conn);
  void RemoveH2WebsocketConns(HttpConnectionBase* conn);

  HttpConnectionBase* GetH2orH3ActiveConn();
  // Make an active spdy connection DontReuse.
  // TODO: this is a helper function and should nbe improved.
  bool MakeFirstActiveSpdyConnDontReuse();

  void ClosePersistentConnections();

  uint32_t PruneDeadConnections();
  void VerifyTraffic();
  void PruneNoTraffic();
  uint32_t TimeoutTick();

  void MoveConnection(HttpConnectionBase* proxyConn, ConnectionEntry* otherEnt);

  size_t DnsAndConnectSocketsLength() const {
    return mDnsAndConnectSockets.Length();
  }

  void InsertIntoDnsAndConnectSockets(DnsAndConnectSocket* sock);
  void RemoveDnsAndConnectSocket(DnsAndConnectSocket* dnsAndSock, bool abandon);
  void CloseAllDnsAndConnectSockets();

  HttpRetParams GetConnectionData();
  void LogConnections();

  const RefPtr<nsHttpConnectionInfo> mConnInfo;

  bool AvailableForDispatchNow();

  // calculate the number of half open sockets that have not had at least 1
  // connection complete
  uint32_t UnconnectedDnsAndConnectSockets() const;

  // Remove a particular DnsAndConnectSocket from the mDnsAndConnectSocket array
  bool RemoveDnsAndConnectSocket(DnsAndConnectSocket*);

  bool MaybeProcessCoalescingKeys(nsIDNSAddrRecord* dnsRecord,
                                  bool aIsHttp3 = false);

  nsresult CreateDnsAndConnectSocket(nsAHttpTransaction* trans, uint32_t caps,
                                     bool speculative, bool isFromPredictor,
                                     bool urgentStart, bool allow1918,
                                     PendingTransactionInfo* pendingTransInfo);

  // 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<nsCString> mCoalescingKeys;

  // 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;

  bool mDoNotDestroy : 1;

  bool IsHttp3() const { return mConnInfo->IsHttp3(); }
  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;

  void AppendPendingUrgentStartQ(
      nsTArray<RefPtr<PendingTransactionInfo>>& 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<RefPtr<PendingTransactionInfo>>& 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<RefPtr<PendingTransactionInfo>>& 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 RemoveTransFromPendingQ(nsHttpTransaction* aTrans);

  void MaybeUpdateEchConfig(nsHttpConnectionInfo* aConnInfo);

  bool AllowToRetryDifferentIPFamilyForHttp3(nsresult aError);
  void SetRetryDifferentIPFamilyForHttp3(uint16_t aIPFamily);

 private:
  void InsertIntoIdleConnections_internal(nsHttpConnection* conn);
  void RemoveFromIdleConnectionsIndex(size_t inx);
  bool RemoveFromIdleConnections(nsHttpConnection* conn);

  nsTArray<RefPtr<nsHttpConnection>> mIdleConns;  // idle persistent connections
  nsTArray<RefPtr<HttpConnectionBase>> mActiveConns;  // active connections

  // "fake" http2 websocket connections that needs to be cleaned up on shutdown
  nsTArray<RefPtr<HttpConnectionBase>> mH2WebsocketConns;

  nsTArray<RefPtr<DnsAndConnectSocket>>
      mDnsAndConnectSockets;  // dns resolution and half open connections

  PendingTransactionQueue mPendingQ;
  ~ConnectionEntry();

  bool mRetriedDifferentIPFamilyForHttp3 = false;
};

}  // namespace net
}  // namespace mozilla

#endif  // !ConnectionEntry_h__