Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  WebSocketChannelChild.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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/. */


#include "WebSocketLog.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/net/NeckoChild.h"
#include "WebSocketChannelChild.h"
#include "nsContentUtils.h"
#include "nsIBrowserChild.h"
#include "nsNetUtil.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/net/ChannelEventQueue.h"
#include "SerializedLoadContext.h"
#include "mozilla/dom/ContentChild.h"
#include "nsITransportProvider.h"

using namespace mozilla::ipc;
using mozilla::dom::ContentChild;

namespace mozilla {
namespace net {

NS_IMPL_ADDREF(WebSocketChannelChild)

NS_IMETHODIMP_(MozExternalRefCountType) WebSocketChannelChild::Release() {
  MOZ_ASSERT(0 != mRefCnt, "dup release");
  --mRefCnt;
  NS_LOG_RELEASE(this, mRefCnt, "WebSocketChannelChild");

  if (mRefCnt == 1) {
    MaybeReleaseIPCObject();
    return mRefCnt;
  }

  if (mRefCnt == 0) {
    mRefCnt = 1; /* stabilize */
    delete this;
    return 0;
  }
  return mRefCnt;
}

NS_INTERFACE_MAP_BEGIN(WebSocketChannelChild)
  NS_INTERFACE_MAP_ENTRY(nsIWebSocketChannel)
  NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketChannel)
  NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)
NS_INTERFACE_MAP_END

WebSocketChannelChild::WebSocketChannelChild(bool aEncrypted)
    : NeckoTargetHolder(nullptr),
      mIPCState(Closed),
      mMutex("WebSocketChannelChild::mMutex") {
  MOZ_ASSERT(NS_IsMainThread(), "not main thread");

  LOG(("WebSocketChannelChild::WebSocketChannelChild() %p\n"this));
  mEncrypted = aEncrypted;
  mEventQ = new ChannelEventQueue(static_cast<nsIWebSocketChannel*>(this));
}

WebSocketChannelChild::~WebSocketChannelChild() {
  LOG(("WebSocketChannelChild::~WebSocketChannelChild() %p\n"this));
  mEventQ->NotifyReleasingOwner();
}

void WebSocketChannelChild::AddIPDLReference() {
  MOZ_ASSERT(NS_IsMainThread());

  {
    MutexAutoLock lock(mMutex);
    MOZ_ASSERT(mIPCState == Closed,
               "Attempt to retain more than one IPDL reference");
    mIPCState = Opened;
  }

  AddRef();
}

void WebSocketChannelChild::ReleaseIPDLReference() {
  MOZ_ASSERT(NS_IsMainThread());

  {
    MutexAutoLock lock(mMutex);
    MOZ_ASSERT(mIPCState != Closed,
               "Attempt to release nonexistent IPDL reference");
    mIPCState = Closed;
  }

  Release();
}

void WebSocketChannelChild::MaybeReleaseIPCObject() {
  {
    MutexAutoLock lock(mMutex);
    if (mIPCState != Opened) {
      return;
    }

    mIPCState = Closing;
  }

  if (!NS_IsMainThread()) {
    nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
    MOZ_ALWAYS_SUCCEEDS(target->Dispatch(
        NewRunnableMethod("WebSocketChannelChild::MaybeReleaseIPCObject"this,
                          &WebSocketChannelChild::MaybeReleaseIPCObject),
        NS_DISPATCH_NORMAL));
    return;
  }

  SendDeleteSelf();
}

void WebSocketChannelChild::GetEffectiveURL(nsAString& aEffectiveURL) const {
  aEffectiveURL = mEffectiveURL;
}

bool WebSocketChannelChild::IsEncrypted() const { return mEncrypted; }

class WebSocketEvent {
 public:
  MOZ_COUNTED_DEFAULT_CTOR(WebSocketEvent)
  MOZ_COUNTED_DTOR_VIRTUAL(WebSocketEvent)
  virtual void Run(WebSocketChannelChild* aChild) = 0;
};

class WrappedWebSocketEvent : public Runnable {
 public:
  WrappedWebSocketEvent(WebSocketChannelChild* aChild,
                        UniquePtr<WebSocketEvent>&& aWebSocketEvent)
      : Runnable("net::WrappedWebSocketEvent"),
        mChild(aChild),
        mWebSocketEvent(std::move(aWebSocketEvent)) {
    MOZ_RELEASE_ASSERT(!!mWebSocketEvent);
  }
  NS_IMETHOD Run() override {
    mWebSocketEvent->Run(mChild);
    return NS_OK;
  }

