tor-browser

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

TCPServerSocket.cpp (5828B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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 "TCPServerSocket.h"
      8 
      9 #include "TCPServerSocketChild.h"
     10 #include "TCPServerSocketParent.h"
     11 #include "TCPSocket.h"
     12 #include "mozilla/ErrorResult.h"
     13 #include "mozilla/dom/Event.h"
     14 #include "mozilla/dom/TCPServerSocketBinding.h"
     15 #include "mozilla/dom/TCPServerSocketEvent.h"
     16 #include "mozilla/dom/TCPSocketBinding.h"
     17 #include "nsComponentManagerUtils.h"
     18 #include "nsGlobalWindowInner.h"
     19 
     20 using namespace mozilla::dom;
     21 
     22 NS_IMPL_CYCLE_COLLECTION_CLASS(TCPServerSocket)
     23 
     24 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(TCPServerSocket,
     25                                               DOMEventTargetHelper)
     26 NS_IMPL_CYCLE_COLLECTION_TRACE_END
     27 
     28 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TCPServerSocket,
     29                                                  DOMEventTargetHelper)
     30  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerSocket)
     31  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerBridgeChild)
     32  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerBridgeParent)
     33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     34 
     35 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TCPServerSocket,
     36                                                DOMEventTargetHelper)
     37  NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerSocket)
     38  NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerBridgeChild)
     39  NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerBridgeParent)
     40 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     41 
     42 NS_IMPL_ADDREF_INHERITED(TCPServerSocket, DOMEventTargetHelper)
     43 NS_IMPL_RELEASE_INHERITED(TCPServerSocket, DOMEventTargetHelper)
     44 
     45 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPServerSocket)
     46  NS_INTERFACE_MAP_ENTRY(nsIServerSocketListener)
     47 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     48 
     49 TCPServerSocket::TCPServerSocket(nsIGlobalObject* aGlobal, uint16_t aPort,
     50                                 bool aUseArrayBuffers, uint16_t aBacklog)
     51    : DOMEventTargetHelper(aGlobal),
     52      mPort(aPort),
     53      mBacklog(aBacklog),
     54      mUseArrayBuffers(aUseArrayBuffers) {}
     55 
     56 TCPServerSocket::~TCPServerSocket() = default;
     57 
     58 nsresult TCPServerSocket::Init() {
     59  if (mServerSocket || mServerBridgeChild) {
     60    NS_WARNING("Child TCPServerSocket is already listening.");
     61    return NS_ERROR_FAILURE;
     62  }
     63 
     64  if (XRE_GetProcessType() == GeckoProcessType_Content) {
     65    mServerBridgeChild =
     66        new TCPServerSocketChild(this, mPort, mBacklog, mUseArrayBuffers);
     67    return NS_OK;
     68  }
     69 
     70  nsresult rv;
     71  mServerSocket =
     72      do_CreateInstance("@mozilla.org/network/server-socket;1", &rv);
     73  NS_ENSURE_SUCCESS(rv, rv);
     74  rv = mServerSocket->Init(mPort, false, mBacklog);
     75  NS_ENSURE_SUCCESS(rv, rv);
     76  rv = mServerSocket->GetPort(&mPort);
     77  NS_ENSURE_SUCCESS(rv, rv);
     78  rv = mServerSocket->AsyncListen(this);
     79  NS_ENSURE_SUCCESS(rv, rv);
     80  return NS_OK;
     81 }
     82 
     83 already_AddRefed<TCPServerSocket> TCPServerSocket::Constructor(
     84    const GlobalObject& aGlobal, uint16_t aPort,
     85    const ServerSocketOptions& aOptions, uint16_t aBacklog,
     86    mozilla::ErrorResult& aRv) {
     87  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
     88  if (!global) {
     89    aRv = NS_ERROR_FAILURE;
     90    return nullptr;
     91  }
     92  bool useArrayBuffers =
     93      aOptions.mBinaryType == TCPSocketBinaryType::Arraybuffer;
     94  RefPtr<TCPServerSocket> socket =
     95      new TCPServerSocket(global, aPort, useArrayBuffers, aBacklog);
     96  nsresult rv = socket->Init();
     97  if (NS_WARN_IF(NS_FAILED(rv))) {
     98    aRv = NS_ERROR_FAILURE;
     99    return nullptr;
    100  }
    101  return socket.forget();
    102 }
    103 
    104 uint16_t TCPServerSocket::LocalPort() const { return mPort; }
    105 
    106 void TCPServerSocket::Close() {
    107  if (mServerBridgeChild) {
    108    mServerBridgeChild->Close();
    109  }
    110  if (mServerSocket) {
    111    mServerSocket->Close();
    112  }
    113 }
    114 
    115 void TCPServerSocket::FireEvent(const nsAString& aType, TCPSocket* aSocket) {
    116  TCPServerSocketEventInit init;
    117  init.mBubbles = false;
    118  init.mCancelable = false;
    119  init.mSocket = aSocket;
    120 
    121  RefPtr<TCPServerSocketEvent> event =
    122      TCPServerSocketEvent::Constructor(this, aType, init);
    123  event->SetTrusted(true);
    124  DispatchEvent(*event);
    125 
    126  if (mServerBridgeParent) {
    127    mServerBridgeParent->OnConnect(event);
    128  }
    129 }
    130 
    131 NS_IMETHODIMP
    132 TCPServerSocket::OnSocketAccepted(nsIServerSocket* aServer,
    133                                  nsISocketTransport* aTransport) {
    134  nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
    135  RefPtr<TCPSocket> socket =
    136      TCPSocket::CreateAcceptedSocket(global, aTransport, mUseArrayBuffers);
    137  FireEvent(u"connect"_ns, socket);
    138  return NS_OK;
    139 }
    140 
    141 NS_IMETHODIMP
    142 TCPServerSocket::OnStopListening(nsIServerSocket* aServer, nsresult aStatus) {
    143  if (aStatus != NS_BINDING_ABORTED) {
    144    RefPtr<Event> event = new Event(GetOwnerWindow());
    145    event->InitEvent(u"error"_ns, false, false);
    146    event->SetTrusted(true);
    147    DispatchEvent(*event);
    148 
    149    NS_WARNING("Server socket was closed by unexpected reason.");
    150    return NS_ERROR_FAILURE;
    151  }
    152  mServerSocket = nullptr;
    153  return NS_OK;
    154 }
    155 
    156 nsresult TCPServerSocket::AcceptChildSocket(TCPSocketChild* aSocketChild) {
    157  nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
    158  NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
    159  RefPtr<TCPSocket> socket =
    160      TCPSocket::CreateAcceptedSocket(global, aSocketChild, mUseArrayBuffers);
    161  NS_ENSURE_TRUE(socket, NS_ERROR_FAILURE);
    162  FireEvent(u"connect"_ns, socket);
    163  return NS_OK;
    164 }
    165 
    166 void TCPServerSocket::SetServerBridgeParent(
    167    TCPServerSocketParent* aBridgeParent) {
    168  mServerBridgeParent = aBridgeParent;
    169 }
    170 
    171 JSObject* TCPServerSocket::WrapObject(JSContext* aCx,
    172                                      JS::Handle<JSObject*> aGivenProto) {
    173  return TCPServerSocket_Binding::Wrap(aCx, this, aGivenProto);
    174 }