123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- /* vim:set ts=4 sw=4 sts=4 ci et: */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef nsSocketTransportService2_h__
- #define nsSocketTransportService2_h__
- #include "nsPISocketTransportService.h"
- #include "nsIThreadInternal.h"
- #include "nsIRunnable.h"
- #include "nsEventQueue.h"
- #include "nsCOMPtr.h"
- #include "prinrval.h"
- #include "mozilla/Logging.h"
- #include "prinit.h"
- #include "nsIObserver.h"
- #include "mozilla/LinkedList.h"
- #include "mozilla/Mutex.h"
- #include "mozilla/net/DashboardTypes.h"
- #include "mozilla/Atomics.h"
- #include "nsITimer.h"
- #include "mozilla/UniquePtr.h"
- #include "PollableEvent.h"
- class nsASocketHandler;
- struct PRPollDesc;
- class nsIPrefBranch;
- //-----------------------------------------------------------------------------
- namespace mozilla {
- namespace net {
- //
- // set MOZ_LOG=nsSocketTransport:5
- //
- extern LazyLogModule gSocketTransportLog;
- #define SOCKET_LOG(args) MOZ_LOG(gSocketTransportLog, LogLevel::Debug, args)
- #define SOCKET_LOG_ENABLED() MOZ_LOG_TEST(gSocketTransportLog, LogLevel::Debug)
- //
- // set MOZ_LOG=UDPSocket:5
- //
- extern LazyLogModule gUDPSocketLog;
- #define UDPSOCKET_LOG(args) MOZ_LOG(gUDPSocketLog, LogLevel::Debug, args)
- #define UDPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gUDPSocketLog, LogLevel::Debug)
- //-----------------------------------------------------------------------------
- #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT
- //-----------------------------------------------------------------------------
- // These maximums are borrowed from the linux kernel.
- static const int32_t kMaxTCPKeepIdle = 32767; // ~9 hours.
- static const int32_t kMaxTCPKeepIntvl = 32767;
- static const int32_t kMaxTCPKeepCount = 127;
- static const int32_t kDefaultTCPKeepCount =
- #if defined (XP_WIN)
- 10; // Hardcoded in Windows.
- #elif defined (XP_MACOSX)
- 8; // Hardcoded in OSX.
- #else
- 4; // Specifiable in Linux.
- #endif
- class LinkedRunnableEvent final : public LinkedListElement<LinkedRunnableEvent>
- {
- public:
- explicit LinkedRunnableEvent(nsIRunnable *event) : mEvent(event) {}
- ~LinkedRunnableEvent() {}
- already_AddRefed<nsIRunnable> TakeEvent()
- {
- return mEvent.forget();
- }
- private:
- nsCOMPtr<nsIRunnable> mEvent;
- };
- //-----------------------------------------------------------------------------
- class nsSocketTransportService final : public nsPISocketTransportService
- , public nsIEventTarget
- , public nsIThreadObserver
- , public nsIRunnable
- , public nsIObserver
- {
- public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSPISOCKETTRANSPORTSERVICE
- NS_DECL_NSISOCKETTRANSPORTSERVICE
- NS_DECL_NSIROUTEDSOCKETTRANSPORTSERVICE
- NS_DECL_NSIEVENTTARGET
- NS_DECL_NSITHREADOBSERVER
- NS_DECL_NSIRUNNABLE
- NS_DECL_NSIOBSERVER
- using nsIEventTarget::Dispatch;
- nsSocketTransportService();
- // Max Socket count may need to get initialized/used by nsHttpHandler
- // before this class is initialized.
- static uint32_t gMaxCount;
- static PRCallOnceType gMaxCountInitOnce;
- static PRStatus DiscoverMaxCount();
- bool CanAttachSocket();
- // Called by the networking dashboard on the socket thread only
- // Fills the passed array with socket information
- void GetSocketConnections(nsTArray<SocketInfo> *);
- uint64_t GetSentBytes() { return mSentBytesCount; }
- uint64_t GetReceivedBytes() { return mReceivedBytesCount; }
- // Returns true if keepalives are enabled in prefs.
- bool IsKeepaliveEnabled() { return mKeepaliveEnabledPref; }
- PRIntervalTime MaxTimeForPrClosePref() {return mMaxTimeForPrClosePref; }
- protected:
- virtual ~nsSocketTransportService();
- private:
- //-------------------------------------------------------------------------
- // misc (any thread)
- //-------------------------------------------------------------------------
- nsCOMPtr<nsIThread> mThread; // protected by mLock
- UniquePtr<PollableEvent> mPollableEvent;
- // Returns mThread, protecting the get-and-addref with mLock
- already_AddRefed<nsIThread> GetThreadSafely();
- //-------------------------------------------------------------------------
- // initialization and shutdown (any thread)
- //-------------------------------------------------------------------------
- Mutex mLock;
- bool mInitialized;
- bool mShuttingDown;
- // indicates whether we are currently in the
- // process of shutting down
- bool mOffline;
- bool mGoingOffline;
- // Detaches all sockets.
- void Reset(bool aGuardLocals);
- nsresult ShutdownThread();
- //-------------------------------------------------------------------------
- // socket lists (socket thread only)
- //
- // only "active" sockets are on the poll list. the active list is kept
- // in sync with the poll list such that:
- //
- // mActiveList[k].mFD == mPollList[k+1].fd
- //
- // where k=0,1,2,...
- //-------------------------------------------------------------------------
- struct SocketContext
- {
- PRFileDesc *mFD;
- nsASocketHandler *mHandler;
- PRIntervalTime mPollStartEpoch; // Epoch timestamp when we started to poll this socket
- public:
- // Helper functions implementing a timeout mechanism.
-
- // Returns true if the socket has not been signalled in more than the desired
- // timeout for this socket (mHandler->mPollTimeout).
- bool IsTimedOut(PRIntervalTime now) const;
-
- // Records the epoch timestamp we started polling this socket. If the epoch is already
- // recorded, then it does nothing (i.e. does not re-arm) so it's safe to call whenever
- // this socket is put into the active polling list.
- void StartTimeout(PRIntervalTime now);
-
- // Turns off the timout calculation.
- void StopTimeout();
-
- // Returns the number of intervals from "now" after which this socket will timeout,
- // or 0 (zero) when it has already timed out. Returns NS_SOCKET_POLL_TIMEOUT
- // when there is no timeout set on the socket.
- PRIntervalTime TimeoutIn(PRIntervalTime now) const;
-
- // When a socket timeout is set to not time out and later set again to time out, it
- // is possible that mPollStartEpoch is not reset in-between. We have to manually
- // call this on every iteration over sockets to ensure the epoch timestamp is reset
- // and our socket bookkeeping remains accurate.
- void ResetTimeout();
- };
- SocketContext *mActiveList; /* mListSize entries */
- SocketContext *mIdleList; /* mListSize entries */
- nsIThread *mRawThread;
- uint32_t mActiveListSize;
- uint32_t mIdleListSize;
- uint32_t mActiveCount;
- uint32_t mIdleCount;
- nsresult DetachSocket(SocketContext *, SocketContext *);
- nsresult AddToIdleList(SocketContext *);
- nsresult AddToPollList(SocketContext *);
- void RemoveFromIdleList(SocketContext *);
- void RemoveFromPollList(SocketContext *);
- void MoveToIdleList(SocketContext *sock);
- void MoveToPollList(SocketContext *sock);
- bool GrowActiveList();
- bool GrowIdleList();
- void InitMaxCount();
- // Total bytes number transfered through all the sockets except active ones
- uint64_t mSentBytesCount;
- uint64_t mReceivedBytesCount;
- //-------------------------------------------------------------------------
- // poll list (socket thread only)
- //
- // first element of the poll list is mPollableEvent (or null if the pollable
- // event cannot be created).
- //-------------------------------------------------------------------------
- PRPollDesc *mPollList; /* mListSize + 1 entries */
- PRIntervalTime PollTimeout(PRIntervalTime now); // computes ideal poll timeout
- nsresult DoPollIteration();
- // perfoms a single poll iteration
- int32_t Poll(PRIntervalTime now);
- // calls PR_Poll. the out param
- // interval indicates the poll
- // duration in seconds.
- //-------------------------------------------------------------------------
- // pending socket queue - see NotifyWhenCanAttachSocket
- //-------------------------------------------------------------------------
- AutoCleanLinkedList<LinkedRunnableEvent> mPendingSocketQueue;
- // Preference Monitor for SendBufferSize and Keepalive prefs.
- nsresult UpdatePrefs();
- void UpdateSendBufferPref(nsIPrefBranch *);
- int32_t mSendBufferSize;
- // Number of seconds of connection is idle before first keepalive ping.
- int32_t mKeepaliveIdleTimeS;
- // Number of seconds between retries should keepalive pings fail.
- int32_t mKeepaliveRetryIntervalS;
- // Number of keepalive probes to send.
- int32_t mKeepaliveProbeCount;
- // True if TCP keepalive is enabled globally.
- bool mKeepaliveEnabledPref;
- Atomic<bool> mServingPendingQueue;
- Atomic<int32_t, Relaxed> mMaxTimePerPollIter;
- Atomic<PRIntervalTime, Relaxed> mMaxTimeForPrClosePref;
- Atomic<bool, Relaxed> mSleepPhase;
- nsCOMPtr<nsITimer> mAfterWakeUpTimer;
- void OnKeepaliveEnabledPrefChange();
- void NotifyKeepaliveEnabledPrefChange(SocketContext *sock);
- // Socket thread only for dynamically adjusting max socket size
- #if defined(XP_WIN)
- void ProbeMaxCount();
- #endif
- bool mProbedMaxCount;
- void AnalyzeConnection(nsTArray<SocketInfo> *data,
- SocketContext *context, bool aActive);
- void ClosePrivateConnections();
- void DetachSocketWithGuard(bool aGuardLocals,
- SocketContext *socketList,
- int32_t index);
- void MarkTheLastElementOfPendingQueue();
- #if defined(XP_WIN)
- Atomic<bool> mPolling;
- nsCOMPtr<nsITimer> mPollRepairTimer;
- void StartPollWatchdog();
- void DoPollRepair();
- void StartPolling();
- void EndPolling();
- #endif
- };
- extern nsSocketTransportService *gSocketTransportService;
- extern Atomic<PRThread*, Relaxed> gSocketThread;
- } // namespace net
- } // namespace mozilla
- #endif // !nsSocketTransportService_h__
|