tor-browser

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

DataPipe.h (6875B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_ipc_DataPipe_h
      8 #define mozilla_ipc_DataPipe_h
      9 
     10 #include "mozilla/ipc/SharedMemoryHandle.h"
     11 #include "mozilla/ipc/SharedMemoryMapping.h"
     12 #include "mozilla/ipc/NodeController.h"
     13 #include "nsIAsyncInputStream.h"
     14 #include "nsIAsyncOutputStream.h"
     15 #include "nsIIPCSerializableInputStream.h"
     16 #include "nsISupports.h"
     17 #include <memory>
     18 
     19 namespace mozilla {
     20 namespace ipc {
     21 
     22 namespace data_pipe_detail {
     23 
     24 class DataPipeAutoLock;
     25 class DataPipeLink;
     26 
     27 class DataPipeBase {
     28 public:
     29  DataPipeBase(const DataPipeBase&) = delete;
     30  DataPipeBase& operator=(const DataPipeBase&) = delete;
     31 
     32 protected:
     33  explicit DataPipeBase(bool aReceiverSide, nsresult aError);
     34  DataPipeBase(bool aReceiverSide, ScopedPort aPort,
     35               MutableSharedMemoryHandle&& aShmemHandle,
     36               const std::shared_ptr<SharedMemoryMapping>& aShmem,
     37               uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
     38               uint32_t aAvailable);
     39 
     40  void CloseInternal(DataPipeAutoLock&, nsresult aStatus) MOZ_REQUIRES(*mMutex);
     41 
     42  void AsyncWaitInternal(already_AddRefed<nsIRunnable> aCallback,
     43                         already_AddRefed<nsIEventTarget> aTarget,
     44                         bool aClosureOnly) MOZ_EXCLUDES(*mMutex);
     45 
     46  // Like `nsWriteSegmentFun` or `nsReadSegmentFun`.
     47  using ProcessSegmentFun =
     48      FunctionRef<nsresult(Span<char> aSpan, uint32_t aProcessedThisCall,
     49                           uint32_t* aProcessedCount)>;
     50  nsresult ProcessSegmentsInternal(uint32_t aCount,
     51                                   ProcessSegmentFun aProcessSegment,
     52                                   uint32_t* aProcessedCount)
     53      MOZ_EXCLUDES(*mMutex);
     54 
     55  nsresult CheckStatus(DataPipeAutoLock&) MOZ_REQUIRES(*mMutex);
     56 
     57  nsCString Describe(DataPipeAutoLock&) MOZ_REQUIRES(*mMutex);
     58 
     59  // Thread safety helper to tell the analysis that `mLink->mMutex` is held when
     60  // `mMutex` is held.
     61  void AssertSameMutex(const std::shared_ptr<Mutex>& aMutex)
     62      MOZ_REQUIRES(*mMutex) MOZ_ASSERT_CAPABILITY(*aMutex) {
     63    MOZ_ASSERT(mMutex == aMutex);
     64  }
     65 
     66  virtual ~DataPipeBase();
     67 
     68  const std::shared_ptr<Mutex> mMutex;
     69  nsresult mStatus MOZ_GUARDED_BY(*mMutex) = NS_OK;
     70  RefPtr<DataPipeLink> mLink MOZ_GUARDED_BY(*mMutex);
     71 };
     72 
     73 template <typename T>
     74 void DataPipeWrite(IPC::MessageWriter* aWriter, T* aParam);
     75 
     76 template <typename T>
     77 bool DataPipeRead(IPC::MessageReader* aReader, RefPtr<T>* aResult);
     78 
     79 }  // namespace data_pipe_detail
     80 
     81 class DataPipeSender;
     82 class DataPipeReceiver;
     83 
     84 #define NS_DATAPIPESENDER_IID \
     85  {0x6698ed77, 0x9fff, 0x425d, {0xb0, 0xa6, 0x1d, 0x30, 0x66, 0xee, 0xb8, 0x16}}
     86 
     87 // Helper class for streaming data to another process.
     88 class DataPipeSender final : public nsIAsyncOutputStream,
     89                             public data_pipe_detail::DataPipeBase {
     90 public:
     91  NS_INLINE_DECL_STATIC_IID(NS_DATAPIPESENDER_IID)
     92  NS_DECL_THREADSAFE_ISUPPORTS
     93  NS_DECL_NSIOUTPUTSTREAM
     94  NS_DECL_NSIASYNCOUTPUTSTREAM
     95 
     96 private:
     97  friend nsresult NewDataPipe(uint32_t, DataPipeSender**, DataPipeReceiver**);
     98  friend void data_pipe_detail::DataPipeWrite<DataPipeSender>(
     99      IPC::MessageWriter* aWriter, DataPipeSender* aParam);
    100  friend bool data_pipe_detail::DataPipeRead<DataPipeSender>(
    101      IPC::MessageReader* aReader, RefPtr<DataPipeSender>* aResult);
    102 
    103  explicit DataPipeSender(nsresult aError)
    104      : data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError) {}
    105  DataPipeSender(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle,
    106                 const std::shared_ptr<SharedMemoryMapping>& aShmem,
    107                 uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
    108                 uint32_t aAvailable)
    109      : data_pipe_detail::DataPipeBase(
    110            /* aReceiverSide */ false, std::move(aPort),
    111            std::move(aShmemHandle), aShmem, aCapacity, aPeerStatus, aOffset,
    112            aAvailable) {}
    113 
    114  ~DataPipeSender() = default;
    115 };
    116 
    117 #define NS_DATAPIPERECEIVER_IID \
    118  {0x0a185f83, 0x499e, 0x450c, {0x95, 0x82, 0x27, 0x67, 0xad, 0x6d, 0x64, 0xb5}}
    119 
    120 // Helper class for streaming data from another process.
    121 class DataPipeReceiver final : public nsIAsyncInputStream,
    122                               public nsIIPCSerializableInputStream,
    123                               public data_pipe_detail::DataPipeBase {
    124 public:
    125  NS_INLINE_DECL_STATIC_IID(NS_DATAPIPERECEIVER_IID)
    126  NS_DECL_THREADSAFE_ISUPPORTS
    127  NS_DECL_NSIINPUTSTREAM
    128  NS_DECL_NSIASYNCINPUTSTREAM
    129  NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
    130 
    131 private:
    132  friend nsresult NewDataPipe(uint32_t, DataPipeSender**, DataPipeReceiver**);
    133  friend void data_pipe_detail::DataPipeWrite<DataPipeReceiver>(
    134      IPC::MessageWriter* aWriter, DataPipeReceiver* aParam);
    135  friend bool data_pipe_detail::DataPipeRead<DataPipeReceiver>(
    136      IPC::MessageReader* aReader, RefPtr<DataPipeReceiver>* aResult);
    137 
    138  explicit DataPipeReceiver(nsresult aError)
    139      : data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError) {}
    140  DataPipeReceiver(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle,
    141                   const std::shared_ptr<SharedMemoryMapping>& aShmem,
    142                   uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
    143                   uint32_t aAvailable)
    144      : data_pipe_detail::DataPipeBase(
    145            /* aReceiverSide */ true, std::move(aPort), std::move(aShmemHandle),
    146            aShmem, aCapacity, aPeerStatus, aOffset, aAvailable) {}
    147 
    148  ~DataPipeReceiver() = default;
    149 };
    150 
    151 constexpr uint32_t kDefaultDataPipeCapacity = 64 * 1024;
    152 
    153 /**
    154 * Create a new DataPipe pair. The sender and receiver ends of the pipe may be
    155 * used to transfer data between processes. |aCapacity| is the capacity of the
    156 * underlying ring buffer. If `0` is passed, `kDefaultDataPipeCapacity` will be
    157 * used.
    158 */
    159 nsresult NewDataPipe(uint32_t aCapacity, DataPipeSender** aSender,
    160                     DataPipeReceiver** aReceiver);
    161 
    162 }  // namespace ipc
    163 }  // namespace mozilla
    164 
    165 namespace IPC {
    166 
    167 template <>
    168 struct ParamTraits<mozilla::ipc::DataPipeSender*> {
    169  static void Write(MessageWriter* aWriter,
    170                    mozilla::ipc::DataPipeSender* aParam);
    171  static bool Read(MessageReader* aReader,
    172                   RefPtr<mozilla::ipc::DataPipeSender>* aResult);
    173 };
    174 
    175 template <>
    176 struct ParamTraits<mozilla::ipc::DataPipeReceiver*> {
    177  static void Write(MessageWriter* aWriter,
    178                    mozilla::ipc::DataPipeReceiver* aParam);
    179  static bool Read(MessageReader* aReader,
    180                   RefPtr<mozilla::ipc::DataPipeReceiver>* aResult);
    181 };
    182 
    183 }  // namespace IPC
    184 
    185 #endif  // mozilla_ipc_DataPipe_h