 private:
  RefPtr<WebSocketChannelChild> mChild;
  UniquePtr<WebSocketEvent> mWebSocketEvent;
};

class EventTargetDispatcher : public ChannelEvent {
 public:
  EventTargetDispatcher(WebSocketChannelChild* aChild,
                        WebSocketEvent* aWebSocketEvent)
      : mChild(aChild),
        mWebSocketEvent(aWebSocketEvent),
        mEventTarget(mChild->GetTargetThread()) {}

  void Run() override {
    if (mEventTarget) {
      mEventTarget->Dispatch(
          new WrappedWebSocketEvent(mChild, std::move(mWebSocketEvent)),
          NS_DISPATCH_NORMAL);
      return;
    }
  }

  already_AddRefed<nsIEventTarget> GetEventTarget() override {
    nsCOMPtr<nsIEventTarget> target = mEventTarget;
    if (!target) {
      target = GetMainThreadSerialEventTarget();
    }
    return target.forget();
  }

 private:
  // The lifetime of the child is ensured by ChannelEventQueue.
  WebSocketChannelChild* mChild;
  UniquePtr<WebSocketEvent> mWebSocketEvent;
  nsCOMPtr<nsIEventTarget> mEventTarget;
};

class StartEvent : public WebSocketEvent {
 public:
  StartEvent(const nsACString& aProtocol, const nsACString& aExtensions,
             const nsAString& aEffectiveURL, bool aEncrypted,
             uint64_t aHttpChannelId)
      : mProtocol(aProtocol),
        mExtensions(aExtensions),
        mEffectiveURL(aEffectiveURL),
        mEncrypted(aEncrypted),
        mHttpChannelId(aHttpChannelId) {}

  void Run(WebSocketChannelChild* aChild) override {
    aChild->OnStart(mProtocol, mExtensions, mEffectiveURL, mEncrypted,
                    mHttpChannelId);
  }

 private:
  nsCString mProtocol;
  nsCString mExtensions;
  nsString mEffectiveURL;
  bool mEncrypted;
  uint64_t mHttpChannelId;
};

mozilla::ipc::IPCResult WebSocketChannelChild::RecvOnStart(
    const nsACString& aProtocol, const nsACString& aExtensions,
    const nsAString& aEffectiveURL, const bool& aEncrypted,
    const uint64_t& aHttpChannelId) {
  mEventQ->RunOrEnqueue(new EventTargetDispatcher(
      thisnew StartEvent(aProtocol, aExtensions, aEffectiveURL, aEncrypted,
                           aHttpChannelId)));

  return IPC_OK();
}

void WebSocketChannelChild::OnStart(const nsACString& aProtocol,
                                    const nsACString& aExtensions,
                                    const nsAString& aEffectiveURL,
                                    const bool& aEncrypted,
                                    const uint64_t& aHttpChannelId) {
  LOG(("WebSocketChannelChild::RecvOnStart() %p\n"this));
  SetProtocol(aProtocol);
  mNegotiatedExtensions = aExtensions;
  mEffectiveURL = aEffectiveURL;
  mEncrypted = aEncrypted;
  mHttpChannelId = aHttpChannelId;

  if (mListenerMT) {
    AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    nsresult rv = mListenerMT->mListener->OnStart(mListenerMT->mContext);
    if (NS_FAILED(rv)) {
      LOG(
          ("WebSocketChannelChild::OnStart "
           "mListenerMT->mListener->OnStart() failed with error 0x%08" PRIx32,
           static_cast<uint32_t>(rv)));
    }
  }
}

class StopEvent : public WebSocketEvent {
 public:
  explicit StopEvent(const nsresult& aStatusCode) : mStatusCode(aStatusCode) {}

  void Run(WebSocketChannelChild* aChild) override {
    aChild->OnStop(mStatusCode);
  }

 private:
  nsresult mStatusCode;
};

mozilla::ipc::IPCResult WebSocketChannelChild::RecvOnStop(
    const nsresult& aStatusCode) {
  mEventQ->RunOrEnqueue(
      new EventTargetDispatcher(thisnew StopEvent(aStatusCode)));

  return IPC_OK();
}

