nsSocketTransportService2.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. #ifndef nsSocketTransportService2_h__
  6. #define nsSocketTransportService2_h__
  7. #include "nsPISocketTransportService.h"
  8. #include "nsIThreadInternal.h"
  9. #include "nsIRunnable.h"
  10. #include "nsEventQueue.h"
  11. #include "nsCOMPtr.h"
  12. #include "prinrval.h"
  13. #include "mozilla/Logging.h"
  14. #include "prinit.h"
  15. #include "nsIObserver.h"
  16. #include "mozilla/LinkedList.h"
  17. #include "mozilla/Mutex.h"
  18. #include "mozilla/net/DashboardTypes.h"
  19. #include "mozilla/Atomics.h"
  20. #include "nsITimer.h"
  21. #include "mozilla/UniquePtr.h"
  22. #include "PollableEvent.h"
  23. class nsASocketHandler;
  24. struct PRPollDesc;
  25. class nsIPrefBranch;
  26. //-----------------------------------------------------------------------------
  27. namespace mozilla {
  28. namespace net {
  29. //
  30. // set MOZ_LOG=nsSocketTransport:5
  31. //
  32. extern LazyLogModule gSocketTransportLog;
  33. #define SOCKET_LOG(args) MOZ_LOG(gSocketTransportLog, LogLevel::Debug, args)
  34. #define SOCKET_LOG_ENABLED() MOZ_LOG_TEST(gSocketTransportLog, LogLevel::Debug)
  35. //
  36. // set MOZ_LOG=UDPSocket:5
  37. //
  38. extern LazyLogModule gUDPSocketLog;
  39. #define UDPSOCKET_LOG(args) MOZ_LOG(gUDPSocketLog, LogLevel::Debug, args)
  40. #define UDPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gUDPSocketLog, LogLevel::Debug)
  41. //-----------------------------------------------------------------------------
  42. #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT
  43. //-----------------------------------------------------------------------------
  44. // These maximums are borrowed from the linux kernel.
  45. static const int32_t kMaxTCPKeepIdle = 32767; // ~9 hours.
  46. static const int32_t kMaxTCPKeepIntvl = 32767;
  47. static const int32_t kMaxTCPKeepCount = 127;
  48. static const int32_t kDefaultTCPKeepCount =
  49. #if defined (XP_WIN)
  50. 10; // Hardcoded in Windows.
  51. #elif defined (XP_MACOSX)
  52. 8; // Hardcoded in OSX.
  53. #else
  54. 4; // Specifiable in Linux.
  55. #endif
  56. class LinkedRunnableEvent final : public LinkedListElement<LinkedRunnableEvent>
  57. {
  58. public:
  59. explicit LinkedRunnableEvent(nsIRunnable *event) : mEvent(event) {}
  60. ~LinkedRunnableEvent() {}
  61. already_AddRefed<nsIRunnable> TakeEvent()
  62. {
  63. return mEvent.forget();
  64. }
  65. private:
  66. nsCOMPtr<nsIRunnable> mEvent;
  67. };
  68. //-----------------------------------------------------------------------------
  69. class nsSocketTransportService final : public nsPISocketTransportService
  70. , public nsIEventTarget
  71. , public nsIThreadObserver
  72. , public nsIRunnable
  73. , public nsIObserver
  74. {
  75. public:
  76. NS_DECL_THREADSAFE_ISUPPORTS
  77. NS_DECL_NSPISOCKETTRANSPORTSERVICE
  78. NS_DECL_NSISOCKETTRANSPORTSERVICE
  79. NS_DECL_NSIROUTEDSOCKETTRANSPORTSERVICE
  80. NS_DECL_NSIEVENTTARGET
  81. NS_DECL_NSITHREADOBSERVER
  82. NS_DECL_NSIRUNNABLE
  83. NS_DECL_NSIOBSERVER
  84. using nsIEventTarget::Dispatch;
  85. nsSocketTransportService();
  86. // Max Socket count may need to get initialized/used by nsHttpHandler
  87. // before this class is initialized.
  88. static uint32_t gMaxCount;
  89. static PRCallOnceType gMaxCountInitOnce;
  90. static PRStatus DiscoverMaxCount();
  91. bool CanAttachSocket();
  92. // Called by the networking dashboard on the socket thread only
  93. // Fills the passed array with socket information
  94. void GetSocketConnections(nsTArray<SocketInfo> *);
  95. uint64_t GetSentBytes() { return mSentBytesCount; }
  96. uint64_t GetReceivedBytes() { return mReceivedBytesCount; }
  97. // Returns true if keepalives are enabled in prefs.
  98. bool IsKeepaliveEnabled() { return mKeepaliveEnabledPref; }
  99. PRIntervalTime MaxTimeForPrClosePref() {return mMaxTimeForPrClosePref; }
  100. protected:
  101. virtual ~nsSocketTransportService();
  102. private:
  103. //-------------------------------------------------------------------------
  104. // misc (any thread)
  105. //-------------------------------------------------------------------------
  106. nsCOMPtr<nsIThread> mThread; // protected by mLock
  107. UniquePtr<PollableEvent> mPollableEvent;
  108. // Returns mThread, protecting the get-and-addref with mLock
  109. already_AddRefed<nsIThread> GetThreadSafely();
  110. //-------------------------------------------------------------------------
  111. // initialization and shutdown (any thread)
  112. //-------------------------------------------------------------------------
  113. Mutex mLock;
  114. bool mInitialized;
  115. bool mShuttingDown;
  116. // indicates whether we are currently in the
  117. // process of shutting down
  118. bool mOffline;
  119. bool mGoingOffline;
  120. // Detaches all sockets.
  121. void Reset(bool aGuardLocals);
  122. nsresult ShutdownThread();
  123. //-------------------------------------------------------------------------
  124. // socket lists (socket thread only)
  125. //
  126. // only "active" sockets are on the poll list. the active list is kept
  127. // in sync with the poll list such that:
  128. //
  129. // mActiveList[k].mFD == mPollList[k+1].fd
  130. //
  131. // where k=0,1,2,...
  132. //-------------------------------------------------------------------------
  133. struct SocketContext
  134. {
  135. PRFileDesc *mFD;
  136. nsASocketHandler *mHandler;
  137. PRIntervalTime mPollStartEpoch; // Epoch timestamp when we started to poll this socket
  138. public:
  139. // Helper functions implementing a timeout mechanism.
  140. // Returns true if the socket has not been signalled in more than the desired
  141. // timeout for this socket (mHandler->mPollTimeout).
  142. bool IsTimedOut(PRIntervalTime now) const;
  143. // Records the epoch timestamp we started polling this socket. If the epoch is already
  144. // recorded, then it does nothing (i.e. does not re-arm) so it's safe to call whenever
  145. // this socket is put into the active polling list.
  146. void StartTimeout(PRIntervalTime now);
  147. // Turns off the timout calculation.
  148. void StopTimeout();
  149. // Returns the number of intervals from "now" after which this socket will timeout,
  150. // or 0 (zero) when it has already timed out. Returns NS_SOCKET_POLL_TIMEOUT
  151. // when there is no timeout set on the socket.
  152. PRIntervalTime TimeoutIn(PRIntervalTime now) const;
  153. // When a socket timeout is set to not time out and later set again to time out, it
  154. // is possible that mPollStartEpoch is not reset in-between. We have to manually
  155. // call this on every iteration over sockets to ensure the epoch timestamp is reset
  156. // and our socket bookkeeping remains accurate.
  157. void ResetTimeout();
  158. };
  159. SocketContext *mActiveList; /* mListSize entries */
  160. SocketContext *mIdleList; /* mListSize entries */
  161. nsIThread *mRawThread;
  162. uint32_t mActiveListSize;
  163. uint32_t mIdleListSize;
  164. uint32_t mActiveCount;
  165. uint32_t mIdleCount;
  166. nsresult DetachSocket(SocketContext *, SocketContext *);
  167. nsresult AddToIdleList(SocketContext *);
  168. nsresult AddToPollList(SocketContext *);
  169. void RemoveFromIdleList(SocketContext *);
  170. void RemoveFromPollList(SocketContext *);
  171. void MoveToIdleList(SocketContext *sock);
  172. void MoveToPollList(SocketContext *sock);
  173. bool GrowActiveList();
  174. bool GrowIdleList();
  175. void InitMaxCount();
  176. // Total bytes number transfered through all the sockets except active ones
  177. uint64_t mSentBytesCount;
  178. uint64_t mReceivedBytesCount;
  179. //-------------------------------------------------------------------------
  180. // poll list (socket thread only)
  181. //
  182. // first element of the poll list is mPollableEvent (or null if the pollable
  183. // event cannot be created).
  184. //-------------------------------------------------------------------------
  185. PRPollDesc *mPollList; /* mListSize + 1 entries */
  186. PRIntervalTime PollTimeout(PRIntervalTime now); // computes ideal poll timeout
  187. nsresult DoPollIteration();
  188. // perfoms a single poll iteration
  189. int32_t Poll(PRIntervalTime now);
  190. // calls PR_Poll. the out param
  191. // interval indicates the poll
  192. // duration in seconds.
  193. //-------------------------------------------------------------------------
  194. // pending socket queue - see NotifyWhenCanAttachSocket
  195. //-------------------------------------------------------------------------
  196. AutoCleanLinkedList<LinkedRunnableEvent> mPendingSocketQueue;
  197. // Preference Monitor for SendBufferSize and Keepalive prefs.
  198. nsresult UpdatePrefs();
  199. void UpdateSendBufferPref(nsIPrefBranch *);
  200. int32_t mSendBufferSize;
  201. // Number of seconds of connection is idle before first keepalive ping.
  202. int32_t mKeepaliveIdleTimeS;
  203. // Number of seconds between retries should keepalive pings fail.
  204. int32_t mKeepaliveRetryIntervalS;
  205. // Number of keepalive probes to send.
  206. int32_t mKeepaliveProbeCount;
  207. // True if TCP keepalive is enabled globally.
  208. bool mKeepaliveEnabledPref;
  209. Atomic<bool> mServingPendingQueue;
  210. Atomic<int32_t, Relaxed> mMaxTimePerPollIter;
  211. Atomic<PRIntervalTime, Relaxed> mMaxTimeForPrClosePref;
  212. Atomic<bool, Relaxed> mSleepPhase;
  213. nsCOMPtr<nsITimer> mAfterWakeUpTimer;
  214. void OnKeepaliveEnabledPrefChange();
  215. void NotifyKeepaliveEnabledPrefChange(SocketContext *sock);
  216. // Socket thread only for dynamically adjusting max socket size
  217. #if defined(XP_WIN)
  218. void ProbeMaxCount();
  219. #endif
  220. bool mProbedMaxCount;
  221. void AnalyzeConnection(nsTArray<SocketInfo> *data,
  222. SocketContext *context, bool aActive);
  223. void ClosePrivateConnections();
  224. void DetachSocketWithGuard(bool aGuardLocals,
  225. SocketContext *socketList,
  226. int32_t index);
  227. void MarkTheLastElementOfPendingQueue();
  228. #if defined(XP_WIN)
  229. Atomic<bool> mPolling;
  230. nsCOMPtr<nsITimer> mPollRepairTimer;
  231. void StartPollWatchdog();
  232. void DoPollRepair();
  233. void StartPolling();
  234. void EndPolling();
  235. #endif
  236. };
  237. extern nsSocketTransportService *gSocketTransportService;
  238. extern Atomic<PRThread*, Relaxed> gSocketThread;
  239. } // namespace net
  240. } // namespace mozilla
  241. #endif // !nsSocketTransportService_h__