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/SharedMemory.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
,
33 SharedMemory::Handle aShmemHandle
, SharedMemory
* aShmem
,
34 uint32_t aCapacity
, nsresult aPeerStatus
, uint32_t aOffset
,
37 void CloseInternal(DataPipeAutoLock
&, nsresult aStatus
) MOZ_REQUIRES(*mMutex
);
39 void AsyncWaitInternal(already_AddRefed
<nsIRunnable
> aCallback
,
40 already_AddRefed
<nsIEventTarget
> aTarget
,
41 bool aClosureOnly
) MOZ_EXCLUDES(*mMutex
);
43 // Like `nsWriteSegmentFun` or `nsReadSegmentFun`.
44 using ProcessSegmentFun
=
45 FunctionRef
<nsresult(Span
<char> aSpan
, uint32_t aProcessedThisCall
,
46 uint32_t* aProcessedCount
)>;
47 nsresult
ProcessSegmentsInternal(uint32_t aCount
,
48 ProcessSegmentFun aProcessSegment
,
49 uint32_t* aProcessedCount
)
50 MOZ_EXCLUDES(*mMutex
);
52 nsresult
CheckStatus(DataPipeAutoLock
&) MOZ_REQUIRES(*mMutex
);
54 nsCString
Describe(DataPipeAutoLock
&) MOZ_REQUIRES(*mMutex
);
56 // Thread safety helper to tell the analysis that `mLink->mMutex` is held when
58 void AssertSameMutex(const std::shared_ptr
<Mutex
>& aMutex
)
59 MOZ_REQUIRES(*mMutex
) MOZ_ASSERT_CAPABILITY(*aMutex
) {
60 MOZ_ASSERT(mMutex
== aMutex
);
63 virtual ~DataPipeBase();
65 const std::shared_ptr
<Mutex
> mMutex
;
66 nsresult mStatus
MOZ_GUARDED_BY(*mMutex
) = NS_OK
;
67 RefPtr
<DataPipeLink
> mLink
MOZ_GUARDED_BY(*mMutex
);
71 void DataPipeWrite(IPC::MessageWriter
* aWriter
, T
* aParam
);
74 bool DataPipeRead(IPC::MessageReader
* aReader
, RefPtr
<T
>* aResult
);
76 } // namespace data_pipe_detail
79 class DataPipeReceiver
;
81 #define NS_DATAPIPESENDER_IID \
83 0x6698ed77, 0x9fff, 0x425d, { \
84 0xb0, 0xa6, 0x1d, 0x30, 0x66, 0xee, 0xb8, 0x16 \
88 // Helper class for streaming data to another process.
89 class DataPipeSender final
: public nsIAsyncOutputStream
,
90 public data_pipe_detail::DataPipeBase
{
92 NS_DECLARE_STATIC_IID_ACCESSOR(NS_DATAPIPESENDER_IID
)
93 NS_DECL_THREADSAFE_ISUPPORTS
94 NS_DECL_NSIOUTPUTSTREAM
95 NS_DECL_NSIASYNCOUTPUTSTREAM
98 friend nsresult
NewDataPipe(uint32_t, DataPipeSender
**, DataPipeReceiver
**);
99 friend void data_pipe_detail::DataPipeWrite
<DataPipeSender
>(
100 IPC::MessageWriter
* aWriter
, DataPipeSender
* aParam
);
101 friend bool data_pipe_detail::DataPipeRead
<DataPipeSender
>(
102 IPC::MessageReader
* aReader
, RefPtr
<DataPipeSender
>* aResult
);
104 explicit DataPipeSender(nsresult aError
)
105 : data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError
) {}
106 DataPipeSender(ScopedPort aPort
, SharedMemory::Handle aShmemHandle
,
107 SharedMemory
* aShmem
, uint32_t aCapacity
, nsresult aPeerStatus
,
108 uint32_t aOffset
, uint32_t aAvailable
)
109 : data_pipe_detail::DataPipeBase(
110 /* aReceiverSide */ false, std::move(aPort
),
111 std::move(aShmemHandle
), aShmem
, aCapacity
, aPeerStatus
, aOffset
,
114 ~DataPipeSender() = default;
117 NS_DEFINE_STATIC_IID_ACCESSOR(DataPipeSender
, NS_DATAPIPESENDER_IID
)
119 #define NS_DATAPIPERECEIVER_IID \
121 0x0a185f83, 0x499e, 0x450c, { \
122 0x95, 0x82, 0x27, 0x67, 0xad, 0x6d, 0x64, 0xb5 \
126 // Helper class for streaming data from another process.
127 class DataPipeReceiver final
: public nsIAsyncInputStream
,
128 public nsIIPCSerializableInputStream
,
129 public data_pipe_detail::DataPipeBase
{
131 NS_DECLARE_STATIC_IID_ACCESSOR(NS_DATAPIPERECEIVER_IID
)
132 NS_DECL_THREADSAFE_ISUPPORTS
133 NS_DECL_NSIINPUTSTREAM
134 NS_DECL_NSIASYNCINPUTSTREAM
135 NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
138 friend nsresult
NewDataPipe(uint32_t, DataPipeSender
**, DataPipeReceiver
**);
139 friend void data_pipe_detail::DataPipeWrite
<DataPipeReceiver
>(
140 IPC::MessageWriter
* aWriter
, DataPipeReceiver
* aParam
);
141 friend bool data_pipe_detail::DataPipeRead
<DataPipeReceiver
>(
142 IPC::MessageReader
* aReader
, RefPtr
<DataPipeReceiver
>* aResult
);
144 explicit DataPipeReceiver(nsresult aError
)
145 : data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError
) {}
146 DataPipeReceiver(ScopedPort aPort
, SharedMemory::Handle aShmemHandle
,
147 SharedMemory
* aShmem
, uint32_t aCapacity
,
148 nsresult aPeerStatus
, uint32_t aOffset
, uint32_t aAvailable
)
149 : data_pipe_detail::DataPipeBase(
150 /* aReceiverSide */ true, std::move(aPort
), std::move(aShmemHandle
),
151 aShmem
, aCapacity
, aPeerStatus
, aOffset
, aAvailable
) {}
153 ~DataPipeReceiver() = default;
156 NS_DEFINE_STATIC_IID_ACCESSOR(DataPipeReceiver
, NS_DATAPIPERECEIVER_IID
)
158 constexpr uint32_t kDefaultDataPipeCapacity
= 64 * 1024;
161 * Create a new DataPipe pair. The sender and receiver ends of the pipe may be
162 * used to transfer data between processes. |aCapacity| is the capacity of the
163 * underlying ring buffer. If `0` is passed, `kDefaultDataPipeCapacity` will be
166 nsresult
NewDataPipe(uint32_t aCapacity
, DataPipeSender
** aSender
,
167 DataPipeReceiver
** aReceiver
);
170 } // namespace mozilla
175 struct ParamTraits
<mozilla::ipc::DataPipeSender
*> {
176 static void Write(MessageWriter
* aWriter
,
177 mozilla::ipc::DataPipeSender
* aParam
);
178 static bool Read(MessageReader
* aReader
,
179 RefPtr
<mozilla::ipc::DataPipeSender
>* aResult
);
183 struct ParamTraits
<mozilla::ipc::DataPipeReceiver
*> {
184 static void Write(MessageWriter
* aWriter
,
185 mozilla::ipc::DataPipeReceiver
* aParam
);
186 static bool Read(MessageReader
* aReader
,
187 RefPtr
<mozilla::ipc::DataPipeReceiver
>* aResult
);
192 #endif // mozilla_ipc_DataPipe_h