netwerk/base/src/nsSyncStreamListener.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial