Line data Source code
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 "nsEventQueue.h"
13 : #include "nsCOMPtr.h"
14 : #include "prinrval.h"
15 : #include "mozilla/Logging.h"
16 : #include "prinit.h"
17 : #include "nsIObserver.h"
18 : #include "mozilla/LinkedList.h"
19 : #include "mozilla/Mutex.h"
20 : #include "mozilla/net/DashboardTypes.h"
21 : #include "mozilla/Atomics.h"
22 : #include "mozilla/TimeStamp.h"
23 : #include "nsITimer.h"
24 : #include "mozilla/UniquePtr.h"
25 : #include "PollableEvent.h"
26 :
27 : class nsASocketHandler;
28 : struct PRPollDesc;
29 : class nsIPrefBranch;
30 :
31 : //-----------------------------------------------------------------------------
32 :
33 : namespace mozilla {
34 : namespace net {
35 :
36 : //
37 : // set MOZ_LOG=nsSocketTransport:5
38 : //
39 : extern LazyLogModule gSocketTransportLog;
40 : #define SOCKET_LOG(args) MOZ_LOG(gSocketTransportLog, LogLevel::Debug, args)
41 : #define SOCKET_LOG_ENABLED() MOZ_LOG_TEST(gSocketTransportLog, LogLevel::Debug)
42 :
43 : //
44 : // set MOZ_LOG=UDPSocket:5
45 : //
46 : extern LazyLogModule gUDPSocketLog;
47 : #define UDPSOCKET_LOG(args) MOZ_LOG(gUDPSocketLog, LogLevel::Debug, args)
48 : #define UDPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gUDPSocketLog, LogLevel::Debug)
49 :
50 : //-----------------------------------------------------------------------------
51 :
52 : #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT
53 :
54 : //-----------------------------------------------------------------------------
55 :
56 : // These maximums are borrowed from the linux kernel.
57 : static const int32_t kMaxTCPKeepIdle = 32767; // ~9 hours.
58 : static const int32_t kMaxTCPKeepIntvl = 32767;
59 : static const int32_t kMaxTCPKeepCount = 127;
60 : static const int32_t kDefaultTCPKeepCount =
61 : #if defined (XP_WIN)
62 : 10; // Hardcoded in Windows.
63 : #elif defined (XP_MACOSX)
64 : 8; // Hardcoded in OSX.
65 : #else
66 : 4; // Specifiable in Linux.
67 : #endif
68 :
69 : class LinkedRunnableEvent final : public LinkedListElement<LinkedRunnableEvent>
70 : {
71 : public:
72 0 : explicit LinkedRunnableEvent(nsIRunnable *event) : mEvent(event) {}
73 0 : ~LinkedRunnableEvent() {}
74 :
75 0 : already_AddRefed<nsIRunnable> TakeEvent()
76 : {
77 0 : return mEvent.forget();
78 : }
79 : private:
80 : nsCOMPtr<nsIRunnable> mEvent;
81 : };
82 :
83 : //-----------------------------------------------------------------------------
84 :
85 : class nsSocketTransportService final : public nsPISocketTransportService
86 : , public nsIEventTarget
87 : , public nsIThreadObserver
88 : , public nsIRunnable
89 : , public nsIObserver
90 : {
91 : public:
92 : NS_DECL_THREADSAFE_ISUPPORTS
93 : NS_DECL_NSPISOCKETTRANSPORTSERVICE
94 : NS_DECL_NSISOCKETTRANSPORTSERVICE
95 : NS_DECL_NSIROUTEDSOCKETTRANSPORTSERVICE
96 : NS_DECL_NSIEVENTTARGET_FULL
97 : NS_DECL_NSITHREADOBSERVER
98 : NS_DECL_NSIRUNNABLE
99 : NS_DECL_NSIOBSERVER
100 :
101 : nsSocketTransportService();
102 :
103 : // Max Socket count may need to get initialized/used by nsHttpHandler
104 : // before this class is initialized.
105 : static uint32_t gMaxCount;
106 : static PRCallOnceType gMaxCountInitOnce;
107 : static PRStatus DiscoverMaxCount();
108 :
109 : bool CanAttachSocket();
110 :
111 : // Called by the networking dashboard on the socket thread only
112 : // Fills the passed array with socket information
113 : void GetSocketConnections(nsTArray<SocketInfo> *);
114 0 : uint64_t GetSentBytes() { return mSentBytesCount; }
115 0 : uint64_t GetReceivedBytes() { return mReceivedBytesCount; }
116 :
117 : // Returns true if keepalives are enabled in prefs.
118 15 : bool IsKeepaliveEnabled() { return mKeepaliveEnabledPref; }
119 :
120 34 : bool IsTelemetryEnabledAndNotSleepPhase() { return mTelemetryEnabledPref &&
121 34 : !mSleepPhase; }
122 0 : PRIntervalTime MaxTimeForPrClosePref() {return mMaxTimeForPrClosePref; }
123 : protected:
124 :
125 : virtual ~nsSocketTransportService();
126 :
127 : private:
128 :
129 : //-------------------------------------------------------------------------
130 : // misc (any thread)
131 : //-------------------------------------------------------------------------
132 :
133 : nsCOMPtr<nsIThread> mThread; // protected by mLock
134 : UniquePtr<PollableEvent> mPollableEvent;
135 :
136 : // Returns mThread, protecting the get-and-addref with mLock
137 : already_AddRefed<nsIThread> GetThreadSafely();
138 :
139 : //-------------------------------------------------------------------------
140 : // initialization and shutdown (any thread)
141 : //-------------------------------------------------------------------------
142 :
143 : Mutex mLock;
144 : bool mInitialized;
145 : bool mShuttingDown;
146 : // indicates whether we are currently in the
147 : // process of shutting down
148 : bool mOffline;
149 : bool mGoingOffline;
150 :
151 : // Detaches all sockets.
152 : void Reset(bool aGuardLocals);
153 :
154 : nsresult ShutdownThread();
155 :
156 : //-------------------------------------------------------------------------
157 : // socket lists (socket thread only)
158 : //
159 : // only "active" sockets are on the poll list. the active list is kept
160 : // in sync with the poll list such that:
161 : //
162 : // mActiveList[k].mFD == mPollList[k+1].fd
163 : //
164 : // where k=0,1,2,...
165 : //-------------------------------------------------------------------------
166 :
167 : struct SocketContext
168 : {
169 : PRFileDesc *mFD;
170 : nsASocketHandler *mHandler;
171 : uint16_t mElapsedTime; // time elapsed w/o activity
172 : };
173 :
174 : SocketContext *mActiveList; /* mListSize entries */
175 : SocketContext *mIdleList; /* mListSize entries */
176 : nsIThread *mRawThread;
177 :
178 : uint32_t mActiveListSize;
179 : uint32_t mIdleListSize;
180 : uint32_t mActiveCount;
181 : uint32_t mIdleCount;
182 :
183 : nsresult DetachSocket(SocketContext *, SocketContext *);
184 : nsresult AddToIdleList(SocketContext *);
185 : nsresult AddToPollList(SocketContext *);
186 : void RemoveFromIdleList(SocketContext *);
187 : void RemoveFromPollList(SocketContext *);
188 : void MoveToIdleList(SocketContext *sock);
189 : void MoveToPollList(SocketContext *sock);
190 :
191 : bool GrowActiveList();
192 : bool GrowIdleList();
193 : void InitMaxCount();
194 :
195 : // Total bytes number transfered through all the sockets except active ones
196 : uint64_t mSentBytesCount;
197 : uint64_t mReceivedBytesCount;
198 : //-------------------------------------------------------------------------
199 : // poll list (socket thread only)
200 : //
201 : // first element of the poll list is mPollableEvent (or null if the pollable
202 : // event cannot be created).
203 : //-------------------------------------------------------------------------
204 :
205 : PRPollDesc *mPollList; /* mListSize + 1 entries */
206 :
207 : PRIntervalTime PollTimeout(); // computes ideal poll timeout
208 : nsresult DoPollIteration(TimeDuration *pollDuration);
209 : // perfoms a single poll iteration
210 : int32_t Poll(uint32_t *interval,
211 : TimeDuration *pollDuration);
212 : // calls PR_Poll. the out param
213 : // interval indicates the poll
214 : // duration in seconds.
215 : // pollDuration is used only for
216 : // telemetry
217 :
218 : //-------------------------------------------------------------------------
219 : // pending socket queue - see NotifyWhenCanAttachSocket
220 : //-------------------------------------------------------------------------
221 : AutoCleanLinkedList<LinkedRunnableEvent> mPendingSocketQueue;
222 :
223 : // Preference Monitor for SendBufferSize and Keepalive prefs.
224 : nsresult UpdatePrefs();
225 : void UpdateSendBufferPref(nsIPrefBranch *);
226 : int32_t mSendBufferSize;
227 : // Number of seconds of connection is idle before first keepalive ping.
228 : int32_t mKeepaliveIdleTimeS;
229 : // Number of seconds between retries should keepalive pings fail.
230 : int32_t mKeepaliveRetryIntervalS;
231 : // Number of keepalive probes to send.
232 : int32_t mKeepaliveProbeCount;
233 : // True if TCP keepalive is enabled globally.
234 : bool mKeepaliveEnabledPref;
235 :
236 : Atomic<bool> mServingPendingQueue;
237 : Atomic<int32_t, Relaxed> mMaxTimePerPollIter;
238 : Atomic<bool, Relaxed> mTelemetryEnabledPref;
239 : Atomic<PRIntervalTime, Relaxed> mMaxTimeForPrClosePref;
240 :
241 : // Between a computer going to sleep and waking up the PR_*** telemetry
242 : // will be corrupted - so do not record it.
243 : Atomic<bool, Relaxed> mSleepPhase;
244 : nsCOMPtr<nsITimer> mAfterWakeUpTimer;
245 :
246 : void OnKeepaliveEnabledPrefChange();
247 : void NotifyKeepaliveEnabledPrefChange(SocketContext *sock);
248 :
249 : // Socket thread only for dynamically adjusting max socket size
250 : #if defined(XP_WIN)
251 : void ProbeMaxCount();
252 : #endif
253 : bool mProbedMaxCount;
254 :
255 : void AnalyzeConnection(nsTArray<SocketInfo> *data,
256 : SocketContext *context, bool aActive);
257 :
258 : void ClosePrivateConnections();
259 : void DetachSocketWithGuard(bool aGuardLocals,
260 : SocketContext *socketList,
261 : int32_t index);
262 :
263 : void MarkTheLastElementOfPendingQueue();
264 :
265 : #if defined(XP_WIN)
266 : Atomic<bool> mPolling;
267 : nsCOMPtr<nsITimer> mPollRepairTimer;
268 : void StartPollWatchdog();
269 : void DoPollRepair();
270 : void StartPolling();
271 : void EndPolling();
272 : #endif
273 : };
274 :
275 : extern nsSocketTransportService *gSocketTransportService;
276 : bool OnSocketThread();
277 :
278 : } // namespace net
279 : } // namespace mozilla
280 :
281 : #endif // !nsSocketTransportService_h__
|