netwerk/base/src/nsSyncStreamListener.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "nsIOService.h"
michael@0 6 #include "nsSyncStreamListener.h"
michael@0 7 #include "nsIPipe.h"
michael@0 8 #include "nsThreadUtils.h"
michael@0 9 #include <algorithm>
michael@0 10
michael@0 11 nsresult
michael@0 12 nsSyncStreamListener::Init()
michael@0 13 {
michael@0 14 return NS_NewPipe(getter_AddRefs(mPipeIn),
michael@0 15 getter_AddRefs(mPipeOut),
michael@0 16 nsIOService::gDefaultSegmentSize,
michael@0 17 UINT32_MAX, // no size limit
michael@0 18 false,
michael@0 19 false);
michael@0 20 }
michael@0 21
michael@0 22 nsresult
michael@0 23 nsSyncStreamListener::WaitForData()
michael@0 24 {
michael@0 25 mKeepWaiting = true;
michael@0 26
michael@0 27 while (mKeepWaiting)
michael@0 28 NS_ENSURE_STATE(NS_ProcessNextEvent(NS_GetCurrentThread()));
michael@0 29
michael@0 30 return NS_OK;
michael@0 31 }
michael@0 32
michael@0 33 //-----------------------------------------------------------------------------
michael@0 34 // nsSyncStreamListener::nsISupports
michael@0 35 //-----------------------------------------------------------------------------
michael@0 36
michael@0 37 NS_IMPL_ISUPPORTS(nsSyncStreamListener,
michael@0 38 nsIStreamListener,
michael@0 39 nsIRequestObserver,
michael@0 40 nsIInputStream,
michael@0 41 nsISyncStreamListener)
michael@0 42
michael@0 43 //-----------------------------------------------------------------------------
michael@0 44 // nsSyncStreamListener::nsISyncStreamListener
michael@0 45 //-----------------------------------------------------------------------------
michael@0 46
michael@0 47 NS_IMETHODIMP
michael@0 48 nsSyncStreamListener::GetInputStream(nsIInputStream **result)
michael@0 49 {
michael@0 50 NS_ADDREF(*result = this);
michael@0 51 return NS_OK;
michael@0 52 }
michael@0 53
michael@0 54 //-----------------------------------------------------------------------------
michael@0 55 // nsSyncStreamListener::nsIStreamListener
michael@0 56 //-----------------------------------------------------------------------------
michael@0 57
michael@0 58 NS_IMETHODIMP
michael@0 59 nsSyncStreamListener::OnStartRequest(nsIRequest *request,
michael@0 60 nsISupports *context)
michael@0 61 {
michael@0 62 return NS_OK;
michael@0 63 }
michael@0 64
michael@0 65 NS_IMETHODIMP
michael@0 66 nsSyncStreamListener::OnDataAvailable(nsIRequest *request,
michael@0 67 nsISupports *context,
michael@0 68 nsIInputStream *stream,
michael@0 69 uint64_t offset,
michael@0 70 uint32_t count)
michael@0 71 {
michael@0 72 uint32_t bytesWritten;
michael@0 73
michael@0 74 nsresult rv = mPipeOut->WriteFrom(stream, count, &bytesWritten);
michael@0 75
michael@0 76 // if we get an error, then return failure. this will cause the
michael@0 77 // channel to be canceled, and as a result our OnStopRequest method
michael@0 78 // will be called immediately. because of this we do not need to
michael@0 79 // set mStatus or mKeepWaiting here.
michael@0 80 if (NS_FAILED(rv))
michael@0 81 return rv;
michael@0 82
michael@0 83 // we expect that all data will be written to the pipe because
michael@0 84 // the pipe was created to have "infinite" room.
michael@0 85 NS_ASSERTION(bytesWritten == count, "did not write all data");
michael@0 86
michael@0 87 mKeepWaiting = false; // unblock Read
michael@0 88 return NS_OK;
michael@0 89 }
michael@0 90
michael@0 91 NS_IMETHODIMP
michael@0 92 nsSyncStreamListener::OnStopRequest(nsIRequest *request,
michael@0 93 nsISupports *context,
michael@0 94 nsresult status)
michael@0 95 {
michael@0 96 mStatus = status;
michael@0 97 mKeepWaiting = false; // unblock Read
michael@0 98 mDone = true;
michael@0 99 return NS_OK;
michael@0 100 }
michael@0 101
michael@0 102 //-----------------------------------------------------------------------------
michael@0 103 // nsSyncStreamListener::nsIInputStream
michael@0 104 //-----------------------------------------------------------------------------
michael@0 105
michael@0 106 NS_IMETHODIMP
michael@0 107 nsSyncStreamListener::Close()
michael@0 108 {
michael@0 109 mStatus = NS_BASE_STREAM_CLOSED;
michael@0 110 mDone = true;
michael@0 111
michael@0 112 // It'd be nice if we could explicitly cancel the request at this point,
michael@0 113 // but we don't have a reference to it, so the best we can do is close the
michael@0 114 // pipe so that the next OnDataAvailable event will fail.
michael@0 115 if (mPipeIn) {
michael@0 116 mPipeIn->Close();
michael@0 117 mPipeIn = nullptr;
michael@0 118 }
michael@0 119 return NS_OK;
michael@0 120 }
michael@0 121
michael@0 122 NS_IMETHODIMP
michael@0 123 nsSyncStreamListener::Available(uint64_t *result)
michael@0 124 {
michael@0 125 if (NS_FAILED(mStatus))
michael@0 126 return mStatus;
michael@0 127
michael@0 128 mStatus = mPipeIn->Available(result);
michael@0 129 if (NS_SUCCEEDED(mStatus) && (*result == 0) && !mDone) {
michael@0 130 mStatus = WaitForData();
michael@0 131 if (NS_SUCCEEDED(mStatus))
michael@0 132 mStatus = mPipeIn->Available(result);
michael@0 133 }
michael@0 134 return mStatus;
michael@0 135 }
michael@0 136
michael@0 137 NS_IMETHODIMP
michael@0 138 nsSyncStreamListener::Read(char *buf,
michael@0 139 uint32_t bufLen,
michael@0 140 uint32_t *result)
michael@0 141 {
michael@0 142 if (mStatus == NS_BASE_STREAM_CLOSED) {
michael@0 143 *result = 0;
michael@0 144 return NS_OK;
michael@0 145 }
michael@0 146
michael@0 147 uint64_t avail64;
michael@0 148 if (NS_FAILED(Available(&avail64)))
michael@0 149 return mStatus;
michael@0 150
michael@0 151 uint32_t avail = (uint32_t)std::min(avail64, (uint64_t)bufLen);
michael@0 152 mStatus = mPipeIn->Read(buf, avail, result);
michael@0 153 return mStatus;
michael@0 154 }
michael@0 155
michael@0 156 NS_IMETHODIMP
michael@0 157 nsSyncStreamListener::ReadSegments(nsWriteSegmentFun writer,
michael@0 158 void *closure,
michael@0 159 uint32_t count,
michael@0 160 uint32_t *result)
michael@0 161 {
michael@0 162 if (mStatus == NS_BASE_STREAM_CLOSED) {
michael@0 163 *result = 0;
michael@0 164 return NS_OK;
michael@0 165 }
michael@0 166
michael@0 167 uint64_t avail64;
michael@0 168 if (NS_FAILED(Available(&avail64)))
michael@0 169 return mStatus;
michael@0 170
michael@0 171 uint32_t avail = (uint32_t)std::min(avail64, (uint64_t)count);
michael@0 172 mStatus = mPipeIn->ReadSegments(writer, closure, avail, result);
michael@0 173 return mStatus;
michael@0 174 }
michael@0 175
michael@0 176 NS_IMETHODIMP
michael@0 177 nsSyncStreamListener::IsNonBlocking(bool *result)
michael@0 178 {
michael@0 179 *result = false;
michael@0 180 return NS_OK;
michael@0 181 }

mercurial