Coverage Report

Created: 2018-09-25 14:53

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