void WebSocketChannelChild::OnStop(const nsresult& aStatusCode) {
  LOG(("WebSocketChannelChild::RecvOnStop() %p\n"this));
  if (mListenerMT) {
    AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    nsresult rv =
        mListenerMT->mListener->OnStop(mListenerMT->mContext, aStatusCode);
    if (NS_FAILED(rv)) {
      LOG(
          ("WebSocketChannel::OnStop "
           "mListenerMT->mListener->OnStop() failed with error 0x%08" PRIx32,
           static_cast<uint32_t>(rv)));
    }
  }
}

class MessageEvent : public WebSocketEvent {
 public:
  MessageEvent(const nsACString& aMessage, bool aBinary)
      : mMessage(aMessage), mBinary(aBinary) {}

  void Run(WebSocketChannelChild* aChild) override {
    if (!mBinary) {
      aChild->OnMessageAvailable(mMessage);
    } else {
      aChild->OnBinaryMessageAvailable(mMessage);
    }
  }

 private:
  nsCString mMessage;
  bool mBinary;
};

bool WebSocketChannelChild::RecvOnMessageAvailableInternal(
    const nsACString& aMsg, bool aMoreData, bool aBinary) {
  if (aMoreData) {
    return mReceivedMsgBuffer.Append(aMsg, fallible);
  }

  if (!mReceivedMsgBuffer.Append(aMsg, fallible)) {
    return false;
  }

  mEventQ->RunOrEnqueue(new EventTargetDispatcher(
      thisnew MessageEvent(mReceivedMsgBuffer, aBinary)));
  mReceivedMsgBuffer.Truncate();
  return true;
}

class OnErrorEvent : public WebSocketEvent {
 public:
  OnErrorEvent() = default;

  void Run(WebSocketChannelChild* aChild) override { aChild->OnError(); }
};

void WebSocketChannelChild::OnError() {
  LOG(("WebSocketChannelChild::OnError() %p"this));
  if (mListenerMT) {
    AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    Unused << mListenerMT->mListener->OnError();
  }
}

mozilla::ipc::IPCResult WebSocketChannelChild::RecvOnMessageAvailable(
    const nsACString& aMsg, const bool& aMoreData) {
  if (!RecvOnMessageAvailableInternal(aMsg, aMoreData, false)) {
    LOG(("WebSocketChannelChild %p append message failed"this));
    mEventQ->RunOrEnqueue(new EventTargetDispatcher(thisnew OnErrorEvent()));
  }
  return IPC_OK();
}

void WebSocketChannelChild::OnMessageAvailable(const nsACString& aMsg) {
  LOG(("WebSocketChannelChild::RecvOnMessageAvailable() %p\n"this));
  if (mListenerMT) {
    AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    nsresult rv =
        mListenerMT->mListener->OnMessageAvailable(mListenerMT->mContext, aMsg);
    if (NS_FAILED(rv)) {
      LOG(
          ("WebSocketChannelChild::OnMessageAvailable "
           "mListenerMT->mListener->OnMessageAvailable() "
           "failed with error 0x%08" PRIx32,
           static_cast<uint32_t>(rv)));
    }
  }
}

mozilla::ipc::IPCResult WebSocketChannelChild::RecvOnBinaryMessageAvailable(
    const nsACString& aMsg, const bool& aMoreData) {
  if (!RecvOnMessageAvailableInternal(aMsg, aMoreData, true)) {
    LOG(("WebSocketChannelChild %p append message failed"this));
    mEventQ->RunOrEnqueue(new EventTargetDispatcher(thisnew OnErrorEvent()));
  }
  return IPC_OK();
}

void WebSocketChannelChild::OnBinaryMessageAvailable(const nsACString& aMsg) {
  LOG(("WebSocketChannelChild::RecvOnBinaryMessageAvailable() %p\n"this));
  if (mListenerMT) {
    AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    nsresult rv = mListenerMT->mListener->OnBinaryMessageAvailable(
        mListenerMT->mContext, aMsg);
    if (NS_FAILED(rv)) {
      LOG(
          ("WebSocketChannelChild::OnBinaryMessageAvailable "
           "mListenerMT->mListener->OnBinaryMessageAvailable() "
           "failed with error 0x%08" PRIx32,
           static_cast<uint32_t>(rv)));
    }
  }
}

