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