/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */
/** * Both blocking/non-blocking mode are supported in this class. * The default mode is non-blocking mode, however, the client may change its * mode to blocking mode during hand-shaking (e.g. nsSOCKSSocketInfo). * * In non-blocking mode, |Read| and |Write| should be called by clients only * when |GetPollFlags| reports data availability. That is, the client calls * |GetPollFlags| with |PR_POLL_READ| and/or |PR_POLL_WRITE| set, and * according to the flags that set, |GetPollFlags| will check buffers status * and decide corresponding actions: * * ------------------------------------------------------------------- * | | data in buffer | empty buffer | * |---------------+-------------------------+-----------------------| * | PR_POLL_READ | out: PR_POLL_READ | DoRead/DoReadContinue | * |---------------+-------------------------+-----------------------| * | PR_POLL_WRITE | DoWrite/DoWriteContinue | out: PR_POLL_WRITE | * ------------------------------------------+------------------------ * * |DoRead| and |DoWrite| initiate read/write operations asynchronously, and * the |DoReadContinue| and |DoWriteContinue| are used to check the amount * of the data are read/written to/from buffers. * * The output parameter and the return value of |GetPollFlags| are identical * because we don't rely on the low-level select function to wait for data * availability, we instead use nsNamedPipeService to poll I/O completeness. * * When client get |PR_POLL_READ| or |PR_POLL_WRITE| from |GetPollFlags|, * they are able to use |Read| or |Write| to access the data in the buffer, * and this is supposed to be very fast because no network traffic is * involved. * * In blocking mode, the flow is quite similar to non-blocking mode, but * |DoReadContinue| and |DoWriteContinue| are never been used since the * operations are done synchronously, which could lead to slow responses.
*/
int32_t Read(void* aBuffer, int32_t aSize);
int32_t Write(constvoid* aBuffer, int32_t aSize);
// Like Read, but doesn't remove data in internal buffer.
uint32_t Peek(void* aBuffer, int32_t aSize);
// Number of bytes available to read in internal buffer.
int32_t Available() const;
// Flush write buffer // // @return whether the buffer has been flushed bool Sync(uint32_t aTimeout); void SetNonblocking(bool nonblocking);
// Initiate and check current status for read/write operations.
int16_t GetPollFlags(int16_t aInFlags, int16_t* aOutFlags);
private: virtual ~NamedPipeInfo();
/** * DoRead/DoWrite starts a read/write call synchronously or asynchronously * depending on |mNonblocking|. In blocking mode, they return when the action * has been done and in non-blocking mode it returns the number of bytes that * were read/written if the operation is done immediately. If it takes some * time to finish the operation, zero is returned and * DoReadContinue/DoWriteContinue must be called to get async I/O result.
*/
int32_t DoRead();
int32_t DoReadContinue();
int32_t DoWrite();
int32_t DoWriteContinue();
/** * There was a write size limitation of named pipe, * see https://support.microsoft.com/en-us/kb/119218 for more information. * The limitation no longer exists, so feel free to change the value.
*/ staticconst uint32_t kBufferSize = 65536;
nsCOMPtr<nsINamedPipeService> mNamedPipeService;
HANDLE mPipe; // the handle to the named pipe.
OVERLAPPED mReadOverlapped; // used for asynchronous read operations.
OVERLAPPED mWriteOverlapped; // used for asynchronous write operations.
uint8_t mReadBuffer[kBufferSize]; // octets read from pipe.
/** * These indicates the [begin, end) position of the data in the buffer.
*/
DWORD mReadBegin;
DWORD mReadEnd;
bool mHasPendingRead; // previous asynchronous read is not finished yet.
uint8_t mWriteBuffer[kBufferSize]; // octets to be written to pipe.
/** * These indicates the [begin, end) position of the data in the buffer.
*/
DWORD mWriteBegin; // how many bytes are already written.
DWORD mWriteEnd; // valid amount of data in the buffer.
bool mHasPendingWrite; // previous asynchronous write is not finished yet.
/** * current blocking mode is non-blocking or not, accessed only in socket * thread.
*/ bool mNonblocking;
Atomic<DWORD> mErrorCode; // error code from Named Pipe Service.
};
/** * Triggers internal write operation by calling |GetPollFlags|. * This is required for callers that use blocking I/O because they don't call * |GetPollFlags| to write data, but this also works for non-blocking I/O.
*/
int16_t outFlag;
GetPollFlags(PR_POLL_WRITE, &outFlag);
/** * If there's nothing in the read buffer, try to trigger internal read * operation by calling |GetPollFlags|. This is required for callers that * use blocking I/O because they don't call |GetPollFlags| to read data, * but this also works for non-blocking I/O.
*/ if (!Available()) {
int16_t outFlag;
GetPollFlags(PR_POLL_READ, &outFlag);
// Available() can't return more than what fits to the buffer at the read // offset.
int32_t bytesRead = std::min<int32_t>(aSize, Available());
MOZ_ASSERT(bytesRead >= 0);
MOZ_ASSERT(mReadBegin + bytesRead <= mReadEnd);
memcpy(aBuffer, &mReadBuffer[mReadBegin], bytesRead); return bytesRead;
}
int32_t NamedPipeInfo::Available() const {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
MOZ_ASSERT(mReadBegin <= mReadEnd);
MOZ_ASSERT(mReadEnd - mReadBegin <= 0x7FFFFFFF); // no more than int32_max return mReadEnd - mReadBegin;
}
bool NamedPipeInfo::Sync(uint32_t aTimeout) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread"); if (!mHasPendingWrite) { returntrue;
} return WaitForSingleObject(mWriteOverlapped.hEvent, aTimeout) ==
WAIT_OBJECT_0;
}
if (aInFlags & PR_POLL_READ) {
int32_t bytesToRead = 0; if (mReadBegin < mReadEnd) { // data in buffer and is ready to be read
bytesToRead = Available();
} elseif (mHasPendingRead) { // nonblocking I/O and has pending task
bytesToRead = DoReadContinue();
} else { // read bufer is empty.
bytesToRead = DoRead();
}
// @return: data has been read and is available
int32_t NamedPipeInfo::DoRead() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
MOZ_ASSERT(!mHasPendingRead);
MOZ_ASSERT(mReadBegin == mReadEnd); // the buffer should be empty
RefPtr<NamedPipeInfo> info = new NamedPipeInfo();
layer->secret = reinterpret_cast<PRFilePrivate*>(info.forget().take());
return layer;
}
} // namespace net
} // namespace mozilla
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.34Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.