class AcknowledgeEvent : public WebSocketEvent {
 public:
  explicit AcknowledgeEvent(const uint32_t& aSize) : mSize(aSize) {}

  void Run(WebSocketChannelChild* aChild) override {
    aChild->OnAcknowledge(mSize);
  }

 private:
  uint32_t mSize;
};

mozilla::ipc::IPCResult WebSocketChannelChild::RecvOnAcknowledge(
    const uint32_t& aSize) {
  mEventQ->RunOrEnqueue(
      new EventTargetDispatcher(thisnew AcknowledgeEvent(aSize)));

  return IPC_OK();
}

void WebSocketChannelChild::OnAcknowledge(const uint32_t& aSize) {
  LOG(("WebSocketChannelChild::RecvOnAcknowledge() %p\n"this));
  if (mListenerMT) {
    AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    nsresult rv =
        mListenerMT->mListener->OnAcknowledge(mListenerMT->mContext, aSize);
    if (NS_FAILED(rv)) {
      LOG(
          ("WebSocketChannel::OnAcknowledge "
           "mListenerMT->mListener->OnAcknowledge() "
           "failed with error 0x%08" PRIx32,
           static_cast<uint32_t>(rv)));
    }
  }
}

class ServerCloseEvent : public WebSocketEvent {
 public:
  ServerCloseEvent(const uint16_t aCode, const nsACString& aReason)
      : mCode(aCode), mReason(aReason) {}

  void Run(WebSocketChannelChild* aChild) override {
    aChild->OnServerClose(mCode, mReason);
  }

 private:
  uint16_t mCode;
  nsCString mReason;
};

mozilla::ipc::IPCResult WebSocketChannelChild::RecvOnServerClose(
    const uint16_t& aCode, const nsACString& aReason) {
  mEventQ->RunOrEnqueue(
      new EventTargetDispatcher(thisnew ServerCloseEvent(aCode, aReason)));

  return IPC_OK();
}

void WebSocketChannelChild::OnServerClose(const uint16_t& aCode,
                                          const nsACString& aReason) {
  LOG(("WebSocketChannelChild::RecvOnServerClose() %p\n"this));
  if (mListenerMT) {
    AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    DebugOnly<nsresult> rv = mListenerMT->mListener->OnServerClose(
        mListenerMT->mContext, aCode, aReason);
    MOZ_ASSERT(NS_SUCCEEDED(rv));
  }
}

void WebSocketChannelChild::SetupNeckoTarget() {
  mNeckoTarget = GetMainThreadSerialEventTarget();
}

NS_IMETHODIMP
WebSocketChannelChild::AsyncOpen(nsIURI* aURI, const nsACString& aOrigin,
                                 JS::Handle<JS::Value> aOriginAttributes,
                                 uint64_t aInnerWindowID,
                                 nsIWebSocketListener* aListener,
                                 nsISupports* aContext, JSContext* aCx) {
  OriginAttributes attrs;
  if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
    return NS_ERROR_INVALID_ARG;
  }
  return AsyncOpenNative(aURI, aOrigin, attrs, aInnerWindowID, aListener,
                         aContext);
}

