nsSocketTransportService2.h (13435B)
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/. */ 5 6 #ifndef nsSocketTransportService2_h__ 7 #define nsSocketTransportService2_h__ 8 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 17 #include "mozilla/UniquePtr.h" 18 #include "mozilla/net/DashboardTypes.h" 19 #include "nsCOMPtr.h" 20 #include "nsASocketHandler.h" 21 #include "nsIDirectTaskDispatcher.h" 22 #include "nsIObserver.h" 23 #include "nsIRunnable.h" 24 #include "nsIThreadInternal.h" 25 #include "nsITimer.h" 26 #include "nsPISocketTransportService.h" 27 #include "prinit.h" 28 #include "prinrval.h" 29 30 struct PRPollDesc; 31 class nsIPrefBranch; 32 33 //----------------------------------------------------------------------------- 34 35 namespace mozilla { 36 namespace net { 37 38 // 39 // set MOZ_LOG=nsSocketTransport:5 40 // 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) 45 46 // 47 // set MOZ_LOG=UDPSocket:5 48 // 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) 52 53 //----------------------------------------------------------------------------- 54 55 #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT 56 57 //----------------------------------------------------------------------------- 58 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 71 72 class LinkedRunnableEvent final 73 : public LinkedListElement<LinkedRunnableEvent> { 74 public: 75 explicit LinkedRunnableEvent(nsIRunnable* event) : mEvent(event) {} 76 ~LinkedRunnableEvent() = default; 77 78 already_AddRefed<nsIRunnable> TakeEvent() { return mEvent.forget(); } 79 80 private: 81 nsCOMPtr<nsIRunnable> mEvent; 82 }; 83 84 //----------------------------------------------------------------------------- 85 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 104 105 static const uint32_t SOCKET_LIMIT_MIN = 50U; 106 107 nsSocketTransportService(); 108 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(); 114 115 bool CanAttachSocket(); 116 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; } 122 123 // Returns true if keepalives are enabled in prefs. 124 bool IsKeepaliveEnabled() { return mKeepaliveEnabledPref; } 125 126 bool IsTelemetryEnabledAndNotSleepPhase(); 127 PRIntervalTime MaxTimeForPrClosePref() { return mMaxTimeForPrClosePref; } 128 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); 132 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); 137 138 protected: 139 ~nsSocketTransportService(); 140 141 private: 142 //------------------------------------------------------------------------- 143 // misc (any thread) 144 //------------------------------------------------------------------------- 145 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}; 150 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(); 155 156 //------------------------------------------------------------------------- 157 // initialization and shutdown (any thread) 158 //------------------------------------------------------------------------- 159 160 Atomic<bool> mInitialized{false}; 161 // indicates whether we are currently in the process of shutting down 162 Atomic<bool> mShuttingDown{false}; 163 164 Mutex mLock{"nsSocketTransportService::mLock"}; 165 // Variables in the next section protected by mLock 166 167 // mThread and mDirectTaskDispatcher are only ever modified on the main 168 // thread. Will be set on Init and set to null after shutdown. You must access 169 // mThread and mDirectTaskDispatcher outside the main thread via respectively 170 // GetThreadSafely and GetDirectTaskDispatchedSafely(). 171 nsCOMPtr<nsIThread> mThread MOZ_GUARDED_BY(mLock); 172 // We store a pointer to mThread as a direct task dispatcher to avoid having 173 // to do do_QueryInterface whenever we need to access the interface. 174 nsCOMPtr<nsIDirectTaskDispatcher> mDirectTaskDispatcher MOZ_GUARDED_BY(mLock); 175 UniquePtr<PollableEvent> mPollableEvent MOZ_GUARDED_BY(mLock); 176 bool mOffline MOZ_GUARDED_BY(mLock) = false; 177 bool mGoingOffline MOZ_GUARDED_BY(mLock) = false; 178 179 // Detaches all sockets. 180 void Reset(bool aGuardLocals); 181 182 nsresult ShutdownThread(); 183 184 //------------------------------------------------------------------------- 185 // socket lists (socket thread only) 186 // 187 // only "active" sockets are on the poll list. the active list is kept 188 // in sync with the poll list such that: 189 // 190 // mActiveList[k].mFD == mPollList[k+1].fd 191 // 192 // where k=0,1,2,... 193 //------------------------------------------------------------------------- 194 195 class SocketContext { 196 public: 197 SocketContext(PRFileDesc* aFD, 198 already_AddRefed<nsASocketHandler>&& aHandler, 199 PRIntervalTime aPollStartEpoch) 200 : mFD(aFD), mHandler(aHandler), mPollStartEpoch(aPollStartEpoch) {} 201 SocketContext(PRFileDesc* aFD, nsASocketHandler* aHandler, 202 PRIntervalTime aPollStartEpoch) 203 : mFD(aFD), mHandler(aHandler), mPollStartEpoch(aPollStartEpoch) {} 204 ~SocketContext() = default; 205 206 // Returns true iff the socket has not been signalled longer than 207 // the desired timeout (mHandler->mPollTimeout). 208 bool IsTimedOut(PRIntervalTime now) const; 209 // Engages the timeout by marking the epoch we start polling this socket. 210 // If epoch is already marked this does nothing, hence, this method can be 211 // called everytime we put this socket to poll() list with in-flags set. 212 void EnsureTimeout(PRIntervalTime now); 213 // Called after an event on a socket has been signalled to turn of the 214 // timeout calculation. 215 void DisengageTimeout(); 216 // Returns the number of intervals this socket is about to timeout in, 217 // or 0 (zero) when it has already timed out. Returns 218 // NS_SOCKET_POLL_TIMEOUT when there is no timeout set on the socket. 219 PRIntervalTime TimeoutIn(PRIntervalTime now) const; 220 // When a socket timeout is reset and later set again, it may happen 221 // that mPollStartEpoch is not reset in between. We have to manually 222 // call this on every iteration over sockets to ensure the epoch reset. 223 void MaybeResetEpoch(); 224 225 PRFileDesc* mFD; 226 RefPtr<nsASocketHandler> mHandler; 227 PRIntervalTime mPollStartEpoch; // time we started to poll this socket 228 }; 229 230 using SocketContextList = AutoTArray<SocketContext, SOCKET_LIMIT_MIN>; 231 int64_t SockIndex(SocketContextList& aList, SocketContext* aSock); 232 233 SocketContextList mActiveList; 234 SocketContextList mIdleList; 235 236 nsresult DetachSocket(SocketContextList& listHead, SocketContext*); 237 void AddToIdleList(SocketContext* sock); 238 void AddToPollList(SocketContext* sock); 239 void RemoveFromIdleList(SocketContext* sock); 240 void RemoveFromPollList(SocketContext* sock); 241 void MoveToIdleList(SocketContext* sock); 242 void MoveToPollList(SocketContext* sock); 243 244 void InitMaxCount(); 245 246 // Total bytes number transfered through all the sockets except active ones 247 uint64_t mSentBytesCount{0}; 248 uint64_t mReceivedBytesCount{0}; 249 //------------------------------------------------------------------------- 250 // poll list (socket thread only) 251 // 252 // first element of the poll list is mPollableEvent (or null if the pollable 253 // event cannot be created). 254 //------------------------------------------------------------------------- 255 256 nsTArray<PRPollDesc> mPollList; 257 258 PRIntervalTime PollTimeout( 259 PRIntervalTime now); // computes ideal poll timeout 260 nsresult DoPollIteration(); 261 // perfoms a single poll iteration 262 int32_t Poll(PRIntervalTime ts); 263 // calls PR_Poll. 264 265 //------------------------------------------------------------------------- 266 // pending socket queue - see NotifyWhenCanAttachSocket 267 //------------------------------------------------------------------------- 268 AutoCleanLinkedList<LinkedRunnableEvent> mPendingSocketQueue; 269 270 // Preference Monitor for SendBufferSize and Keepalive prefs. 271 nsresult UpdatePrefs(); 272 static void UpdatePrefs(const char* aPref, void* aSelf); 273 void UpdateSendBufferPref(); 274 int32_t mSendBufferSize{0}; 275 // Number of seconds of connection is idle before first keepalive ping. 276 int32_t mKeepaliveIdleTimeS{600}; 277 // Number of seconds between retries should keepalive pings fail. 278 int32_t mKeepaliveRetryIntervalS{1}; 279 // Number of keepalive probes to send. 280 int32_t mKeepaliveProbeCount{kDefaultTCPKeepCount}; 281 // True if TCP keepalive is enabled globally. 282 bool mKeepaliveEnabledPref{false}; 283 // Timeout of pollable event signalling. 284 TimeDuration mPollableEventTimeout MOZ_GUARDED_BY(mLock); 285 286 Atomic<bool> mServingPendingQueue{false}; 287 Atomic<int32_t, Relaxed> mMaxTimePerPollIter{100}; 288 Atomic<PRIntervalTime, Relaxed> mMaxTimeForPrClosePref; 289 // Timestamp of the last network link change event, tracked 290 // also on child processes. 291 Atomic<PRIntervalTime, Relaxed> mLastNetworkLinkChangeTime{0}; 292 // Preference for how long we do busy wait after network link 293 // change has been detected. 294 Atomic<PRIntervalTime, Relaxed> mNetworkLinkChangeBusyWaitPeriod; 295 // Preference for the value of timeout for poll() we use during 296 // the network link change event period. 297 Atomic<PRIntervalTime, Relaxed> mNetworkLinkChangeBusyWaitTimeout; 298 299 // Between a computer going to sleep and waking up the PR_*** telemetry 300 // will be corrupted - so do not record it. 301 Atomic<bool, Relaxed> mSleepPhase{false}; 302 nsCOMPtr<nsITimer> mAfterWakeUpTimer; 303 304 // Lazily created array of forced port remappings. The tuple members meaning 305 // is exactly: 306 // <0> the greater-or-equal port number of the range to remap 307 // <1> the less-or-equal port number of the range to remap 308 // <2> the port number to remap to, when the given port number falls to the 309 // range 310 using TPortRemapping = 311 CopyableTArray<std::tuple<uint16_t, uint16_t, uint16_t>>; 312 Maybe<TPortRemapping> mPortRemapping; 313 314 // Called on the socket thread to apply the mapping build on the main thread 315 // from the preference. 316 void ApplyPortRemapPreference(TPortRemapping const& portRemapping); 317 318 void OnKeepaliveEnabledPrefChange(); 319 void NotifyKeepaliveEnabledPrefChange(SocketContext* sock); 320 321 // Report socket status to about:networking 322 void AnalyzeConnection(nsTArray<SocketInfo>* data, SocketContext* context, 323 bool aActive); 324 325 void ClosePrivateConnections(); 326 void DetachSocketWithGuard(bool aGuardLocals, SocketContextList& socketList, 327 int32_t index); 328 329 void MarkTheLastElementOfPendingQueue(); 330 331 #if defined(XP_WIN) 332 Atomic<bool> mPolling{false}; 333 nsCOMPtr<nsITimer> mPollRepairTimer; 334 void StartPollWatchdog(); 335 void DoPollRepair(); 336 void StartPolling(); 337 void EndPolling(); 338 #endif 339 340 void TryRepairPollableEvent(); 341 342 CopyableTArray<nsCOMPtr<nsISTSShutdownObserver>> mShutdownObservers; 343 }; 344 345 extern nsSocketTransportService* gSocketTransportService; 346 bool OnSocketThread(); 347 348 } // namespace net 349 } // namespace mozilla 350 351 #endif // !nsSocketTransportService_h__