netwerk/base/src/nsSyncStreamListener.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/base/src/nsSyncStreamListener.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,181 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "nsIOService.h"
     1.9 +#include "nsSyncStreamListener.h"
    1.10 +#include "nsIPipe.h"
    1.11 +#include "nsThreadUtils.h"
    1.12 +#include <algorithm>
    1.13 +
    1.14 +nsresult
    1.15 +nsSyncStreamListener::Init()
    1.16 +{
    1.17 +    return NS_NewPipe(getter_AddRefs(mPipeIn),
    1.18 +                      getter_AddRefs(mPipeOut),
    1.19 +                      nsIOService::gDefaultSegmentSize,
    1.20 +                      UINT32_MAX, // no size limit
    1.21 +                      false,
    1.22 +                      false);
    1.23 +}
    1.24 +
    1.25 +nsresult
    1.26 +nsSyncStreamListener::WaitForData()
    1.27 +{
    1.28 +    mKeepWaiting = true;
    1.29 +
    1.30 +    while (mKeepWaiting)
    1.31 +        NS_ENSURE_STATE(NS_ProcessNextEvent(NS_GetCurrentThread()));
    1.32 +
    1.33 +    return NS_OK;
    1.34 +}
    1.35 +
    1.36 +//-----------------------------------------------------------------------------
    1.37 +// nsSyncStreamListener::nsISupports
    1.38 +//-----------------------------------------------------------------------------
    1.39 +
    1.40 +NS_IMPL_ISUPPORTS(nsSyncStreamListener,
    1.41 +                  nsIStreamListener,
    1.42 +                  nsIRequestObserver,
    1.43 +                  nsIInputStream,
    1.44 +                  nsISyncStreamListener)
    1.45 +
    1.46 +//-----------------------------------------------------------------------------
    1.47 +// nsSyncStreamListener::nsISyncStreamListener
    1.48 +//-----------------------------------------------------------------------------
    1.49 +
    1.50 +NS_IMETHODIMP
    1.51 +nsSyncStreamListener::GetInputStream(nsIInputStream **result)
    1.52 +{
    1.53 +    NS_ADDREF(*result = this);
    1.54 +    return NS_OK;
    1.55 +}
    1.56 +
    1.57 +//-----------------------------------------------------------------------------
    1.58 +// nsSyncStreamListener::nsIStreamListener
    1.59 +//-----------------------------------------------------------------------------
    1.60 +
    1.61 +NS_IMETHODIMP
    1.62 +nsSyncStreamListener::OnStartRequest(nsIRequest  *request,
    1.63 +                                     nsISupports *context)
    1.64 +{
    1.65 +    return NS_OK;
    1.66 +}
    1.67 +
    1.68 +NS_IMETHODIMP
    1.69 +nsSyncStreamListener::OnDataAvailable(nsIRequest     *request,
    1.70 +                                      nsISupports    *context,
    1.71 +                                      nsIInputStream *stream,
    1.72 +                                      uint64_t        offset,
    1.73 +                                      uint32_t        count)
    1.74 +{
    1.75 +    uint32_t bytesWritten;
    1.76 +
    1.77 +    nsresult rv = mPipeOut->WriteFrom(stream, count, &bytesWritten);
    1.78 +
    1.79 +    // if we get an error, then return failure.  this will cause the
    1.80 +    // channel to be canceled, and as a result our OnStopRequest method
    1.81 +    // will be called immediately.  because of this we do not need to
    1.82 +    // set mStatus or mKeepWaiting here.
    1.83 +    if (NS_FAILED(rv))
    1.84 +        return rv;
    1.85 +
    1.86 +    // we expect that all data will be written to the pipe because
    1.87 +    // the pipe was created to have "infinite" room.
    1.88 +    NS_ASSERTION(bytesWritten == count, "did not write all data"); 
    1.89 +
    1.90 +    mKeepWaiting = false; // unblock Read
    1.91 +    return NS_OK;
    1.92 +}
    1.93 +
    1.94 +NS_IMETHODIMP
    1.95 +nsSyncStreamListener::OnStopRequest(nsIRequest  *request,
    1.96 +                                    nsISupports *context,
    1.97 +                                    nsresult     status)
    1.98 +{
    1.99 +    mStatus = status;
   1.100 +    mKeepWaiting = false; // unblock Read
   1.101 +    mDone = true;
   1.102 +    return NS_OK;
   1.103 +}
   1.104 +
   1.105 +//-----------------------------------------------------------------------------
   1.106 +// nsSyncStreamListener::nsIInputStream
   1.107 +//-----------------------------------------------------------------------------
   1.108 +
   1.109 +NS_IMETHODIMP
   1.110 +nsSyncStreamListener::Close()
   1.111 +{
   1.112 +    mStatus = NS_BASE_STREAM_CLOSED;
   1.113 +    mDone = true;
   1.114 +
   1.115 +    // It'd be nice if we could explicitly cancel the request at this point,
   1.116 +    // but we don't have a reference to it, so the best we can do is close the
   1.117 +    // pipe so that the next OnDataAvailable event will fail.
   1.118 +    if (mPipeIn) {
   1.119 +        mPipeIn->Close();
   1.120 +        mPipeIn = nullptr;
   1.121 +    }
   1.122 +    return NS_OK;
   1.123 +}
   1.124 +
   1.125 +NS_IMETHODIMP
   1.126 +nsSyncStreamListener::Available(uint64_t *result)
   1.127 +{
   1.128 +    if (NS_FAILED(mStatus))
   1.129 +        return mStatus;
   1.130 +
   1.131 +    mStatus = mPipeIn->Available(result);
   1.132 +    if (NS_SUCCEEDED(mStatus) && (*result == 0) && !mDone) {
   1.133 +        mStatus = WaitForData();
   1.134 +        if (NS_SUCCEEDED(mStatus))
   1.135 +            mStatus = mPipeIn->Available(result);
   1.136 +    }
   1.137 +    return mStatus;
   1.138 +}
   1.139 +
   1.140 +NS_IMETHODIMP
   1.141 +nsSyncStreamListener::Read(char     *buf,
   1.142 +                           uint32_t  bufLen,
   1.143 +                           uint32_t *result)
   1.144 +{
   1.145 +    if (mStatus == NS_BASE_STREAM_CLOSED) {
   1.146 +        *result = 0;
   1.147 +        return NS_OK;
   1.148 +    }
   1.149 +
   1.150 +    uint64_t avail64;
   1.151 +    if (NS_FAILED(Available(&avail64)))
   1.152 +        return mStatus;
   1.153 +
   1.154 +    uint32_t avail = (uint32_t)std::min(avail64, (uint64_t)bufLen);
   1.155 +    mStatus = mPipeIn->Read(buf, avail, result);
   1.156 +    return mStatus;
   1.157 +}
   1.158 +
   1.159 +NS_IMETHODIMP
   1.160 +nsSyncStreamListener::ReadSegments(nsWriteSegmentFun  writer,
   1.161 +                                   void              *closure,
   1.162 +                                   uint32_t           count,
   1.163 +                                   uint32_t          *result)
   1.164 +{
   1.165 +    if (mStatus == NS_BASE_STREAM_CLOSED) {
   1.166 +        *result = 0;
   1.167 +        return NS_OK;
   1.168 +    }
   1.169 +
   1.170 +    uint64_t avail64;
   1.171 +    if (NS_FAILED(Available(&avail64)))
   1.172 +        return mStatus;
   1.173 +
   1.174 +    uint32_t avail = (uint32_t)std::min(avail64, (uint64_t)count);
   1.175 +    mStatus = mPipeIn->ReadSegments(writer, closure, avail, result);
   1.176 +    return mStatus;
   1.177 +}
   1.178 +
   1.179 +NS_IMETHODIMP
   1.180 +nsSyncStreamListener::IsNonBlocking(bool *result)
   1.181 +{
   1.182 +    *result = false;
   1.183 +    return NS_OK;
   1.184 +}

mercurial