NS_IMETHODIMP
WebSocketChannelChild::AsyncOpenNative(
    nsIURI* aURI, const nsACString& aOrigin,
    const OriginAttributes& aOriginAttributes, uint64_t aInnerWindowID,
    nsIWebSocketListener* aListener, nsISupports* aContext) {
  LOG(("WebSocketChannelChild::AsyncOpen() %p\n"this));

  MOZ_ASSERT(NS_IsMainThread(), "not main thread");
  MOZ_ASSERT((aURI && !mIsServerSide) || (!aURI && mIsServerSide),
             "Invalid aURI for WebSocketChannelChild::AsyncOpen");
  MOZ_ASSERT(aListener && !mListenerMT,
             "Invalid state for WebSocketChannelChild::AsyncOpen");

  mozilla::dom::BrowserChild* browserChild = nullptr;
  nsCOMPtr<nsIBrowserChild> iBrowserChild;
  NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
                                NS_GET_IID(nsIBrowserChild),
                                getter_AddRefs(iBrowserChild));
  if (iBrowserChild) {
    browserChild =
        static_cast<mozilla::dom::BrowserChild*>(iBrowserChild.get());
  }

  ContentChild* cc = static_cast<ContentChild*>(gNeckoChild->Manager());
  if (cc->IsShuttingDown()) {
    return NS_ERROR_FAILURE;
  }

  // Corresponding release in DeallocPWebSocket
  AddIPDLReference();

  nsCOMPtr<nsIURI> uri;
  LoadInfoArgs loadInfoArgs;
  Maybe<NotNull<PTransportProviderChild*>> transportProvider;

  if (!mIsServerSide) {
    uri = aURI;
    nsresult rv = LoadInfoToLoadInfoArgs(mLoadInfo, &loadInfoArgs);
    NS_ENSURE_SUCCESS(rv, rv);

    transportProvider = Nothing();
  } else {
    MOZ_ASSERT(mServerTransportProvider);
    PTransportProviderChild* ipcChild;
    nsresult rv = mServerTransportProvider->GetIPCChild(&ipcChild);
    NS_ENSURE_SUCCESS(rv, rv);

    transportProvider = Some(WrapNotNull(ipcChild));
  }

  // This must be called before sending constructor message.
  SetupNeckoTarget();

  if (!gNeckoChild->SendPWebSocketConstructor(
          this, browserChild, IPC::SerializedLoadContext(this), mSerial)) {
    return NS_ERROR_UNEXPECTED;
  }
  if (!SendAsyncOpen(uri, aOrigin, aOriginAttributes, aInnerWindowID, mProtocol,
                     mEncrypted, mPingInterval, mClientSetPingInterval,
                     mPingResponseTimeout, mClientSetPingTimeout, loadInfoArgs,
                     transportProvider, mNegotiatedExtensions)) {
    return NS_ERROR_UNEXPECTED;
  }

  if (mIsServerSide) {
    mServerTransportProvider = nullptr;
  }

  mOriginalURI = aURI;
  mURI = mOriginalURI;
  mListenerMT = new ListenerAndContextContainer(aListener, aContext);
  mOrigin = aOrigin;
  mWasOpened = 1;

  return NS_OK;
}

class CloseEvent : public Runnable {
 public:
  CloseEvent(WebSocketChannelChild* aChild, uint16_t aCode,
             const nsACString& aReason)
      : Runnable("net::CloseEvent"),
        mChild(aChild),
        mCode(aCode),
        mReason(aReason) {
    MOZ_RELEASE_ASSERT(!NS_IsMainThread());
    MOZ_ASSERT(aChild);
  }
  NS_IMETHOD Run() override {
    MOZ_RELEASE_ASSERT(NS_IsMainThread());
    mChild->Close(mCode, mReason);
    return NS_OK;
  }

 private:
  RefPtr<WebSocketChannelChild> mChild;
  uint16_t mCode;
  nsCString mReason;
};

NS_IMETHODIMP
WebSocketChannelChild::Close(uint16_t code, const nsACString& reason) {
  if (!NS_IsMainThread()) {
    MOZ_RELEASE_ASSERT(IsOnTargetThread());
    nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
    return target->Dispatch(new CloseEvent(this, code, reason),
                            NS_DISPATCH_NORMAL);
  }
  LOG(("WebSocketChannelChild::Close() %p\n"this));

  {
    MutexAutoLock lock(mMutex);
    if (mIPCState != Opened) {
      return NS_ERROR_UNEXPECTED;
    }
  }

  if (!SendClose(code, reason)) {
    return NS_ERROR_UNEXPECTED;
  }

  return NS_OK;
}

class MsgEvent : public Runnable {
 public:
  MsgEvent(WebSocketChannelChild* aChild, const nsACString& aMsg,
           bool aBinaryMsg)
      : Runnable("net::MsgEvent"),
        mChild(aChild),
        mMsg(aMsg),
        mBinaryMsg(aBinaryMsg) {
    MOZ_RELEASE_ASSERT(!NS_IsMainThread());
    MOZ_ASSERT(aChild);
  }
  NS_IMETHOD Run() override {
    MOZ_RELEASE_ASSERT(NS_IsMainThread());
    if (mBinaryMsg) {
      mChild->SendBinaryMsg(mMsg);
    } else {
      mChild->SendMsg(mMsg);
    }
    return NS_OK;
  }

