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/. */
7 #ifndef mozilla_ipc_DataPipe_h
8 #define mozilla_ipc_DataPipe_h
10 #include "mozilla/ipc/SharedMemoryBasic.h"
11 #include "mozilla/ipc/NodeController.h"
12 #include "nsIAsyncInputStream.h"
13 #include "nsIAsyncOutputStream.h"
14 #include "nsIIPCSerializableInputStream.h"
15 #include "nsISupports.h"
20 namespace data_pipe_detail
{
22 class DataPipeAutoLock
;
27 DataPipeBase(const DataPipeBase
&) = delete;
28 DataPipeBase
& operator=(const DataPipeBase
&) = delete;
31 explicit DataPipeBase(bool aReceiverSide
, nsresult aError
);
32 DataPipeBase(bool aReceiverSide
, ScopedPort aPort
, SharedMemory
* aShmem
,
33 uint32_t aCapacity
, nsresult aPeerStatus
, uint32_t aOffset
,
36 void CloseInternal(DataPipeAutoLock
&, nsresult aStatus
) MOZ_REQUIRES(*mMutex
);
38 void AsyncWaitInternal(already_AddRefed
<nsIRunnable
> aCallback
,
39 already_AddRefed
<nsIEventTarget
> aTarget
,
40 bool aClosureOnly
) MOZ_EXCLUDES(*mMutex
);
42 // Like `nsWriteSegmentFun` or `nsReadSegmentFun`.
43 using ProcessSegmentFun
=
44 FunctionRef
<nsresult(Span
<char> aSpan
, uint32_t aProcessedThisCall
,
45 uint32_t* aProcessedCount
)>;
46 nsresult
ProcessSegmentsInternal(uint32_t aCount
,
47 ProcessSegmentFun aProcessSegment
,
48 uint32_t* aProcessedCount
)
49 MOZ_EXCLUDES(*mMutex
);
51 nsresult
CheckStatus(DataPipeAutoLock
&) MOZ_REQUIRES(*mMutex
);
53 nsCString
Describe(DataPipeAutoLock
&) MOZ_REQUIRES(*mMutex
);
55 // Thread safety helper to tell the analysis that `mLink->mMutex` is held when
57 void AssertSameMutex(const std::shared_ptr
<Mutex
>& aMutex
)
58 MOZ_REQUIRES(*mMutex
) MOZ_ASSERT_CAPABILITY(*aMutex
) {
59 MOZ_ASSERT(mMutex
== aMutex
);
62 virtual ~DataPipeBase();
64 const std::shared_ptr
<Mutex
> mMutex
;
65 nsresult mStatus
MOZ_GUARDED_BY(*mMutex
) = NS_OK
;
66 RefPtr
<DataPipeLink
> mLink
MOZ_GUARDED_BY(*mMutex
);
70 void DataPipeWrite(IPC::MessageWriter
* aWriter
, T
* aParam
);
73 bool DataPipeRead(IPC::MessageReader
* aReader
, RefPtr
<T
>* aResult
);
75 } // namespace data_pipe_detail
78 class DataPipeReceiver
;
80 #define NS_DATAPIPESENDER_IID \
82 0x6698ed77, 0x9fff, 0x425d, { \
83 0xb0, 0xa6, 0x1d, 0x30, 0x66, 0xee, 0xb8, 0x16 \
87 // Helper class for streaming data to another process.
88 class DataPipeSender final
: public nsIAsyncOutputStream
,
89 public data_pipe_detail::DataPipeBase
{
91 NS_DECLARE_STATIC_IID_ACCESSOR(NS_DATAPIPESENDER_IID
)
92 NS_DECL_THREADSAFE_ISUPPORTS
93 NS_DECL_NSIOUTPUTSTREAM
94 NS_DECL_NSIASYNCOUTPUTSTREAM
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
);
103 explicit DataPipeSender(nsresult aError
)
104 : data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError
) {}
105 DataPipeSender(ScopedPort aPort
, SharedMemory
* aShmem
, uint32_t aCapacity
,
106 nsresult aPeerStatus
, uint32_t aOffset
, uint32_t aAvailable
)
107 : data_pipe_detail::DataPipeBase(/* aReceiverSide */ false,
108 std::move(aPort
), aShmem
, aCapacity
,
109 aPeerStatus
, aOffset
, aAvailable
) {}
111 ~DataPipeSender() = default;
114 NS_DEFINE_STATIC_IID_ACCESSOR(DataPipeSender
, NS_DATAPIPESENDER_IID
)
116 #define NS_DATAPIPERECEIVER_IID \
118 0x0a185f83, 0x499e, 0x450c, { \
119 0x95, 0x82, 0x27, 0x67, 0xad, 0x6d, 0x64, 0xb5 \
123 // Helper class for streaming data from another process.
124 class DataPipeReceiver final
: public nsIAsyncInputStream
,
125 public nsIIPCSerializableInputStream
,
126 public data_pipe_detail::DataPipeBase
{
128 NS_DECLARE_STATIC_IID_ACCESSOR(NS_DATAPIPERECEIVER_IID
)
129 NS_DECL_THREADSAFE_ISUPPORTS
130 NS_DECL_NSIINPUTSTREAM
131 NS_DECL_NSIASYNCINPUTSTREAM
132 NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
135 friend nsresult
NewDataPipe(uint32_t, DataPipeSender
**, DataPipeReceiver
**);
136 friend void data_pipe_detail::DataPipeWrite
<DataPipeReceiver
>(
137 IPC::MessageWriter
* aWriter
, DataPipeReceiver
* aParam
);
138 friend bool data_pipe_detail::DataPipeRead
<DataPipeReceiver
>(
139 IPC::MessageReader
* aReader
, RefPtr
<DataPipeReceiver
>* aResult
);
141 explicit DataPipeReceiver(nsresult aError
)
142 : data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError
) {}
143 DataPipeReceiver(ScopedPort aPort
, SharedMemory
* aShmem
, uint32_t aCapacity
,
144 nsresult aPeerStatus
, uint32_t aOffset
, uint32_t aAvailable
)
145 : data_pipe_detail::DataPipeBase(/* aReceiverSide */ true,
146 std::move(aPort
), aShmem
, aCapacity
,
147 aPeerStatus
, aOffset
, aAvailable
) {}
149 ~DataPipeReceiver() = default;
152 NS_DEFINE_STATIC_IID_ACCESSOR(DataPipeReceiver
, NS_DATAPIPERECEIVER_IID
)
154 constexpr uint32_t kDefaultDataPipeCapacity
= 64 * 1024;
157 * Create a new DataPipe pair. The sender and receiver ends of the pipe may be
158 * used to transfer data between processes. |aCapacity| is the capacity of the
159 * underlying ring buffer. If `0` is passed, `kDefaultDataPipeCapacity` will be
162 nsresult
NewDataPipe(uint32_t aCapacity
, DataPipeSender
** aSender
,
163 DataPipeReceiver
** aReceiver
);
166 } // namespace mozilla
171 struct ParamTraits
<mozilla::ipc::DataPipeSender
*> {
172 static void Write(MessageWriter
* aWriter
,
173 mozilla::ipc::DataPipeSender
* aParam
);
174 static bool Read(MessageReader
* aReader
,
175 RefPtr
<mozilla::ipc::DataPipeSender
>* aResult
);
179 struct ParamTraits
<mozilla::ipc::DataPipeReceiver
*> {
180 static void Write(MessageWriter
* aWriter
,
181 mozilla::ipc::DataPipeReceiver
* aParam
);
182 static bool Read(MessageReader
* aReader
,
183 RefPtr
<mozilla::ipc::DataPipeReceiver
>* aResult
);
188 #endif // mozilla_ipc_DataPipe_h