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