 private:
  RefPtr<WebSocketChannelChild> mChild;
  nsCString mMsg;
  bool mBinaryMsg;
};

NS_IMETHODIMP
WebSocketChannelChild::SendMsg(const nsACString& aMsg) {
  if (!NS_IsMainThread()) {
    MOZ_RELEASE_ASSERT(IsOnTargetThread());
    nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
    return target->Dispatch(new MsgEvent(this, aMsg, false),
                            NS_DISPATCH_NORMAL);
  }
  LOG(("WebSocketChannelChild::SendMsg() %p\n"this));

  {
    MutexAutoLock lock(mMutex);
    if (mIPCState != Opened) {
      return NS_ERROR_UNEXPECTED;
    }
  }

  if (!SendSendMsg(aMsg)) {
    return NS_ERROR_UNEXPECTED;
  }

  return NS_OK;
}

NS_IMETHODIMP
WebSocketChannelChild::SendBinaryMsg(const nsACString& aMsg) {
  if (!NS_IsMainThread()) {
    MOZ_RELEASE_ASSERT(IsOnTargetThread());
    nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
    return target->Dispatch(new MsgEvent(this, aMsg, true), NS_DISPATCH_NORMAL);
  }
  LOG(("WebSocketChannelChild::SendBinaryMsg() %p\n"this));

  {
    MutexAutoLock lock(mMutex);
    if (mIPCState != Opened) {
      return NS_ERROR_UNEXPECTED;
    }
  }

  if (!SendSendBinaryMsg(aMsg)) {
    return NS_ERROR_UNEXPECTED;
  }

  return NS_OK;
}

class BinaryStreamEvent : public Runnable {
 public:
  BinaryStreamEvent(WebSocketChannelChild* aChild, nsIInputStream* aStream,
                    uint32_t aLength)
      : Runnable("net::BinaryStreamEvent"),
        mChild(aChild),
        mStream(aStream),
        mLength(aLength) {
    MOZ_RELEASE_ASSERT(!NS_IsMainThread());
    MOZ_ASSERT(aChild);
  }
  NS_IMETHOD Run() override {
    MOZ_ASSERT(NS_IsMainThread());
    nsresult rv = mChild->SendBinaryStream(mStream, mLength);
    if (NS_FAILED(rv)) {
      LOG(
          ("WebSocketChannelChild::BinaryStreamEvent %p "
           "SendBinaryStream failed (%08" PRIx32 ")\n",
           thisstatic_cast<uint32_t>(rv)));
    }
    return NS_OK;
  }

 private:
  RefPtr<WebSocketChannelChild> mChild;
  nsCOMPtr<nsIInputStream> mStream;
  uint32_t mLength;
};

NS_IMETHODIMP
WebSocketChannelChild::SendBinaryStream(nsIInputStream* aStream,
                                        uint32_t aLength) {
  if (!NS_IsMainThread()) {
    MOZ_RELEASE_ASSERT(IsOnTargetThread());
    nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
    return target->Dispatch(new BinaryStreamEvent(this, aStream, aLength),
                            NS_DISPATCH_NORMAL);
  }

  LOG(("WebSocketChannelChild::SendBinaryStream() %p\n"this));

  IPCStream ipcStream;
  if (NS_WARN_IF(!mozilla::ipc::SerializeIPCStream(do_AddRef(aStream),
                                                   ipcStream,
                                                   /* aAllowLazy */ false))) {
    return NS_ERROR_UNEXPECTED;
  }

  {
    MutexAutoLock lock(mMutex);
    if (mIPCState != Opened) {
      return NS_ERROR_UNEXPECTED;
    }
  }

  if (!SendSendBinaryStream(ipcStream, aLength)) {
    return NS_ERROR_UNEXPECTED;
  }

  return NS_OK;
}

NS_IMETHODIMP
WebSocketChannelChild::GetSecurityInfo(
    nsITransportSecurityInfo** aSecurityInfo) {
  LOG(("WebSocketChannelChild::GetSecurityInfo() %p\n"this));
  return NS_ERROR_NOT_AVAILABLE;
}

}  // namespace net
}  // namespace mozilla

100%


¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge