Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/netwerk/protocol/websocket/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 7 kB image not shown  

Quelle  WebSocketConnection.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 "nsIInterfaceRequestor.h"
#include "WebSocketConnection.h"

#include "WebSocketLog.h"
#include "mozilla/net/WebSocketConnectionListener.h"
#include "mozilla/Components.h"
#include "nsIOService.h"
#include "nsITLSSocketControl.h"
#include "nsISocketTransport.h"
#include "nsITransportSecurityInfo.h"
#include "nsSocketTransportService2.h"

namespace mozilla::net {

NS_IMPL_ISUPPORTS(WebSocketConnection, nsIInputStreamCallback,
                  nsIOutputStreamCallback)

WebSocketConnection::WebSocketConnection(nsISocketTransport* aTransport,
                                         nsIAsyncInputStream* aInputStream,
                                         nsIAsyncOutputStream* aOutputStream)
    : mTransport(aTransport),
      mSocketIn(aInputStream),
      mSocketOut(aOutputStream) {
  LOG(("WebSocketConnection ctor %p\n"this));
}

WebSocketConnection::~WebSocketConnection() {
  LOG(("WebSocketConnection dtor %p\n"this));
}

nsresult WebSocketConnection::Init(WebSocketConnectionListener* aListener) {
  NS_ENSURE_ARG_POINTER(aListener);

  mListener = aListener;
  nsresult rv;
  mSocketThread = mozilla::components::SocketTransport::Service(&rv);
  if (NS_FAILED(rv)) {
    return rv;
  }

  if (!mTransport) {
    return NS_ERROR_FAILURE;
  }

  if (XRE_IsParentProcess()) {
    nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(mListener);
    mTransport->SetSecurityCallbacks(callbacks);
  } else {
    // NOTE: we don't use security callbacks in socket process.
    mTransport->SetSecurityCallbacks(nullptr);
  }
  return mTransport->SetEventSink(nullptr, nullptr);
}

void WebSocketConnection::GetIoTarget(nsIEventTarget** aTarget) {
  nsCOMPtr<nsIEventTarget> target = mSocketThread;
  return target.forget(aTarget);
}

void WebSocketConnection::Close() {
  LOG(("WebSocketConnection::Close %p\n"this));
  MOZ_ASSERT(OnSocketThread());

  if (mTransport) {
    mTransport->SetSecurityCallbacks(nullptr);
    mTransport->SetEventSink(nullptr, nullptr);
    mTransport->Close(NS_BASE_STREAM_CLOSED);
    mTransport = nullptr;
  }

  if (mSocketIn) {
    if (mStartReadingCalled) {
      mSocketIn->AsyncWait(nullptr, 0, 0, nullptr);
    }
    mSocketIn = nullptr;
  }

  if (mSocketOut) {
    mSocketOut->AsyncWait(nullptr, 0, 0, nullptr);
    mSocketOut = nullptr;
  }
}

nsresult WebSocketConnection::WriteOutputData(nsTArray<uint8_t>&& aData) {
  MOZ_ASSERT(OnSocketThread());

  if (!mSocketOut) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  mOutputQueue.emplace_back(std::move(aData));
  return OnOutputStreamReady(mSocketOut);
}

nsresult WebSocketConnection::WriteOutputData(const uint8_t* aHdrBuf,
                                              uint32_t aHdrBufLength,
                                              const uint8_t* aPayloadBuf,
                                              uint32_t aPayloadBufLength) {
  MOZ_ASSERT_UNREACHABLE("Should not be called");
  return NS_ERROR_NOT_IMPLEMENTED;
}

nsresult WebSocketConnection::StartReading() {
  MOZ_ASSERT(OnSocketThread());

  if (!mSocketIn) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  MOZ_ASSERT(!mStartReadingCalled, "StartReading twice");
  mStartReadingCalled = true;
  return mSocketIn->AsyncWait(this, 0, 0, mSocketThread);
}

void WebSocketConnection::DrainSocketData() {
  MOZ_ASSERT(OnSocketThread());

  if (!mSocketIn || !mListener) {
    return;
  }

  // If we leave any data unconsumed (including the tcp fin) a RST will be
  // generated The right thing to do here is shutdown(SHUT_WR) and then wait a
  // little while to see if any data comes in.. but there is no reason to delay
  // things for that when the websocket handshake is supposed to guarantee a
  // quiet connection except for that fin.
  char buffer[512];
  uint32_t count = 0;
  uint32_t total = 0;
  nsresult rv;
  do {
    total += count;
    rv = mSocketIn->Read(buffer, 512, &count);
    if (rv != NS_BASE_STREAM_WOULD_BLOCK && (NS_FAILED(rv) || count == 0)) {
      mListener->OnTCPClosed();
    }
  } while (NS_SUCCEEDED(rv) && count > 0 && total < 32000);
}

nsresult WebSocketConnection::GetSecurityInfo(
    nsITransportSecurityInfo** aSecurityInfo) {
  LOG(("WebSocketConnection::GetSecurityInfo() %p\n"this));
  MOZ_ASSERT(OnSocketThread());
  *aSecurityInfo = nullptr;

  if (mTransport) {
    nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
    nsresult rv =
        mTransport->GetTlsSocketControl(getter_AddRefs(tlsSocketControl));
    if (NS_FAILED(rv)) {
      return rv;
    }
    nsCOMPtr<nsITransportSecurityInfo> securityInfo(
        do_QueryInterface(tlsSocketControl));
    if (securityInfo) {
      securityInfo.forget(aSecurityInfo);
    }
  }
  return NS_OK;
}

NS_IMETHODIMP
WebSocketConnection::OnInputStreamReady(nsIAsyncInputStream* aStream) {
  LOG(("WebSocketConnection::OnInputStreamReady() %p\n"this));
  MOZ_ASSERT(OnSocketThread());
  MOZ_ASSERT(mListener);

  // did we we clean up the socket after scheduling InputReady?
  if (!mSocketIn) {
    return NS_OK;
  }

  // this is after the http upgrade - so we are speaking websockets
  uint8_t buffer[2048];
  uint32_t count;
  nsresult rv;

  do {
    rv = mSocketIn->Read((char*)buffer, 2048, &count);
    LOG(("WebSocketConnection::OnInputStreamReady: read %u rv %" PRIx32 "\n",
         count, static_cast<uint32_t>(rv)));

    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
      mSocketIn->AsyncWait(this, 0, 0, mSocketThread);
      return NS_OK;
    }

    if (NS_FAILED(rv)) {
      mListener->OnError(rv);
      return rv;
    }

    if (count == 0) {
      mListener->OnError(NS_BASE_STREAM_CLOSED);
      return NS_OK;
    }

    rv = mListener->OnDataReceived(buffer, count);
    if (NS_FAILED(rv)) {
      mListener->OnError(rv);
      return rv;
    }
  } while (NS_SUCCEEDED(rv) && mSocketIn && mListener);

