tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WebSocketConnectionChild.cpp (6516B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set sw=2 ts=8 et ft=cpp : */
      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "WebSocketLog.h"
      8 #include "WebSocketConnectionChild.h"
      9 
     10 #include "WebSocketConnection.h"
     11 #include "mozilla/ipc/Endpoint.h"
     12 #include "mozilla/net/SocketProcessBackgroundChild.h"
     13 #include "mozilla/Components.h"
     14 #include "nsISerializable.h"
     15 #include "nsITLSSocketControl.h"
     16 #include "nsITransportSecurityInfo.h"
     17 #include "nsNetCID.h"
     18 #include "nsSerializationHelper.h"
     19 #include "nsSocketTransportService2.h"
     20 #include "nsThreadUtils.h"
     21 
     22 namespace mozilla {
     23 namespace net {
     24 
     25 NS_IMPL_ISUPPORTS(WebSocketConnectionChild, nsIHttpUpgradeListener)
     26 
     27 WebSocketConnectionChild::WebSocketConnectionChild() {
     28  LOG(("WebSocketConnectionChild ctor %p\n", this));
     29 }
     30 
     31 WebSocketConnectionChild::~WebSocketConnectionChild() {
     32  LOG(("WebSocketConnectionChild dtor %p\n", this));
     33 }
     34 
     35 void WebSocketConnectionChild::Init(uint32_t aListenerId) {
     36  MOZ_ASSERT(NS_IsMainThread());
     37 
     38  nsresult rv;
     39  mSocketThread = mozilla::components::SocketTransport::Service(&rv);
     40  MOZ_ASSERT(NS_SUCCEEDED(rv));
     41  if (!mSocketThread) {
     42    return;
     43  }
     44 
     45  ipc::Endpoint<PWebSocketConnectionParent> parentEndpoint;
     46  ipc::Endpoint<PWebSocketConnectionChild> childEndpoint;
     47  PWebSocketConnection::CreateEndpoints(&parentEndpoint, &childEndpoint);
     48 
     49  if (NS_FAILED(SocketProcessBackgroundChild::WithActor(
     50          "SendInitWebSocketConnection",
     51          [aListenerId, endpoint = std::move(parentEndpoint)](
     52              SocketProcessBackgroundChild* aActor) mutable {
     53            (void)aActor->SendInitWebSocketConnection(std::move(endpoint),
     54                                                      aListenerId);
     55          }))) {
     56    return;
     57  }
     58 
     59  mSocketThread->Dispatch(NS_NewRunnableFunction(
     60      "BindWebSocketConnectionChild",
     61      [self = RefPtr{this}, endpoint = std::move(childEndpoint)]() mutable {
     62        endpoint.Bind(self);
     63      }));
     64 }
     65 
     66 // nsIHttpUpgradeListener
     67 NS_IMETHODIMP
     68 WebSocketConnectionChild::OnTransportAvailable(
     69    nsISocketTransport* aTransport, nsIAsyncInputStream* aSocketIn,
     70    nsIAsyncOutputStream* aSocketOut) {
     71  LOG(("WebSocketConnectionChild::OnTransportAvailable %p\n", this));
     72  if (!OnSocketThread()) {
     73    nsCOMPtr<nsISocketTransport> transport = aTransport;
     74    nsCOMPtr<nsIAsyncInputStream> inputStream = aSocketIn;
     75    nsCOMPtr<nsIAsyncOutputStream> outputStream = aSocketOut;
     76    RefPtr<WebSocketConnectionChild> self = this;
     77    return mSocketThread->Dispatch(
     78        NS_NewRunnableFunction("WebSocketConnectionChild::OnTransportAvailable",
     79                               [self, transport, inputStream, outputStream]() {
     80                                 (void)self->OnTransportAvailable(
     81                                     transport, inputStream, outputStream);
     82                               }),
     83        NS_DISPATCH_NORMAL);
     84  }
     85 
     86  LOG(("WebSocketConnectionChild::OnTransportAvailable %p\n", this));
     87  MOZ_ASSERT(OnSocketThread());
     88  MOZ_ASSERT(!mConnection, "already called");
     89  MOZ_ASSERT(aTransport);
     90 
     91  if (!CanSend()) {
     92    return NS_ERROR_NOT_AVAILABLE;
     93  }
     94 
     95  nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
     96  aTransport->GetTlsSocketControl(getter_AddRefs(tlsSocketControl));
     97  nsCOMPtr<nsITransportSecurityInfo> securityInfo(
     98      do_QueryInterface(tlsSocketControl));
     99 
    100  RefPtr<WebSocketConnection> connection =
    101      new WebSocketConnection(aTransport, aSocketIn, aSocketOut);
    102  nsresult rv = connection->Init(this);
    103  if (NS_FAILED(rv)) {
    104    (void)OnUpgradeFailed(rv);
    105    return NS_OK;
    106  }
    107 
    108  mConnection = std::move(connection);
    109 
    110  (void)SendOnTransportAvailable(securityInfo);
    111  return NS_OK;
    112 }
    113 
    114 NS_IMETHODIMP
    115 WebSocketConnectionChild::OnUpgradeFailed(nsresult aReason) {
    116  if (!OnSocketThread()) {
    117    return mSocketThread->Dispatch(NewRunnableMethod<nsresult>(
    118        "WebSocketConnectionChild::OnUpgradeFailed", this,
    119        &WebSocketConnectionChild::OnUpgradeFailed, aReason));
    120  }
    121 
    122  if (CanSend()) {
    123    (void)SendOnUpgradeFailed(aReason);
    124  }
    125  return NS_OK;
    126 }
    127 
    128 NS_IMETHODIMP
    129 WebSocketConnectionChild::OnWebSocketConnectionAvailable(
    130    WebSocketConnectionBase* aConnection) {
    131  return NS_ERROR_NOT_IMPLEMENTED;
    132 }
    133 
    134 mozilla::ipc::IPCResult WebSocketConnectionChild::RecvWriteOutputData(
    135    nsTArray<uint8_t>&& aData) {
    136  LOG(("WebSocketConnectionChild::RecvWriteOutputData %p\n", this));
    137 
    138  if (!mConnection) {
    139    OnError(NS_ERROR_NOT_AVAILABLE);
    140    return IPC_OK();
    141  }
    142 
    143  mConnection->WriteOutputData(std::move(aData));
    144  return IPC_OK();
    145 }
    146 
    147 mozilla::ipc::IPCResult WebSocketConnectionChild::RecvStartReading() {
    148  LOG(("WebSocketConnectionChild::RecvStartReading %p\n", this));
    149 
    150  if (!mConnection) {
    151    OnError(NS_ERROR_NOT_AVAILABLE);
    152    return IPC_OK();
    153  }
    154 
    155  mConnection->StartReading();
    156  return IPC_OK();
    157 }
    158 
    159 mozilla::ipc::IPCResult WebSocketConnectionChild::RecvDrainSocketData() {
    160  LOG(("WebSocketConnectionChild::RecvDrainSocketData %p\n", this));
    161 
    162  if (!mConnection) {
    163    OnError(NS_ERROR_NOT_AVAILABLE);
    164    return IPC_OK();
    165  }
    166 
    167  mConnection->DrainSocketData();
    168  return IPC_OK();
    169 }
    170 
    171 mozilla::ipc::IPCResult WebSocketConnectionChild::Recv__delete__() {
    172  LOG(("WebSocketConnectionChild::Recv__delete__ %p\n", this));
    173 
    174  if (!mConnection) {
    175    OnError(NS_ERROR_NOT_AVAILABLE);
    176    return IPC_OK();
    177  }
    178 
    179  mConnection->Close();
    180  mConnection = nullptr;
    181  return IPC_OK();
    182 }
    183 
    184 void WebSocketConnectionChild::OnError(nsresult aStatus) {
    185  LOG(("WebSocketConnectionChild::OnError %p\n", this));
    186 
    187  if (CanSend()) {
    188    (void)SendOnError(aStatus);
    189  }
    190 }
    191 
    192 void WebSocketConnectionChild::OnTCPClosed() {
    193  LOG(("WebSocketConnectionChild::OnTCPClosed %p\n", this));
    194 
    195  if (CanSend()) {
    196    (void)SendOnTCPClosed();
    197  }
    198 }
    199 
    200 nsresult WebSocketConnectionChild::OnDataReceived(uint8_t* aData,
    201                                                  uint32_t aCount) {
    202  LOG(("WebSocketConnectionChild::OnDataReceived %p\n", this));
    203 
    204  if (CanSend()) {
    205    nsTArray<uint8_t> data;
    206    data.AppendElements(aData, aCount);
    207    (void)SendOnDataReceived(data);
    208  }
    209 
    210  return NS_OK;
    211 }
    212 
    213 void WebSocketConnectionChild::ActorDestroy(ActorDestroyReason aWhy) {
    214  LOG(("WebSocketConnectionChild::ActorDestroy %p\n", this));
    215  if (mConnection) {
    216    mConnection->Close();
    217    mConnection = nullptr;
    218  }
    219 }
    220 
    221 }  // namespace net
    222 }  // namespace mozilla