Bug 1804798 - Explicitly set auto page name (and corresponding debug flag) when inser...
[gecko.git] / netwerk / base / nsSocketTransportService2.h
blob451632ac25e72945434b418e415ad53bdb05c9fa
1 /* vim:set ts=4 sw=2 sts=2 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/. */
6 #ifndef nsSocketTransportService2_h__
7 #define nsSocketTransportService2_h__
9 #include "PollableEvent.h"
10 #include "mozilla/Atomics.h"
11 #include "mozilla/LinkedList.h"
12 #include "mozilla/Logging.h"
13 #include "mozilla/Maybe.h"
14 #include "mozilla/Mutex.h"
15 #include "mozilla/TimeStamp.h"
16 #include "mozilla/Tuple.h"
17 #include "mozilla/UniquePtr.h"
18 #include "mozilla/net/DashboardTypes.h"
19 #include "nsCOMPtr.h"
20 #include "nsIDirectTaskDispatcher.h"
21 #include "nsIObserver.h"
22 #include "nsIRunnable.h"
23 #include "nsIThreadInternal.h"
24 #include "nsITimer.h"
25 #include "nsPISocketTransportService.h"
26 #include "prinit.h"
27 #include "prinrval.h"
29 class nsASocketHandler;
30 struct PRPollDesc;
31 class nsIPrefBranch;
33 //-----------------------------------------------------------------------------
35 namespace mozilla {
36 namespace net {
39 // set MOZ_LOG=nsSocketTransport:5
41 extern LazyLogModule gSocketTransportLog;
42 #define SOCKET_LOG(args) MOZ_LOG(gSocketTransportLog, LogLevel::Debug, args)
43 #define SOCKET_LOG1(args) MOZ_LOG(gSocketTransportLog, LogLevel::Error, args)
44 #define SOCKET_LOG_ENABLED() MOZ_LOG_TEST(gSocketTransportLog, LogLevel::Debug)
47 // set MOZ_LOG=UDPSocket:5
49 extern LazyLogModule gUDPSocketLog;
50 #define UDPSOCKET_LOG(args) MOZ_LOG(gUDPSocketLog, LogLevel::Debug, args)
51 #define UDPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gUDPSocketLog, LogLevel::Debug)
53 //-----------------------------------------------------------------------------
55 #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT
57 //-----------------------------------------------------------------------------
59 // These maximums are borrowed from the linux kernel.
60 static const int32_t kMaxTCPKeepIdle = 32767; // ~9 hours.
61 static const int32_t kMaxTCPKeepIntvl = 32767;
62 static const int32_t kMaxTCPKeepCount = 127;
63 static const int32_t kDefaultTCPKeepCount =
64 #if defined(XP_WIN)
65 10; // Hardcoded in Windows.
66 #elif defined(XP_MACOSX)
67 8; // Hardcoded in OSX.
68 #else
69 4; // Specifiable in Linux.
70 #endif
72 class LinkedRunnableEvent final
73 : public LinkedListElement<LinkedRunnableEvent> {
74 public:
75 explicit LinkedRunnableEvent(nsIRunnable* event) : mEvent(event) {}
76 ~LinkedRunnableEvent() = default;
78 already_AddRefed<nsIRunnable> TakeEvent() { return mEvent.forget(); }
80 private:
81 nsCOMPtr<nsIRunnable> mEvent;
84 //-----------------------------------------------------------------------------
86 class nsSocketTransportService final : public nsPISocketTransportService,
87 public nsISerialEventTarget,
88 public nsIThreadObserver,
89 public nsIRunnable,
90 public nsIObserver,
91 public nsINamed,
92 public nsIDirectTaskDispatcher {
93 public:
94 NS_DECL_THREADSAFE_ISUPPORTS
95 NS_DECL_NSPISOCKETTRANSPORTSERVICE
96 NS_DECL_NSISOCKETTRANSPORTSERVICE
97 NS_DECL_NSIROUTEDSOCKETTRANSPORTSERVICE
98 NS_DECL_NSIEVENTTARGET_FULL
99 NS_DECL_NSITHREADOBSERVER
100 NS_DECL_NSIRUNNABLE
101 NS_DECL_NSIOBSERVER
102 NS_DECL_NSINAMED
103 NS_DECL_NSIDIRECTTASKDISPATCHER
105 static const uint32_t SOCKET_LIMIT_MIN = 50U;
107 nsSocketTransportService();
109 // Max Socket count may need to get initialized/used by nsHttpHandler
110 // before this class is initialized.
111 static uint32_t gMaxCount;
112 static PRCallOnceType gMaxCountInitOnce;
113 static PRStatus DiscoverMaxCount();
115 bool CanAttachSocket();
117 // Called by the networking dashboard on the socket thread only
118 // Fills the passed array with socket information
119 void GetSocketConnections(nsTArray<SocketInfo>*);
120 uint64_t GetSentBytes() { return mSentBytesCount; }
121 uint64_t GetReceivedBytes() { return mReceivedBytesCount; }
123 // Returns true if keepalives are enabled in prefs.
124 bool IsKeepaliveEnabled() { return mKeepaliveEnabledPref; }
126 bool IsTelemetryEnabledAndNotSleepPhase();
127 PRIntervalTime MaxTimeForPrClosePref() { return mMaxTimeForPrClosePref; }
129 // According the preference value of `network.socket.forcePort` this method
130 // possibly remaps the port number passed as the arg.
131 void ApplyPortRemap(uint16_t* aPort);
133 // Reads the preference string and updates (rewrites) the mPortRemapping
134 // array on the socket thread. Returns true if the whole pref string was
135 // correctly formed.
136 bool UpdatePortRemapPreference(nsACString const& aPortMappingPref);
138 protected:
139 virtual ~nsSocketTransportService();
141 private:
142 //-------------------------------------------------------------------------
143 // misc (any thread)
144 //-------------------------------------------------------------------------
146 // The value is guaranteed to be valid and not dangling while on the socket
147 // thread as mThread is only ever reset after it's been shutdown.
148 // This member should only ever be read on the socket thread.
149 nsIThread* mRawThread{nullptr};
151 // Returns mThread in a thread-safe manner.
152 already_AddRefed<nsIThread> GetThreadSafely();
153 // Same as above, but return mThread as a nsIDirectTaskDispatcher
154 already_AddRefed<nsIDirectTaskDispatcher> GetDirectTaskDispatcherSafely();
156 //-------------------------------------------------------------------------
157 // initialization and shutdown (any thread)
158 //-------------------------------------------------------------------------
160 Atomic<bool> mInitialized{false};
161 // indicates whether we are currently in the process of shutting down
162 Atomic<bool> mShuttingDown{false};
163 Mutex mLock MOZ_UNANNOTATED{"nsSocketTransportService::mLock"};
164 // Variables in the next section protected by mLock
166 // mThread and mDirectTaskDispatcher are only ever modified on the main
167 // thread. Will be set on Init and set to null after shutdown. You must access
168 // mThread and mDirectTaskDispatcher outside the main thread via respectively
169 // GetThreadSafely and GetDirectTaskDispatchedSafely().
170 nsCOMPtr<nsIThread> mThread;
171 // We store a pointer to mThread as a direct task dispatcher to avoid having
172 // to do do_QueryInterface whenever we need to access the interface.
173 nsCOMPtr<nsIDirectTaskDispatcher> mDirectTaskDispatcher;
174 UniquePtr<PollableEvent> mPollableEvent;
175 bool mOffline{false};
176 bool mGoingOffline{false};
178 // Detaches all sockets.
179 void Reset(bool aGuardLocals);
181 nsresult ShutdownThread();
183 //-------------------------------------------------------------------------
184 // socket lists (socket thread only)
186 // only "active" sockets are on the poll list. the active list is kept
187 // in sync with the poll list such that:
189 // mActiveList[k].mFD == mPollList[k+1].fd
191 // where k=0,1,2,...
192 //-------------------------------------------------------------------------
194 struct SocketContext {
195 PRFileDesc* mFD;
196 nsASocketHandler* mHandler;
197 PRIntervalTime mPollStartEpoch; // time we started to poll this socket
199 public:
200 // Returns true iff the socket has not been signalled longer than
201 // the desired timeout (mHandler->mPollTimeout).
202 bool IsTimedOut(PRIntervalTime now) const;
203 // Engages the timeout by marking the epoch we start polling this socket.
204 // If epoch is already marked this does nothing, hence, this method can be
205 // called everytime we put this socket to poll() list with in-flags set.
206 void EnsureTimeout(PRIntervalTime now);
207 // Called after an event on a socket has been signalled to turn of the
208 // timeout calculation.
209 void DisengageTimeout();
210 // Returns the number of intervals this socket is about to timeout in,
211 // or 0 (zero) when it has already timed out. Returns
212 // NS_SOCKET_POLL_TIMEOUT when there is no timeout set on the socket.
213 PRIntervalTime TimeoutIn(PRIntervalTime now) const;
214 // When a socket timeout is reset and later set again, it may happen
215 // that mPollStartEpoch is not reset in between. We have to manually
216 // call this on every iteration over sockets to ensure the epoch reset.
217 void MaybeResetEpoch();
220 SocketContext* mActiveList; /* mListSize entries */
221 SocketContext* mIdleList; /* mListSize entries */
223 uint32_t mActiveListSize{SOCKET_LIMIT_MIN};
224 uint32_t mIdleListSize{SOCKET_LIMIT_MIN};
225 uint32_t mActiveCount{0};
226 uint32_t mIdleCount{0};
228 nsresult DetachSocket(SocketContext*, SocketContext*);
229 nsresult AddToIdleList(SocketContext*);
230 nsresult AddToPollList(SocketContext*);
231 void RemoveFromIdleList(SocketContext*);
232 void RemoveFromPollList(SocketContext*);
233 void MoveToIdleList(SocketContext* sock);
234 void MoveToPollList(SocketContext* sock);
236 bool GrowActiveList();
237 bool GrowIdleList();
238 void InitMaxCount();
240 // Total bytes number transfered through all the sockets except active ones
241 uint64_t mSentBytesCount{0};
242 uint64_t mReceivedBytesCount{0};
243 //-------------------------------------------------------------------------
244 // poll list (socket thread only)
246 // first element of the poll list is mPollableEvent (or null if the pollable
247 // event cannot be created).
248 //-------------------------------------------------------------------------
250 PRPollDesc* mPollList; /* mListSize + 1 entries */
252 PRIntervalTime PollTimeout(
253 PRIntervalTime now); // computes ideal poll timeout
254 nsresult DoPollIteration(TimeDuration* pollDuration);
255 // perfoms a single poll iteration
256 int32_t Poll(TimeDuration* pollDuration, PRIntervalTime ts);
257 // calls PR_Poll. the out param
258 // interval indicates the poll
259 // duration in seconds.
260 // pollDuration is used only for
261 // telemetry
263 //-------------------------------------------------------------------------
264 // pending socket queue - see NotifyWhenCanAttachSocket
265 //-------------------------------------------------------------------------
266 AutoCleanLinkedList<LinkedRunnableEvent> mPendingSocketQueue;
268 // Preference Monitor for SendBufferSize and Keepalive prefs.
269 nsresult UpdatePrefs();
270 static void UpdatePrefs(const char* aPref, void* aSelf);
271 void UpdateSendBufferPref();
272 int32_t mSendBufferSize{0};
273 // Number of seconds of connection is idle before first keepalive ping.
274 int32_t mKeepaliveIdleTimeS{600};
275 // Number of seconds between retries should keepalive pings fail.
276 int32_t mKeepaliveRetryIntervalS{1};
277 // Number of keepalive probes to send.
278 int32_t mKeepaliveProbeCount{kDefaultTCPKeepCount};
279 // True if TCP keepalive is enabled globally.
280 bool mKeepaliveEnabledPref{false};
281 // Timeout of pollable event signalling.
282 TimeDuration mPollableEventTimeout;
284 Atomic<bool> mServingPendingQueue{false};
285 Atomic<int32_t, Relaxed> mMaxTimePerPollIter{100};
286 Atomic<PRIntervalTime, Relaxed> mMaxTimeForPrClosePref;
287 // Timestamp of the last network link change event, tracked
288 // also on child processes.
289 Atomic<PRIntervalTime, Relaxed> mLastNetworkLinkChangeTime{0};
290 // Preference for how long we do busy wait after network link
291 // change has been detected.
292 Atomic<PRIntervalTime, Relaxed> mNetworkLinkChangeBusyWaitPeriod;
293 // Preference for the value of timeout for poll() we use during
294 // the network link change event period.
295 Atomic<PRIntervalTime, Relaxed> mNetworkLinkChangeBusyWaitTimeout;
297 // Between a computer going to sleep and waking up the PR_*** telemetry
298 // will be corrupted - so do not record it.
299 Atomic<bool, Relaxed> mSleepPhase{false};
300 nsCOMPtr<nsITimer> mAfterWakeUpTimer;
302 // Lazily created array of forced port remappings. The tuple members meaning
303 // is exactly:
304 // <0> the greater-or-equal port number of the range to remap
305 // <1> the less-or-equal port number of the range to remap
306 // <2> the port number to remap to, when the given port number falls to the
307 // range
308 using TPortRemapping = CopyableTArray<Tuple<uint16_t, uint16_t, uint16_t>>;
309 Maybe<TPortRemapping> mPortRemapping;
311 // Called on the socket thread to apply the mapping build on the main thread
312 // from the preference.
313 void ApplyPortRemapPreference(TPortRemapping const& portRemapping);
315 void OnKeepaliveEnabledPrefChange();
316 void NotifyKeepaliveEnabledPrefChange(SocketContext* sock);
318 // Socket thread only for dynamically adjusting max socket size
319 #if defined(XP_WIN)
320 void ProbeMaxCount();
321 #endif
322 bool mProbedMaxCount{false};
324 // Report socket status to about:networking
325 void AnalyzeConnection(nsTArray<SocketInfo>* data, SocketContext* context,
326 bool aActive);
328 void ClosePrivateConnections();
329 void DetachSocketWithGuard(bool aGuardLocals, SocketContext* socketList,
330 int32_t index);
332 void MarkTheLastElementOfPendingQueue();
334 #if defined(XP_WIN)
335 Atomic<bool> mPolling{false};
336 nsCOMPtr<nsITimer> mPollRepairTimer;
337 void StartPollWatchdog();
338 void DoPollRepair();
339 void StartPolling();
340 void EndPolling();
341 #endif
343 void TryRepairPollableEvent();
345 CopyableTArray<nsCOMPtr<nsISTSShutdownObserver>> mShutdownObservers;
348 extern nsSocketTransportService* gSocketTransportService;
349 bool OnSocketThread();
351 } // namespace net
352 } // namespace mozilla
354 #endif // !nsSocketTransportService_h__