  return NS_OK;
}

NS_IMETHODIMP
WebSocketConnection::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
  LOG(("WebSocketConnection::OnOutputStreamReady() %p\n"this));
  MOZ_ASSERT(OnSocketThread());
  MOZ_ASSERT(mListener);

  if (!mSocketOut) {
    return NS_OK;
  }

  while (!mOutputQueue.empty()) {
    const OutputData& data = mOutputQueue.front();

    char* buffer = reinterpret_cast<char*>(
                       const_cast<uint8_t*>(data.GetData().Elements())) +
                   mWriteOffset;
    uint32_t toWrite = data.GetData().Length() - mWriteOffset;

    uint32_t wrote = 0;
    nsresult rv = mSocketOut->Write(buffer, toWrite, &wrote);
    LOG(("WebSocketConnection::OnOutputStreamReady: write %u rv %" PRIx32,
         wrote, static_cast<uint32_t>(rv)));

    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
      mSocketOut->AsyncWait(this, 0, 0, mSocketThread);
      return rv;
    }

    if (NS_FAILED(rv)) {
      LOG(("WebSocketConnection::OnOutputStreamReady %p failed %u\n"this,
           static_cast<uint32_t>(rv)));
      mListener->OnError(rv);
      return NS_OK;
    }

    mWriteOffset += wrote;

    if (toWrite == wrote) {
      mWriteOffset = 0;
      mOutputQueue.pop_front();
    } else {
      mSocketOut->AsyncWait(this, 0, 0, mSocketThread);
    }
  }

  return NS_OK;
}

}  // namespace mozilla::net

88%


¤ Dauer der Verarbeitung: 0.14 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.