LCOV - code coverage report
Current view: top level - dom/presentation - PresentationTCPSessionTransport.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 262 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 35 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsArrayUtils.h"
       8             : #include "nsIAsyncStreamCopier.h"
       9             : #include "nsIInputStreamPump.h"
      10             : #include "nsIMultiplexInputStream.h"
      11             : #include "nsIMutableArray.h"
      12             : #include "nsIOutputStream.h"
      13             : #include "nsIPresentationControlChannel.h"
      14             : #include "nsIScriptableInputStream.h"
      15             : #include "nsISocketTransport.h"
      16             : #include "nsISocketTransportService.h"
      17             : #include "nsISupportsPrimitives.h"
      18             : #include "nsNetUtil.h"
      19             : #include "nsQueryObject.h"
      20             : #include "nsServiceManagerUtils.h"
      21             : #include "nsStreamUtils.h"
      22             : #include "nsThreadUtils.h"
      23             : #include "PresentationLog.h"
      24             : #include "PresentationTCPSessionTransport.h"
      25             : 
      26             : #define BUFFER_SIZE 65536
      27             : 
      28             : using namespace mozilla;
      29             : using namespace mozilla::dom;
      30             : 
      31             : class CopierCallbacks final : public nsIRequestObserver
      32             : {
      33             : public:
      34           0 :   explicit CopierCallbacks(PresentationTCPSessionTransport* aTransport)
      35           0 :     : mOwner(aTransport)
      36           0 :   {}
      37             : 
      38             :   NS_DECL_ISUPPORTS
      39             :   NS_DECL_NSIREQUESTOBSERVER
      40             : private:
      41           0 :   ~CopierCallbacks() {}
      42             : 
      43             :   RefPtr<PresentationTCPSessionTransport> mOwner;
      44             : };
      45             : 
      46           0 : NS_IMPL_ISUPPORTS(CopierCallbacks, nsIRequestObserver)
      47             : 
      48             : NS_IMETHODIMP
      49           0 : CopierCallbacks::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
      50             : {
      51           0 :   return NS_OK;
      52             : }
      53             : 
      54             : NS_IMETHODIMP
      55           0 : CopierCallbacks::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus)
      56             : {
      57           0 :   mOwner->NotifyCopyComplete(aStatus);
      58           0 :   return NS_OK;
      59             : }
      60             : 
      61           0 : NS_IMPL_CYCLE_COLLECTION(PresentationTCPSessionTransport, mTransport,
      62             :                          mSocketInputStream, mSocketOutputStream,
      63             :                          mInputStreamPump, mInputStreamScriptable,
      64             :                          mMultiplexStream, mMultiplexStreamCopier, mCallback)
      65             : 
      66           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationTCPSessionTransport)
      67           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationTCPSessionTransport)
      68             : 
      69           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationTCPSessionTransport)
      70           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPresentationSessionTransport)
      71           0 :   NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
      72           0 :   NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransport)
      73           0 :   NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransportBuilder)
      74           0 :   NS_INTERFACE_MAP_ENTRY(nsIPresentationTCPSessionTransportBuilder)
      75           0 :   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
      76           0 :   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
      77           0 :   NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
      78           0 : NS_INTERFACE_MAP_END
      79             : 
      80           0 : PresentationTCPSessionTransport::PresentationTCPSessionTransport()
      81             :   : mReadyState(ReadyState::CLOSED)
      82             :   , mAsyncCopierActive(false)
      83             :   , mCloseStatus(NS_OK)
      84           0 :   , mDataNotificationEnabled(false)
      85             : {
      86           0 : }
      87             : 
      88           0 : PresentationTCPSessionTransport::~PresentationTCPSessionTransport()
      89             : {
      90           0 : }
      91             : 
      92             : NS_IMETHODIMP
      93           0 : PresentationTCPSessionTransport::BuildTCPSenderTransport(nsISocketTransport* aTransport,
      94             :                                                          nsIPresentationSessionTransportBuilderListener* aListener)
      95             : {
      96           0 :   if (NS_WARN_IF(!aTransport)) {
      97           0 :     return NS_ERROR_INVALID_ARG;
      98             :   }
      99           0 :   mTransport = aTransport;
     100             : 
     101           0 :   if (NS_WARN_IF(!aListener)) {
     102           0 :     return NS_ERROR_INVALID_ARG;
     103             :   }
     104           0 :   mListener = aListener;
     105             : 
     106           0 :   nsresult rv = CreateStream();
     107           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     108           0 :     return rv;
     109             :   }
     110             : 
     111           0 :   mRole = nsIPresentationService::ROLE_CONTROLLER;
     112             : 
     113           0 :   nsCOMPtr<nsIPresentationSessionTransport> sessionTransport = do_QueryObject(this);
     114             :   nsCOMPtr<nsIRunnable> onSessionTransportRunnable =
     115           0 :     NewRunnableMethod<nsIPresentationSessionTransport*>(
     116             :       "nsIPresentationSessionTransportBuilderListener::OnSessionTransport",
     117             :       mListener,
     118             :       &nsIPresentationSessionTransportBuilderListener::OnSessionTransport,
     119           0 :       sessionTransport);
     120             : 
     121           0 :   NS_DispatchToCurrentThread(onSessionTransportRunnable.forget());
     122             : 
     123           0 :   nsCOMPtr<nsIRunnable> setReadyStateRunnable = NewRunnableMethod<ReadyState>(
     124             :     "dom::PresentationTCPSessionTransport::SetReadyState",
     125             :     this,
     126             :     &PresentationTCPSessionTransport::SetReadyState,
     127           0 :     ReadyState::OPEN);
     128           0 :   return NS_DispatchToCurrentThread(setReadyStateRunnable.forget());
     129             : }
     130             : 
     131             : NS_IMETHODIMP
     132           0 : PresentationTCPSessionTransport::BuildTCPReceiverTransport(nsIPresentationChannelDescription* aDescription,
     133             :                                                            nsIPresentationSessionTransportBuilderListener* aListener)
     134             : {
     135           0 :   if (NS_WARN_IF(!aDescription)) {
     136           0 :     return NS_ERROR_INVALID_ARG;
     137             :   }
     138             : 
     139           0 :   if (NS_WARN_IF(!aListener)) {
     140           0 :     return NS_ERROR_INVALID_ARG;
     141             :   }
     142           0 :   mListener = aListener;
     143             : 
     144             :   uint16_t serverPort;
     145           0 :   nsresult rv = aDescription->GetTcpPort(&serverPort);
     146           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     147           0 :     return rv;
     148             :   }
     149             : 
     150           0 :   nsCOMPtr<nsIArray> serverHosts;
     151           0 :   rv = aDescription->GetTcpAddress(getter_AddRefs(serverHosts));
     152           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     153           0 :     return rv;
     154             :   }
     155             : 
     156             :   // TODO bug 1228504 Take all IP addresses in PresentationChannelDescription
     157             :   // into account. And at the first stage Presentation API is only exposed on
     158             :   // Firefox OS where the first IP appears enough for most scenarios.
     159           0 :   nsCOMPtr<nsISupportsCString> supportStr = do_QueryElementAt(serverHosts, 0);
     160           0 :   if (NS_WARN_IF(!supportStr)) {
     161           0 :     return NS_ERROR_INVALID_ARG;
     162             :   }
     163             : 
     164           0 :   nsAutoCString serverHost;
     165           0 :   supportStr->GetData(serverHost);
     166           0 :   if (serverHost.IsEmpty()) {
     167           0 :     return NS_ERROR_INVALID_ARG;
     168             :   }
     169             : 
     170           0 :   PRES_DEBUG("%s:ServerHost[%s],ServerPort[%d]\n", __func__, serverHost.get(), serverPort);
     171             : 
     172           0 :   SetReadyState(ReadyState::CONNECTING);
     173             : 
     174             :   nsCOMPtr<nsISocketTransportService> sts =
     175           0 :     do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
     176           0 :   if (NS_WARN_IF(!sts)) {
     177           0 :     return NS_ERROR_NOT_AVAILABLE;
     178             :   }
     179           0 :   rv = sts->CreateTransport(nullptr, 0, serverHost, serverPort, nullptr,
     180           0 :                             getter_AddRefs(mTransport));
     181           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     182           0 :     return rv;
     183             :   }
     184             : 
     185           0 :   nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
     186           0 :   mTransport->SetEventSink(this, mainTarget);
     187             : 
     188           0 :   rv = CreateStream();
     189           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     190           0 :     return rv;
     191             :   }
     192             : 
     193           0 :   mRole = nsIPresentationService::ROLE_RECEIVER;
     194             : 
     195           0 :   nsCOMPtr<nsIPresentationSessionTransport> sessionTransport = do_QueryObject(this);
     196             :   nsCOMPtr<nsIRunnable> runnable =
     197           0 :     NewRunnableMethod<nsIPresentationSessionTransport*>(
     198             :       "nsIPresentationSessionTransportBuilderListener::OnSessionTransport",
     199             :       mListener,
     200             :       &nsIPresentationSessionTransportBuilderListener::OnSessionTransport,
     201           0 :       sessionTransport);
     202           0 :   return NS_DispatchToCurrentThread(runnable.forget());
     203             : }
     204             : 
     205             : nsresult
     206           0 : PresentationTCPSessionTransport::CreateStream()
     207             : {
     208           0 :   nsresult rv = mTransport->OpenInputStream(0, 0, 0, getter_AddRefs(mSocketInputStream));
     209           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     210           0 :     return rv;
     211             :   }
     212           0 :   rv = mTransport->OpenOutputStream(nsITransport::OPEN_UNBUFFERED, 0, 0, getter_AddRefs(mSocketOutputStream));
     213           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     214           0 :     return rv;
     215             :   }
     216             : 
     217             :   // If the other side is not listening, we will get an |onInputStreamReady|
     218             :   // callback where |available| raises to indicate the connection was refused.
     219           0 :   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mSocketInputStream);
     220           0 :   if (NS_WARN_IF(!asyncStream)) {
     221           0 :     return NS_ERROR_NOT_AVAILABLE;
     222             :   }
     223             : 
     224           0 :   nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
     225           0 :   rv = asyncStream->AsyncWait(this, nsIAsyncInputStream::WAIT_CLOSURE_ONLY, 0, mainTarget);
     226           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     227           0 :     return rv;
     228             :   }
     229             : 
     230           0 :   mInputStreamScriptable = do_CreateInstance("@mozilla.org/scriptableinputstream;1", &rv);
     231           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     232           0 :     return rv;
     233             :   }
     234           0 :   rv = mInputStreamScriptable->Init(mSocketInputStream);
     235           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     236           0 :     return rv;
     237             :   }
     238             : 
     239           0 :   mMultiplexStream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1", &rv);
     240           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     241           0 :     return rv;
     242             :   }
     243             : 
     244           0 :   mMultiplexStreamCopier = do_CreateInstance("@mozilla.org/network/async-stream-copier;1", &rv);
     245           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     246           0 :     return rv;
     247             :   }
     248             : 
     249             :   nsCOMPtr<nsISocketTransportService> sts =
     250           0 :     do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
     251           0 :   if (NS_WARN_IF(!sts)) {
     252           0 :     return NS_ERROR_NOT_AVAILABLE;
     253             :   }
     254             : 
     255           0 :   nsCOMPtr<nsIEventTarget> target = do_QueryInterface(sts);
     256           0 :   rv = mMultiplexStreamCopier->Init(mMultiplexStream,
     257             :                                     mSocketOutputStream,
     258             :                                     target,
     259             :                                     true, /* source buffered */
     260             :                                     false, /* sink buffered */
     261             :                                     BUFFER_SIZE,
     262             :                                     false, /* close source */
     263           0 :                                     false); /* close sink */
     264           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     265           0 :     return rv;
     266             :   }
     267             : 
     268           0 :   return NS_OK;
     269             : }
     270             : 
     271             : nsresult
     272           0 : PresentationTCPSessionTransport::CreateInputStreamPump()
     273             : {
     274           0 :   if (NS_WARN_IF(mInputStreamPump)) {
     275           0 :     return NS_OK;
     276             :   }
     277             : 
     278             :   nsresult rv;
     279           0 :   mInputStreamPump = do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
     280           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     281           0 :     return rv;
     282             :   }
     283             : 
     284           0 :   rv = mInputStreamPump->Init(mSocketInputStream, -1, -1, 0, 0, false, nullptr);
     285           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     286           0 :     return rv;
     287             :   }
     288             : 
     289           0 :   rv = mInputStreamPump->AsyncRead(this, nullptr);
     290           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     291           0 :     return rv;
     292             :   }
     293             : 
     294           0 :   return NS_OK;
     295             : }
     296             : 
     297             : NS_IMETHODIMP
     298           0 : PresentationTCPSessionTransport::EnableDataNotification()
     299             : {
     300           0 :   if (NS_WARN_IF(!mCallback)) {
     301           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
     302             :   }
     303             : 
     304           0 :   if (mDataNotificationEnabled) {
     305           0 :     return NS_OK;
     306             :   }
     307             : 
     308           0 :   mDataNotificationEnabled = true;
     309             : 
     310           0 :   if (IsReadyToNotifyData()) {
     311           0 :     return CreateInputStreamPump();
     312             :   }
     313             : 
     314           0 :   return NS_OK;
     315             : }
     316             : 
     317             : // nsIPresentationSessionTransportBuilderListener
     318             : NS_IMETHODIMP
     319           0 : PresentationTCPSessionTransport::GetCallback(nsIPresentationSessionTransportCallback** aCallback)
     320             : {
     321           0 :   nsCOMPtr<nsIPresentationSessionTransportCallback> callback = mCallback;
     322           0 :   callback.forget(aCallback);
     323           0 :   return NS_OK;
     324             : }
     325             : 
     326             : NS_IMETHODIMP
     327           0 : PresentationTCPSessionTransport::SetCallback(nsIPresentationSessionTransportCallback* aCallback)
     328             : {
     329           0 :   mCallback = aCallback;
     330             : 
     331           0 :   if (!!mCallback && ReadyState::OPEN == mReadyState) {
     332             :     // Notify the transport channel is ready.
     333           0 :     Unused << NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportReady()));
     334             :   }
     335             : 
     336           0 :   return NS_OK;
     337             : }
     338             : 
     339             : NS_IMETHODIMP
     340           0 : PresentationTCPSessionTransport::GetSelfAddress(nsINetAddr** aSelfAddress)
     341             : {
     342           0 :   if (NS_WARN_IF(!mTransport)) {
     343           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
     344             :   }
     345             : 
     346           0 :   return mTransport->GetScriptableSelfAddr(aSelfAddress);
     347             : }
     348             : 
     349             : void
     350           0 : PresentationTCPSessionTransport::EnsureCopying()
     351             : {
     352           0 :   if (mAsyncCopierActive) {
     353           0 :     return;
     354             :   }
     355             : 
     356           0 :   mAsyncCopierActive = true;
     357           0 :   RefPtr<CopierCallbacks> callbacks = new CopierCallbacks(this);
     358           0 :   Unused << NS_WARN_IF(NS_FAILED(mMultiplexStreamCopier->AsyncCopy(callbacks, nullptr)));
     359             : }
     360             : 
     361             : void
     362           0 : PresentationTCPSessionTransport::NotifyCopyComplete(nsresult aStatus)
     363             : {
     364           0 :   mAsyncCopierActive = false;
     365           0 :   mMultiplexStream->RemoveStream(0);
     366           0 :   if (NS_WARN_IF(NS_FAILED(aStatus))) {
     367           0 :     if (mReadyState != ReadyState::CLOSED) {
     368           0 :       mCloseStatus = aStatus;
     369           0 :       SetReadyState(ReadyState::CLOSED);
     370             :     }
     371           0 :     return;
     372             :   }
     373             : 
     374             :   uint32_t count;
     375           0 :   nsresult rv = mMultiplexStream->GetCount(&count);
     376           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     377           0 :     return;
     378             :   }
     379             : 
     380           0 :   if (count) {
     381           0 :     EnsureCopying();
     382           0 :     return;
     383             :   }
     384             : 
     385           0 :   if (mReadyState == ReadyState::CLOSING) {
     386           0 :     mSocketOutputStream->Close();
     387           0 :     mCloseStatus = NS_OK;
     388           0 :     SetReadyState(ReadyState::CLOSED);
     389             :   }
     390             : }
     391             : 
     392             : NS_IMETHODIMP
     393           0 : PresentationTCPSessionTransport::Send(const nsAString& aData)
     394             : {
     395           0 :   if (NS_WARN_IF(mReadyState != ReadyState::OPEN)) {
     396           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
     397             :   }
     398             : 
     399             :   nsresult rv;
     400             :   nsCOMPtr<nsIStringInputStream> stream =
     401           0 :     do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
     402           0 :   if(NS_WARN_IF(NS_FAILED(rv))) {
     403           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
     404             :   }
     405             : 
     406           0 :   NS_ConvertUTF16toUTF8 msgString(aData);
     407           0 :   rv = stream->SetData(msgString.BeginReading(), msgString.Length());
     408           0 :   if(NS_WARN_IF(NS_FAILED(rv))) {
     409           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
     410             :   }
     411             : 
     412           0 :   mMultiplexStream->AppendStream(stream);
     413             : 
     414           0 :   EnsureCopying();
     415             : 
     416           0 :   return NS_OK;
     417             : }
     418             : 
     419             : NS_IMETHODIMP
     420           0 : PresentationTCPSessionTransport::SendBinaryMsg(const nsACString& aData)
     421             : {
     422           0 :   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     423             : }
     424             : 
     425             : NS_IMETHODIMP
     426           0 : PresentationTCPSessionTransport::SendBlob(nsIDOMBlob* aBlob)
     427             : {
     428           0 :   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     429             : }
     430             : 
     431             : NS_IMETHODIMP
     432           0 : PresentationTCPSessionTransport::Close(nsresult aReason)
     433             : {
     434           0 :   PRES_DEBUG("%s:reason[%" PRIx32 "]\n", __func__, static_cast<uint32_t>(aReason));
     435             : 
     436           0 :   if (mReadyState == ReadyState::CLOSED || mReadyState == ReadyState::CLOSING) {
     437           0 :     return NS_OK;
     438             :   }
     439             : 
     440           0 :   mCloseStatus = aReason;
     441           0 :   SetReadyState(ReadyState::CLOSING);
     442             : 
     443           0 :   uint32_t count = 0;
     444           0 :   mMultiplexStream->GetCount(&count);
     445           0 :   if (!count) {
     446           0 :     mSocketOutputStream->Close();
     447             :   }
     448             : 
     449           0 :   mSocketInputStream->Close();
     450           0 :   mDataNotificationEnabled = false;
     451             : 
     452           0 :   mListener = nullptr;
     453             : 
     454           0 :   return NS_OK;
     455             : }
     456             : 
     457             : void
     458           0 : PresentationTCPSessionTransport::SetReadyState(ReadyState aReadyState)
     459             : {
     460           0 :   mReadyState = aReadyState;
     461             : 
     462           0 :   if (mReadyState == ReadyState::OPEN) {
     463           0 :     if (IsReadyToNotifyData()) {
     464           0 :       CreateInputStreamPump();
     465             :     }
     466             : 
     467           0 :     if (NS_WARN_IF(!mCallback)) {
     468           0 :       return;
     469             :     }
     470             : 
     471             :     // Notify the transport channel is ready.
     472           0 :     Unused << NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportReady()));
     473           0 :   } else if (mReadyState == ReadyState::CLOSED && mCallback) {
     474           0 :     if (NS_WARN_IF(!mCallback)) {
     475           0 :       return;
     476             :     }
     477             : 
     478             :     // Notify the transport channel has been shut down.
     479             :     Unused <<
     480           0 :       NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportClosed(mCloseStatus)));
     481           0 :     mCallback = nullptr;
     482             :   }
     483             : }
     484             : 
     485             : // nsITransportEventSink
     486             : NS_IMETHODIMP
     487           0 : PresentationTCPSessionTransport::OnTransportStatus(nsITransport* aTransport,
     488             :                                                    nsresult aStatus,
     489             :                                                    int64_t aProgress,
     490             :                                                    int64_t aProgressMax)
     491             : {
     492           0 :   PRES_DEBUG("%s:aStatus[%" PRIx32 "]\n", __func__, static_cast<uint32_t>(aStatus));
     493             : 
     494           0 :   MOZ_ASSERT(NS_IsMainThread());
     495             : 
     496           0 :   if (aStatus != NS_NET_STATUS_CONNECTED_TO) {
     497           0 :     return NS_OK;
     498             :   }
     499             : 
     500           0 :   SetReadyState(ReadyState::OPEN);
     501             : 
     502           0 :   return NS_OK;
     503             : }
     504             : 
     505             : // nsIInputStreamCallback
     506             : NS_IMETHODIMP
     507           0 : PresentationTCPSessionTransport::OnInputStreamReady(nsIAsyncInputStream* aStream)
     508             : {
     509           0 :   MOZ_ASSERT(NS_IsMainThread());
     510             : 
     511             :   // Only used for detecting if the connection was refused.
     512             :   uint64_t dummy;
     513           0 :   nsresult rv = aStream->Available(&dummy);
     514           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     515           0 :     if (mReadyState != ReadyState::CLOSED) {
     516           0 :       mCloseStatus = NS_ERROR_CONNECTION_REFUSED;
     517           0 :       SetReadyState(ReadyState::CLOSED);
     518             :     }
     519             :   }
     520             : 
     521           0 :   return NS_OK;
     522             : }
     523             : 
     524             : // nsIRequestObserver
     525             : NS_IMETHODIMP
     526           0 : PresentationTCPSessionTransport::OnStartRequest(nsIRequest* aRequest,
     527             :                                                 nsISupports* aContext)
     528             : {
     529             :   // Do nothing.
     530           0 :   return NS_OK;
     531             : }
     532             : 
     533             : NS_IMETHODIMP
     534           0 : PresentationTCPSessionTransport::OnStopRequest(nsIRequest* aRequest,
     535             :                                                nsISupports* aContext,
     536             :                                                nsresult aStatusCode)
     537             : {
     538           0 :   PRES_DEBUG("%s:aStatusCode[%" PRIx32 "]\n", __func__, static_cast<uint32_t>(aStatusCode));
     539             : 
     540           0 :   MOZ_ASSERT(NS_IsMainThread());
     541             : 
     542             :   uint32_t count;
     543           0 :   nsresult rv = mMultiplexStream->GetCount(&count);
     544           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     545           0 :     return rv;
     546             :   }
     547             : 
     548           0 :   mInputStreamPump = nullptr;
     549             : 
     550           0 :   if (count != 0 && NS_SUCCEEDED(aStatusCode)) {
     551             :     // If we have some buffered output still, and status is not an error, the
     552             :     // other side has done a half-close, but we don't want to be in the close
     553             :     // state until we are done sending everything that was buffered. We also
     554             :     // don't want to call |NotifyTransportClosed| yet.
     555           0 :     return NS_OK;
     556             :   }
     557             : 
     558             :   // We call this even if there is no error.
     559           0 :   if (mReadyState != ReadyState::CLOSED) {
     560           0 :     mCloseStatus = aStatusCode;
     561           0 :     SetReadyState(ReadyState::CLOSED);
     562             :   }
     563           0 :   return NS_OK;
     564             : }
     565             : 
     566             : // nsIStreamListener
     567             : NS_IMETHODIMP
     568           0 : PresentationTCPSessionTransport::OnDataAvailable(nsIRequest* aRequest,
     569             :                                                  nsISupports* aContext,
     570             :                                                  nsIInputStream* aStream,
     571             :                                                  uint64_t aOffset,
     572             :                                                  uint32_t aCount)
     573             : {
     574           0 :   MOZ_ASSERT(NS_IsMainThread());
     575             : 
     576           0 :   if (NS_WARN_IF(!mCallback)) {
     577           0 :     return NS_ERROR_NOT_AVAILABLE;
     578             :   }
     579             : 
     580           0 :   nsCString data;
     581           0 :   nsresult rv = mInputStreamScriptable->ReadBytes(aCount, data);
     582           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     583           0 :     return rv;
     584             :   }
     585             : 
     586             :   // Pass the incoming data to the listener.
     587           0 :   return mCallback->NotifyData(data, false);
     588             : }

Generated by: LCOV version 1.13