Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* vim:set ts=4 sw=4 sts=4 ci et: */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef nsSocketTransportService2_h__ |
michael@0 | 7 | #define nsSocketTransportService2_h__ |
michael@0 | 8 | |
michael@0 | 9 | #include "nsPISocketTransportService.h" |
michael@0 | 10 | #include "nsIThreadInternal.h" |
michael@0 | 11 | #include "nsIRunnable.h" |
michael@0 | 12 | #include "nsEventQueue.h" |
michael@0 | 13 | #include "nsCOMPtr.h" |
michael@0 | 14 | #include "prinrval.h" |
michael@0 | 15 | #include "prlog.h" |
michael@0 | 16 | #include "prinit.h" |
michael@0 | 17 | #include "nsIObserver.h" |
michael@0 | 18 | #include "mozilla/Mutex.h" |
michael@0 | 19 | #include "mozilla/net/DashboardTypes.h" |
michael@0 | 20 | |
michael@0 | 21 | class nsASocketHandler; |
michael@0 | 22 | struct PRPollDesc; |
michael@0 | 23 | |
michael@0 | 24 | //----------------------------------------------------------------------------- |
michael@0 | 25 | |
michael@0 | 26 | #if defined(PR_LOGGING) |
michael@0 | 27 | // |
michael@0 | 28 | // set NSPR_LOG_MODULES=nsSocketTransport:5 |
michael@0 | 29 | // |
michael@0 | 30 | extern PRLogModuleInfo *gSocketTransportLog; |
michael@0 | 31 | #endif |
michael@0 | 32 | #define SOCKET_LOG(args) PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args) |
michael@0 | 33 | #define SOCKET_LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG) |
michael@0 | 34 | |
michael@0 | 35 | //----------------------------------------------------------------------------- |
michael@0 | 36 | |
michael@0 | 37 | #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT |
michael@0 | 38 | |
michael@0 | 39 | //----------------------------------------------------------------------------- |
michael@0 | 40 | |
michael@0 | 41 | namespace mozilla { |
michael@0 | 42 | namespace net { |
michael@0 | 43 | // These maximums are borrowed from the linux kernel. |
michael@0 | 44 | static const int32_t kMaxTCPKeepIdle = 32767; // ~9 hours. |
michael@0 | 45 | static const int32_t kMaxTCPKeepIntvl = 32767; |
michael@0 | 46 | static const int32_t kMaxTCPKeepCount = 127; |
michael@0 | 47 | static const int32_t kDefaultTCPKeepCount = |
michael@0 | 48 | #if defined (XP_WIN) |
michael@0 | 49 | 10; // Hardcoded in Windows. |
michael@0 | 50 | #elif defined (XP_MACOSX) |
michael@0 | 51 | 8; // Hardcoded in OSX. |
michael@0 | 52 | #else |
michael@0 | 53 | 4; // Specifiable in Linux. |
michael@0 | 54 | #endif |
michael@0 | 55 | } |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | //----------------------------------------------------------------------------- |
michael@0 | 59 | |
michael@0 | 60 | class nsSocketTransportService : public nsPISocketTransportService |
michael@0 | 61 | , public nsIEventTarget |
michael@0 | 62 | , public nsIThreadObserver |
michael@0 | 63 | , public nsIRunnable |
michael@0 | 64 | , public nsIObserver |
michael@0 | 65 | { |
michael@0 | 66 | typedef mozilla::Mutex Mutex; |
michael@0 | 67 | |
michael@0 | 68 | public: |
michael@0 | 69 | NS_DECL_THREADSAFE_ISUPPORTS |
michael@0 | 70 | NS_DECL_NSPISOCKETTRANSPORTSERVICE |
michael@0 | 71 | NS_DECL_NSISOCKETTRANSPORTSERVICE |
michael@0 | 72 | NS_DECL_NSIEVENTTARGET |
michael@0 | 73 | NS_DECL_NSITHREADOBSERVER |
michael@0 | 74 | NS_DECL_NSIRUNNABLE |
michael@0 | 75 | NS_DECL_NSIOBSERVER |
michael@0 | 76 | |
michael@0 | 77 | nsSocketTransportService(); |
michael@0 | 78 | |
michael@0 | 79 | // Max Socket count may need to get initialized/used by nsHttpHandler |
michael@0 | 80 | // before this class is initialized. |
michael@0 | 81 | static uint32_t gMaxCount; |
michael@0 | 82 | static PRCallOnceType gMaxCountInitOnce; |
michael@0 | 83 | static PRStatus DiscoverMaxCount(); |
michael@0 | 84 | |
michael@0 | 85 | // |
michael@0 | 86 | // the number of sockets that can be attached at any given time is |
michael@0 | 87 | // limited. this is done because some operating systems (e.g., Win9x) |
michael@0 | 88 | // limit the number of sockets that can be created by an application. |
michael@0 | 89 | // AttachSocket will fail if the limit is exceeded. consumers should |
michael@0 | 90 | // call CanAttachSocket and check the result before creating a socket. |
michael@0 | 91 | // |
michael@0 | 92 | bool CanAttachSocket() { |
michael@0 | 93 | return mActiveCount + mIdleCount < gMaxCount; |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | // Called by the networking dashboard on the socket thread only |
michael@0 | 97 | // Fills the passed array with socket information |
michael@0 | 98 | void GetSocketConnections(nsTArray<mozilla::net::SocketInfo> *); |
michael@0 | 99 | uint64_t GetSentBytes() { return mSentBytesCount; } |
michael@0 | 100 | uint64_t GetReceivedBytes() { return mReceivedBytesCount; } |
michael@0 | 101 | |
michael@0 | 102 | // Returns true if keepalives are enabled in prefs. |
michael@0 | 103 | bool IsKeepaliveEnabled() { return mKeepaliveEnabledPref; } |
michael@0 | 104 | protected: |
michael@0 | 105 | |
michael@0 | 106 | virtual ~nsSocketTransportService(); |
michael@0 | 107 | |
michael@0 | 108 | private: |
michael@0 | 109 | |
michael@0 | 110 | //------------------------------------------------------------------------- |
michael@0 | 111 | // misc (any thread) |
michael@0 | 112 | //------------------------------------------------------------------------- |
michael@0 | 113 | |
michael@0 | 114 | nsCOMPtr<nsIThread> mThread; // protected by mLock |
michael@0 | 115 | PRFileDesc *mThreadEvent; |
michael@0 | 116 | // protected by mLock. mThreadEvent may change |
michael@0 | 117 | // if the old pollable event is broken. only |
michael@0 | 118 | // the socket thread may change mThreadEvent; |
michael@0 | 119 | // it needs to lock mLock only when it changes |
michael@0 | 120 | // mThreadEvent. other threads don't change |
michael@0 | 121 | // mThreadEvent; they need to lock mLock |
michael@0 | 122 | // whenever they access mThreadEvent. |
michael@0 | 123 | bool mAutodialEnabled; |
michael@0 | 124 | // pref to control autodial code |
michael@0 | 125 | |
michael@0 | 126 | // Returns mThread, protecting the get-and-addref with mLock |
michael@0 | 127 | already_AddRefed<nsIThread> GetThreadSafely(); |
michael@0 | 128 | |
michael@0 | 129 | //------------------------------------------------------------------------- |
michael@0 | 130 | // initialization and shutdown (any thread) |
michael@0 | 131 | //------------------------------------------------------------------------- |
michael@0 | 132 | |
michael@0 | 133 | Mutex mLock; |
michael@0 | 134 | bool mInitialized; |
michael@0 | 135 | bool mShuttingDown; |
michael@0 | 136 | // indicates whether we are currently in the |
michael@0 | 137 | // process of shutting down |
michael@0 | 138 | bool mOffline; |
michael@0 | 139 | bool mGoingOffline; |
michael@0 | 140 | |
michael@0 | 141 | // Detaches all sockets. |
michael@0 | 142 | void Reset(bool aGuardLocals); |
michael@0 | 143 | |
michael@0 | 144 | //------------------------------------------------------------------------- |
michael@0 | 145 | // socket lists (socket thread only) |
michael@0 | 146 | // |
michael@0 | 147 | // only "active" sockets are on the poll list. the active list is kept |
michael@0 | 148 | // in sync with the poll list such that: |
michael@0 | 149 | // |
michael@0 | 150 | // mActiveList[k].mFD == mPollList[k+1].fd |
michael@0 | 151 | // |
michael@0 | 152 | // where k=0,1,2,... |
michael@0 | 153 | //------------------------------------------------------------------------- |
michael@0 | 154 | |
michael@0 | 155 | struct SocketContext |
michael@0 | 156 | { |
michael@0 | 157 | PRFileDesc *mFD; |
michael@0 | 158 | nsASocketHandler *mHandler; |
michael@0 | 159 | uint16_t mElapsedTime; // time elapsed w/o activity |
michael@0 | 160 | }; |
michael@0 | 161 | |
michael@0 | 162 | SocketContext *mActiveList; /* mListSize entries */ |
michael@0 | 163 | SocketContext *mIdleList; /* mListSize entries */ |
michael@0 | 164 | |
michael@0 | 165 | uint32_t mActiveListSize; |
michael@0 | 166 | uint32_t mIdleListSize; |
michael@0 | 167 | uint32_t mActiveCount; |
michael@0 | 168 | uint32_t mIdleCount; |
michael@0 | 169 | |
michael@0 | 170 | nsresult DetachSocket(SocketContext *, SocketContext *); |
michael@0 | 171 | nsresult AddToIdleList(SocketContext *); |
michael@0 | 172 | nsresult AddToPollList(SocketContext *); |
michael@0 | 173 | void RemoveFromIdleList(SocketContext *); |
michael@0 | 174 | void RemoveFromPollList(SocketContext *); |
michael@0 | 175 | void MoveToIdleList(SocketContext *sock); |
michael@0 | 176 | void MoveToPollList(SocketContext *sock); |
michael@0 | 177 | |
michael@0 | 178 | bool GrowActiveList(); |
michael@0 | 179 | bool GrowIdleList(); |
michael@0 | 180 | void InitMaxCount(); |
michael@0 | 181 | |
michael@0 | 182 | // Total bytes number transfered through all the sockets except active ones |
michael@0 | 183 | uint64_t mSentBytesCount; |
michael@0 | 184 | uint64_t mReceivedBytesCount; |
michael@0 | 185 | //------------------------------------------------------------------------- |
michael@0 | 186 | // poll list (socket thread only) |
michael@0 | 187 | // |
michael@0 | 188 | // first element of the poll list is mThreadEvent (or null if the pollable |
michael@0 | 189 | // event cannot be created). |
michael@0 | 190 | //------------------------------------------------------------------------- |
michael@0 | 191 | |
michael@0 | 192 | PRPollDesc *mPollList; /* mListSize + 1 entries */ |
michael@0 | 193 | |
michael@0 | 194 | PRIntervalTime PollTimeout(); // computes ideal poll timeout |
michael@0 | 195 | nsresult DoPollIteration(bool wait); |
michael@0 | 196 | // perfoms a single poll iteration |
michael@0 | 197 | int32_t Poll(bool wait, uint32_t *interval); |
michael@0 | 198 | // calls PR_Poll. the out param |
michael@0 | 199 | // interval indicates the poll |
michael@0 | 200 | // duration in seconds. |
michael@0 | 201 | |
michael@0 | 202 | //------------------------------------------------------------------------- |
michael@0 | 203 | // pending socket queue - see NotifyWhenCanAttachSocket |
michael@0 | 204 | //------------------------------------------------------------------------- |
michael@0 | 205 | |
michael@0 | 206 | nsEventQueue mPendingSocketQ; // queue of nsIRunnable objects |
michael@0 | 207 | |
michael@0 | 208 | // Preference Monitor for SendBufferSize and Keepalive prefs. |
michael@0 | 209 | nsresult UpdatePrefs(); |
michael@0 | 210 | int32_t mSendBufferSize; |
michael@0 | 211 | // Number of seconds of connection is idle before first keepalive ping. |
michael@0 | 212 | int32_t mKeepaliveIdleTimeS; |
michael@0 | 213 | // Number of seconds between retries should keepalive pings fail. |
michael@0 | 214 | int32_t mKeepaliveRetryIntervalS; |
michael@0 | 215 | // Number of keepalive probes to send. |
michael@0 | 216 | int32_t mKeepaliveProbeCount; |
michael@0 | 217 | // True if TCP keepalive is enabled globally. |
michael@0 | 218 | bool mKeepaliveEnabledPref; |
michael@0 | 219 | |
michael@0 | 220 | void OnKeepaliveEnabledPrefChange(); |
michael@0 | 221 | void NotifyKeepaliveEnabledPrefChange(SocketContext *sock); |
michael@0 | 222 | |
michael@0 | 223 | // Socket thread only for dynamically adjusting max socket size |
michael@0 | 224 | #if defined(XP_WIN) |
michael@0 | 225 | void ProbeMaxCount(); |
michael@0 | 226 | #endif |
michael@0 | 227 | bool mProbedMaxCount; |
michael@0 | 228 | |
michael@0 | 229 | void AnalyzeConnection(nsTArray<mozilla::net::SocketInfo> *data, |
michael@0 | 230 | SocketContext *context, bool aActive); |
michael@0 | 231 | |
michael@0 | 232 | void ClosePrivateConnections(); |
michael@0 | 233 | void DetachSocketWithGuard(bool aGuardLocals, |
michael@0 | 234 | SocketContext *socketList, |
michael@0 | 235 | int32_t index); |
michael@0 | 236 | }; |
michael@0 | 237 | |
michael@0 | 238 | extern nsSocketTransportService *gSocketTransportService; |
michael@0 | 239 | extern PRThread *gSocketThread; |
michael@0 | 240 | |
michael@0 | 241 | #endif // !nsSocketTransportService_h__ |