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
|
/* -*- 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 http://mozilla.org/MPL/2.0/. */
/**
* The multiplex stream concatenates a list of input streams into a single
* stream.
*/
#ifndef _nsMultiplexInputStream_h_
#define _nsMultiplexInputStream_h_
#include "nsIBufferedStreams.h"
#include "nsICloneableInputStream.h"
#include "nsIMultiplexInputStream.h"
#include "nsISeekableStream.h"
#include "nsCOMPtr.h"
#include "nsIIPCSerializableInputStream.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsIAsyncInputStream.h"
#include "nsIInputStreamLength.h"
#include "nsNetUtil.h"
#include "nsStreamUtils.h"
#define NS_MULTIPLEXINPUTSTREAM_CONTRACTID \
"@mozilla.org/io/multiplex-input-stream;1"
#define NS_MULTIPLEXINPUTSTREAM_CID \
{/* 565e3a2c-1dd2-11b2-8da1-b4cef17e568d */ \
0x565e3a2c, \
0x1dd2, \
0x11b2, \
{0x8d, 0xa1, 0xb4, 0xce, 0xf1, 0x7e, 0x56, 0x8d}}
extern nsresult nsMultiplexInputStreamConstructor(REFNSIID aIID,
void** aResult);
namespace mozilla {
class nsMultiplexInputStream final : public nsIMultiplexInputStream,
public nsISeekableStream,
public nsIIPCSerializableInputStream,
public nsICloneableInputStream,
public nsIAsyncInputStream,
public nsIInputStreamCallback,
public nsIInputStreamLength,
public nsIAsyncInputStreamLength {
public:
nsMultiplexInputStream();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIMULTIPLEXINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
// This is used for nsIAsyncInputStream::AsyncWait
void AsyncWaitCompleted();
// This is used for nsIAsyncInputStreamLength::AsyncLengthWait
void AsyncWaitCompleted(int64_t aLength, const MutexAutoLock& aProofOfLock)
MOZ_REQUIRES(mLock);
struct StreamData {
nsresult Initialize(nsIInputStream* aOriginalStream) {
mCurrentPos = 0;
mOriginalStream = aOriginalStream;
mBufferedStream = aOriginalStream;
if (!NS_InputStreamIsBuffered(mBufferedStream)) {
nsCOMPtr<nsIInputStream> bufferedStream;
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
mBufferedStream.forget(), 4096);
NS_ENSURE_SUCCESS(rv, rv);
mBufferedStream = bufferedStream;
}
mAsyncStream = do_QueryInterface(mBufferedStream);
mSeekableStream = do_QueryInterface(mBufferedStream);
return NS_OK;
}
nsCOMPtr<nsIInputStream> mOriginalStream;
// Equal to mOriginalStream or a wrap around the original stream to make it
// buffered.
nsCOMPtr<nsIInputStream> mBufferedStream;
// This can be null.
nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
// This can be null.
nsCOMPtr<nsISeekableStream> mSeekableStream;
uint64_t mCurrentPos;
};
Mutex& GetLock() MOZ_RETURN_CAPABILITY(mLock) { return mLock; }
private:
~nsMultiplexInputStream() = default;
void NextStream() MOZ_REQUIRES(mLock) {
++mCurrentStream;
mStartedReadingCurrent = false;
}
nsresult AsyncWaitInternal();
// This method updates mSeekableStreams, mTellableStreams,
// mIPCSerializableStreams and mCloneableStreams values.
void UpdateQIMap(StreamData& aStream) MOZ_REQUIRES(mLock);
struct MOZ_STACK_CLASS ReadSegmentsState {
nsCOMPtr<nsIInputStream> mThisStream;
uint32_t mOffset;
nsWriteSegmentFun mWriter;
void* mClosure;
bool mDone;
};
void SerializedComplexityInternal(uint32_t aMaxSize, uint32_t* aSizeUsed,
uint32_t* aPipes, uint32_t* aTransferables,
bool* aSerializeAsPipe);
static nsresult ReadSegCb(nsIInputStream* aIn, void* aClosure,
const char* aFromRawSegment, uint32_t aToOffset,
uint32_t aCount, uint32_t* aWriteCount);
bool IsSeekable() const;
bool IsIPCSerializable() const;
bool IsCloneable() const;
bool IsAsyncInputStream() const;
bool IsInputStreamLength() const;
bool IsAsyncInputStreamLength() const;
Mutex mLock; // Protects access to all data members.
nsTArray<StreamData> mStreams MOZ_GUARDED_BY(mLock);
uint32_t mCurrentStream MOZ_GUARDED_BY(mLock);
bool mStartedReadingCurrent MOZ_GUARDED_BY(mLock);
nsresult mStatus MOZ_GUARDED_BY(mLock);
nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback MOZ_GUARDED_BY(mLock);
uint32_t mAsyncWaitFlags MOZ_GUARDED_BY(mLock);
uint32_t mAsyncWaitRequestedCount MOZ_GUARDED_BY(mLock);
nsCOMPtr<nsIEventTarget> mAsyncWaitEventTarget MOZ_GUARDED_BY(mLock);
nsCOMPtr<nsIInputStreamLengthCallback> mAsyncWaitLengthCallback
MOZ_GUARDED_BY(mLock);
class AsyncWaitLengthHelper;
RefPtr<AsyncWaitLengthHelper> mAsyncWaitLengthHelper MOZ_GUARDED_BY(mLock);
uint32_t mSeekableStreams MOZ_GUARDED_BY(mLock);
uint32_t mIPCSerializableStreams MOZ_GUARDED_BY(mLock);
uint32_t mCloneableStreams MOZ_GUARDED_BY(mLock);
// These are Atomics so that we can check them in QueryInterface without
// taking a lock (to look at mStreams.Length() and the numbers above)
// With no streams added yet, all of these are possible
Atomic<bool, Relaxed> mIsSeekableStream{true};
Atomic<bool, Relaxed> mIsIPCSerializableStream{true};
Atomic<bool, Relaxed> mIsCloneableStream{true};
Atomic<bool, Relaxed> mIsAsyncInputStream{false};
Atomic<bool, Relaxed> mIsInputStreamLength{false};
Atomic<bool, Relaxed> mIsAsyncInputStreamLength{false};
};
} // namespace mozilla
#endif // _nsMultiplexInputStream_h_
|