/src/mozilla-central/netwerk/base/nsSocketTransportService2.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* vim:set ts=4 sw=4 sts=4 ci et: */ |
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 nsSocketTransportService2_h__ |
7 | | #define nsSocketTransportService2_h__ |
8 | | |
9 | | #include "nsPISocketTransportService.h" |
10 | | #include "nsIThreadInternal.h" |
11 | | #include "nsIRunnable.h" |
12 | | #include "nsCOMPtr.h" |
13 | | #include "prinrval.h" |
14 | | #include "mozilla/Logging.h" |
15 | | #include "prinit.h" |
16 | | #include "nsIObserver.h" |
17 | | #include "mozilla/LinkedList.h" |
18 | | #include "mozilla/Mutex.h" |
19 | | #include "mozilla/net/DashboardTypes.h" |
20 | | #include "mozilla/Atomics.h" |
21 | | #include "mozilla/TimeStamp.h" |
22 | | #include "nsITimer.h" |
23 | | #include "mozilla/UniquePtr.h" |
24 | | #include "PollableEvent.h" |
25 | | |
26 | | class nsASocketHandler; |
27 | | struct PRPollDesc; |
28 | | class nsIPrefBranch; |
29 | | |
30 | | //----------------------------------------------------------------------------- |
31 | | |
32 | | namespace mozilla { |
33 | | namespace net { |
34 | | |
35 | | // |
36 | | // set MOZ_LOG=nsSocketTransport:5 |
37 | | // |
38 | | extern LazyLogModule gSocketTransportLog; |
39 | 80 | #define SOCKET_LOG(args) MOZ_LOG(gSocketTransportLog, LogLevel::Debug, args) |
40 | 0 | #define SOCKET_LOG_ENABLED() MOZ_LOG_TEST(gSocketTransportLog, LogLevel::Debug) |
41 | | |
42 | | // |
43 | | // set MOZ_LOG=UDPSocket:5 |
44 | | // |
45 | | extern LazyLogModule gUDPSocketLog; |
46 | 0 | #define UDPSOCKET_LOG(args) MOZ_LOG(gUDPSocketLog, LogLevel::Debug, args) |
47 | | #define UDPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gUDPSocketLog, LogLevel::Debug) |
48 | | |
49 | | //----------------------------------------------------------------------------- |
50 | | |
51 | 4 | #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT |
52 | | |
53 | | //----------------------------------------------------------------------------- |
54 | | |
55 | | // These maximums are borrowed from the linux kernel. |
56 | | static const int32_t kMaxTCPKeepIdle = 32767; // ~9 hours. |
57 | | static const int32_t kMaxTCPKeepIntvl = 32767; |
58 | | static const int32_t kMaxTCPKeepCount = 127; |
59 | | static const int32_t kDefaultTCPKeepCount = |
60 | | #if defined (XP_WIN) |
61 | | 10; // Hardcoded in Windows. |
62 | | #elif defined (XP_MACOSX) |
63 | | 8; // Hardcoded in OSX. |
64 | | #else |
65 | | 4; // Specifiable in Linux. |
66 | | #endif |
67 | | |
68 | | class LinkedRunnableEvent final : public LinkedListElement<LinkedRunnableEvent> |
69 | | { |
70 | | public: |
71 | 0 | explicit LinkedRunnableEvent(nsIRunnable *event) : mEvent(event) {} |
72 | 0 | ~LinkedRunnableEvent() = default; |
73 | | |
74 | | already_AddRefed<nsIRunnable> TakeEvent() |
75 | 0 | { |
76 | 0 | return mEvent.forget(); |
77 | 0 | } |
78 | | private: |
79 | | nsCOMPtr<nsIRunnable> mEvent; |
80 | | }; |
81 | | |
82 | | //----------------------------------------------------------------------------- |
83 | | |
84 | | class nsSocketTransportService final : public nsPISocketTransportService |
85 | | , public nsIEventTarget |
86 | | , public nsIThreadObserver |
87 | | , public nsIRunnable |
88 | | , public nsIObserver |
89 | | { |
90 | | public: |
91 | | NS_DECL_THREADSAFE_ISUPPORTS |
92 | | NS_DECL_NSPISOCKETTRANSPORTSERVICE |
93 | | NS_DECL_NSISOCKETTRANSPORTSERVICE |
94 | | NS_DECL_NSIROUTEDSOCKETTRANSPORTSERVICE |
95 | | NS_DECL_NSIEVENTTARGET_FULL |
96 | | NS_DECL_NSITHREADOBSERVER |
97 | | NS_DECL_NSIRUNNABLE |
98 | | NS_DECL_NSIOBSERVER |
99 | | |
100 | | nsSocketTransportService(); |
101 | | |
102 | | // Max Socket count may need to get initialized/used by nsHttpHandler |
103 | | // before this class is initialized. |
104 | | static uint32_t gMaxCount; |
105 | | static PRCallOnceType gMaxCountInitOnce; |
106 | | static PRStatus DiscoverMaxCount(); |
107 | | |
108 | | bool CanAttachSocket(); |
109 | | |
110 | | // Called by the networking dashboard on the socket thread only |
111 | | // Fills the passed array with socket information |
112 | | void GetSocketConnections(nsTArray<SocketInfo> *); |
113 | 0 | uint64_t GetSentBytes() { return mSentBytesCount; } |
114 | 0 | uint64_t GetReceivedBytes() { return mReceivedBytesCount; } |
115 | | |
116 | | // Returns true if keepalives are enabled in prefs. |
117 | 0 | bool IsKeepaliveEnabled() { return mKeepaliveEnabledPref; } |
118 | | |
119 | 0 | bool IsTelemetryEnabledAndNotSleepPhase() { return mTelemetryEnabledPref && |
120 | 0 | !mSleepPhase; } |
121 | 0 | PRIntervalTime MaxTimeForPrClosePref() {return mMaxTimeForPrClosePref; } |
122 | | |
123 | 0 | bool IsEsniEnabled() { return mEsniEnabled && !mTrustedMitmDetected && |
124 | 0 | !mNotTrustedMitmDetected; } |
125 | | |
126 | 0 | void SetNotTrustedMitmDetected() { |
127 | 0 | mNotTrustedMitmDetected = true; |
128 | 0 | } |
129 | | |
130 | | protected: |
131 | | |
132 | | virtual ~nsSocketTransportService(); |
133 | | |
134 | | private: |
135 | | |
136 | | //------------------------------------------------------------------------- |
137 | | // misc (any thread) |
138 | | //------------------------------------------------------------------------- |
139 | | |
140 | | nsCOMPtr<nsIThread> mThread; // protected by mLock |
141 | | UniquePtr<PollableEvent> mPollableEvent; |
142 | | |
143 | | // Returns mThread, protecting the get-and-addref with mLock |
144 | | already_AddRefed<nsIThread> GetThreadSafely(); |
145 | | |
146 | | //------------------------------------------------------------------------- |
147 | | // initialization and shutdown (any thread) |
148 | | //------------------------------------------------------------------------- |
149 | | |
150 | | Mutex mLock; |
151 | | bool mInitialized; |
152 | | bool mShuttingDown; |
153 | | // indicates whether we are currently in the |
154 | | // process of shutting down |
155 | | bool mOffline; |
156 | | bool mGoingOffline; |
157 | | |
158 | | // Detaches all sockets. |
159 | | void Reset(bool aGuardLocals); |
160 | | |
161 | | nsresult ShutdownThread(); |
162 | | |
163 | | //------------------------------------------------------------------------- |
164 | | // socket lists (socket thread only) |
165 | | // |
166 | | // only "active" sockets are on the poll list. the active list is kept |
167 | | // in sync with the poll list such that: |
168 | | // |
169 | | // mActiveList[k].mFD == mPollList[k+1].fd |
170 | | // |
171 | | // where k=0,1,2,... |
172 | | //------------------------------------------------------------------------- |
173 | | |
174 | | struct SocketContext |
175 | | { |
176 | | PRFileDesc *mFD; |
177 | | nsASocketHandler *mHandler; |
178 | | PRIntervalTime mPollStartEpoch; // time we started to poll this socket |
179 | | |
180 | | public: |
181 | | // Returns true iff the socket has not been signalled longer than |
182 | | // the desired timeout (mHandler->mPollTimeout). |
183 | | bool IsTimedOut(PRIntervalTime now) const; |
184 | | // Engages the timeout by marking the epoch we start polling this socket. |
185 | | // If epoch is already marked this does nothing, hence, this method can be |
186 | | // called everytime we put this socket to poll() list with in-flags set. |
187 | | void EnsureTimeout(PRIntervalTime now); |
188 | | // Called after an event on a socket has been signalled to turn of the |
189 | | // timeout calculation. |
190 | | void DisengageTimeout(); |
191 | | // Returns the number of intervals this socket is about to timeout in, |
192 | | // or 0 (zero) when it has already timed out. Returns NS_SOCKET_POLL_TIMEOUT |
193 | | // when there is no timeout set on the socket. |
194 | | PRIntervalTime TimeoutIn(PRIntervalTime now) const; |
195 | | // When a socket timeout is reset and later set again, it may happen |
196 | | // that mPollStartEpoch is not reset in between. We have to manually |
197 | | // call this on every iteration over sockets to ensure the epoch reset. |
198 | | void MaybeResetEpoch(); |
199 | | }; |
200 | | |
201 | | SocketContext *mActiveList; /* mListSize entries */ |
202 | | SocketContext *mIdleList; /* mListSize entries */ |
203 | | nsIThread *mRawThread; |
204 | | |
205 | | uint32_t mActiveListSize; |
206 | | uint32_t mIdleListSize; |
207 | | uint32_t mActiveCount; |
208 | | uint32_t mIdleCount; |
209 | | |
210 | | nsresult DetachSocket(SocketContext *, SocketContext *); |
211 | | nsresult AddToIdleList(SocketContext *); |
212 | | nsresult AddToPollList(SocketContext *); |
213 | | void RemoveFromIdleList(SocketContext *); |
214 | | void RemoveFromPollList(SocketContext *); |
215 | | void MoveToIdleList(SocketContext *sock); |
216 | | void MoveToPollList(SocketContext *sock); |
217 | | |
218 | | bool GrowActiveList(); |
219 | | bool GrowIdleList(); |
220 | | void InitMaxCount(); |
221 | | |
222 | | // Total bytes number transfered through all the sockets except active ones |
223 | | uint64_t mSentBytesCount; |
224 | | uint64_t mReceivedBytesCount; |
225 | | //------------------------------------------------------------------------- |
226 | | // poll list (socket thread only) |
227 | | // |
228 | | // first element of the poll list is mPollableEvent (or null if the pollable |
229 | | // event cannot be created). |
230 | | //------------------------------------------------------------------------- |
231 | | |
232 | | PRPollDesc *mPollList; /* mListSize + 1 entries */ |
233 | | |
234 | | PRIntervalTime PollTimeout(PRIntervalTime now); // computes ideal poll timeout |
235 | | nsresult DoPollIteration(TimeDuration *pollDuration); |
236 | | // perfoms a single poll iteration |
237 | | int32_t Poll(TimeDuration *pollDuration, PRIntervalTime now); |
238 | | // calls PR_Poll. the out param |
239 | | // interval indicates the poll |
240 | | // duration in seconds. |
241 | | // pollDuration is used only for |
242 | | // telemetry |
243 | | |
244 | | //------------------------------------------------------------------------- |
245 | | // pending socket queue - see NotifyWhenCanAttachSocket |
246 | | //------------------------------------------------------------------------- |
247 | | AutoCleanLinkedList<LinkedRunnableEvent> mPendingSocketQueue; |
248 | | |
249 | | // Preference Monitor for SendBufferSize and Keepalive prefs. |
250 | | nsresult UpdatePrefs(); |
251 | | static void PrefCallback(const char* aPref, nsSocketTransportService* aSelf); |
252 | | void UpdateSendBufferPref(); |
253 | | int32_t mSendBufferSize; |
254 | | // Number of seconds of connection is idle before first keepalive ping. |
255 | | int32_t mKeepaliveIdleTimeS; |
256 | | // Number of seconds between retries should keepalive pings fail. |
257 | | int32_t mKeepaliveRetryIntervalS; |
258 | | // Number of keepalive probes to send. |
259 | | int32_t mKeepaliveProbeCount; |
260 | | // True if TCP keepalive is enabled globally. |
261 | | bool mKeepaliveEnabledPref; |
262 | | // Timeout of pollable event signalling. |
263 | | TimeDuration mPollableEventTimeout; |
264 | | |
265 | | Atomic<bool> mServingPendingQueue; |
266 | | Atomic<int32_t, Relaxed> mMaxTimePerPollIter; |
267 | | Atomic<bool, Relaxed> mTelemetryEnabledPref; |
268 | | Atomic<PRIntervalTime, Relaxed> mMaxTimeForPrClosePref; |
269 | | // Timestamp of the last network link change event, tracked |
270 | | // also on child processes. |
271 | | Atomic<PRIntervalTime, Relaxed> mLastNetworkLinkChangeTime; |
272 | | // Preference for how long we do busy wait after network link |
273 | | // change has been detected. |
274 | | Atomic<PRIntervalTime, Relaxed> mNetworkLinkChangeBusyWaitPeriod; |
275 | | // Preference for the value of timeout for poll() we use during |
276 | | // the network link change event period. |
277 | | Atomic<PRIntervalTime, Relaxed> mNetworkLinkChangeBusyWaitTimeout; |
278 | | |
279 | | // Between a computer going to sleep and waking up the PR_*** telemetry |
280 | | // will be corrupted - so do not record it. |
281 | | Atomic<bool, Relaxed> mSleepPhase; |
282 | | nsCOMPtr<nsITimer> mAfterWakeUpTimer; |
283 | | |
284 | | void OnKeepaliveEnabledPrefChange(); |
285 | | void NotifyKeepaliveEnabledPrefChange(SocketContext *sock); |
286 | | |
287 | | // Socket thread only for dynamically adjusting max socket size |
288 | | #if defined(XP_WIN) |
289 | | void ProbeMaxCount(); |
290 | | #endif |
291 | | bool mProbedMaxCount; |
292 | | |
293 | | void AnalyzeConnection(nsTArray<SocketInfo> *data, |
294 | | SocketContext *context, bool aActive); |
295 | | |
296 | | void ClosePrivateConnections(); |
297 | | void DetachSocketWithGuard(bool aGuardLocals, |
298 | | SocketContext *socketList, |
299 | | int32_t index); |
300 | | |
301 | | void MarkTheLastElementOfPendingQueue(); |
302 | | |
303 | | #if defined(XP_WIN) |
304 | | Atomic<bool> mPolling; |
305 | | nsCOMPtr<nsITimer> mPollRepairTimer; |
306 | | void StartPollWatchdog(); |
307 | | void DoPollRepair(); |
308 | | void StartPolling(); |
309 | | void EndPolling(); |
310 | | #endif |
311 | | |
312 | | void TryRepairPollableEvent(); |
313 | | |
314 | | bool mEsniEnabled; |
315 | | bool mTrustedMitmDetected; |
316 | | bool mNotTrustedMitmDetected; |
317 | | }; |
318 | | |
319 | | extern nsSocketTransportService *gSocketTransportService; |
320 | | bool OnSocketThread(); |
321 | | |
322 | | } // namespace net |
323 | | } // namespace mozilla |
324 | | |
325 | | #endif // !nsSocketTransportService_h__ |