tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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__