tor-browser

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

UDPSocket.cpp (18997B)


      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
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "UDPSocket.h"
      8 
      9 #include "mozilla/AsyncEventDispatcher.h"
     10 #include "mozilla/dom/ErrorEvent.h"
     11 #include "mozilla/dom/File.h"
     12 #include "mozilla/dom/RootedDictionary.h"
     13 #include "mozilla/dom/UDPMessageEvent.h"
     14 #include "mozilla/dom/UDPSocketBinding.h"
     15 #include "mozilla/dom/UnionTypes.h"
     16 #include "mozilla/dom/network/UDPSocketChild.h"
     17 #include "mozilla/net/DNS.h"
     18 #include "nsComponentManagerUtils.h"
     19 #include "nsContentUtils.h"
     20 #include "nsINetAddr.h"
     21 #include "nsStringStream.h"
     22 
     23 namespace mozilla::dom {
     24 
     25 NS_IMPL_ISUPPORTS(UDPSocket::ListenerProxy, nsIUDPSocketListener,
     26                  nsIUDPSocketInternal)
     27 
     28 NS_IMPL_CYCLE_COLLECTION_CLASS(UDPSocket)
     29 
     30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(UDPSocket,
     31                                                  DOMEventTargetHelper)
     32  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpened)
     33  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mClosed)
     34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     35 
     36 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(UDPSocket, DOMEventTargetHelper)
     37  NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpened)
     38  NS_IMPL_CYCLE_COLLECTION_UNLINK(mClosed)
     39  tmp->CloseWithReason(NS_OK);
     40 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     41 
     42 NS_IMPL_ADDREF_INHERITED(UDPSocket, DOMEventTargetHelper)
     43 NS_IMPL_RELEASE_INHERITED(UDPSocket, DOMEventTargetHelper)
     44 
     45 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(UDPSocket)
     46  NS_INTERFACE_MAP_ENTRY(nsIUDPSocketListener)
     47  NS_INTERFACE_MAP_ENTRY(nsIUDPSocketInternal)
     48 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     49 
     50 /* static */
     51 already_AddRefed<UDPSocket> UDPSocket::Constructor(const GlobalObject& aGlobal,
     52                                                   const UDPOptions& aOptions,
     53                                                   ErrorResult& aRv) {
     54  nsCOMPtr<nsPIDOMWindowInner> ownerWindow =
     55      do_QueryInterface(aGlobal.GetAsSupports());
     56  if (!ownerWindow) {
     57    aRv.Throw(NS_ERROR_FAILURE);
     58    return nullptr;
     59  }
     60 
     61  bool addressReuse = aOptions.mAddressReuse;
     62  bool loopback = aOptions.mLoopback;
     63 
     64  nsCString remoteAddress;
     65  if (aOptions.mRemoteAddress.WasPassed()) {
     66    CopyUTF16toUTF8(aOptions.mRemoteAddress.Value(), remoteAddress);
     67  } else {
     68    remoteAddress.SetIsVoid(true);
     69  }
     70 
     71  Nullable<uint16_t> remotePort;
     72  if (aOptions.mRemotePort.WasPassed()) {
     73    remotePort.SetValue(aOptions.mRemotePort.Value());
     74 
     75    if (remotePort.Value() == 0) {
     76      aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     77      return nullptr;
     78    }
     79  }
     80 
     81  nsString localAddress;
     82  if (aOptions.mLocalAddress.WasPassed()) {
     83    localAddress = aOptions.mLocalAddress.Value();
     84 
     85    // check if localAddress is a valid IPv4/6 address
     86    NS_ConvertUTF16toUTF8 address(localAddress);
     87    if (!net::HostIsIPLiteral(address)) {
     88      aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     89      return nullptr;
     90    }
     91  } else {
     92    SetDOMStringToNull(localAddress);
     93  }
     94 
     95  Nullable<uint16_t> localPort;
     96  if (aOptions.mLocalPort.WasPassed()) {
     97    localPort.SetValue(aOptions.mLocalPort.Value());
     98 
     99    if (localPort.Value() == 0) {
    100      aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    101      return nullptr;
    102    }
    103  }
    104 
    105  RefPtr<UDPSocket> socket =
    106      new UDPSocket(ownerWindow, remoteAddress, remotePort);
    107  aRv = socket->Init(localAddress, localPort, addressReuse, loopback);
    108 
    109  if (NS_WARN_IF(aRv.Failed())) {
    110    return nullptr;
    111  }
    112 
    113  return socket.forget();
    114 }
    115 
    116 UDPSocket::UDPSocket(nsPIDOMWindowInner* aOwner,
    117                     const nsCString& aRemoteAddress,
    118                     const Nullable<uint16_t>& aRemotePort)
    119    : DOMEventTargetHelper(aOwner),
    120      mRemoteAddress(aRemoteAddress),
    121      mRemotePort(aRemotePort),
    122      mAddressReuse(false),
    123      mLoopback(false),
    124      mReadyState(SocketReadyState::Opening) {
    125  MOZ_ASSERT(aOwner);
    126 
    127  Document* aDoc = aOwner->GetExtantDoc();
    128  if (aDoc) {
    129    aDoc->DisallowBFCaching();
    130  }
    131 }
    132 
    133 UDPSocket::~UDPSocket() { CloseWithReason(NS_OK); }
    134 
    135 JSObject* UDPSocket::WrapObject(JSContext* aCx,
    136                                JS::Handle<JSObject*> aGivenProto) {
    137  return UDPSocket_Binding::Wrap(aCx, this, aGivenProto);
    138 }
    139 
    140 void UDPSocket::DisconnectFromOwner() {
    141  DOMEventTargetHelper::DisconnectFromOwner();
    142  CloseWithReason(NS_OK);
    143 }
    144 
    145 already_AddRefed<Promise> UDPSocket::Close() {
    146  MOZ_ASSERT(mClosed);
    147 
    148  RefPtr<Promise> promise = mClosed;
    149 
    150  if (mReadyState == SocketReadyState::Closed) {
    151    return promise.forget();
    152  }
    153 
    154  CloseWithReason(NS_OK);
    155  return promise.forget();
    156 }
    157 
    158 void UDPSocket::CloseWithReason(nsresult aReason) {
    159  if (mReadyState == SocketReadyState::Closed) {
    160    return;
    161  }
    162 
    163  if (mOpened) {
    164    if (mReadyState == SocketReadyState::Opening) {
    165      // reject openedPromise with AbortError if socket is closed without error
    166      nsresult openFailedReason =
    167          NS_FAILED(aReason) ? aReason : NS_ERROR_DOM_ABORT_ERR;
    168      mOpened->MaybeReject(openFailedReason);
    169    }
    170  }
    171 
    172  mReadyState = SocketReadyState::Closed;
    173 
    174  if (mListenerProxy) {
    175    mListenerProxy->Disconnect();
    176    mListenerProxy = nullptr;
    177  }
    178 
    179  if (mSocket) {
    180    mSocket->Close();
    181    mSocket = nullptr;
    182  }
    183 
    184  if (mSocketChild) {
    185    mSocketChild->Close();
    186    mSocketChild = nullptr;
    187  }
    188 
    189  if (mClosed) {
    190    if (NS_SUCCEEDED(aReason)) {
    191      mClosed->MaybeResolveWithUndefined();
    192    } else {
    193      mClosed->MaybeReject(aReason);
    194    }
    195  }
    196 
    197  mPendingMcastCommands.Clear();
    198 }
    199 
    200 void UDPSocket::JoinMulticastGroup(const nsAString& aMulticastGroupAddress,
    201                                   ErrorResult& aRv) {
    202  if (mReadyState == SocketReadyState::Closed) {
    203    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    204    return;
    205  }
    206 
    207  if (mReadyState == SocketReadyState::Opening) {
    208    MulticastCommand joinCommand(MulticastCommand::Join,
    209                                 aMulticastGroupAddress);
    210    mPendingMcastCommands.AppendElement(joinCommand);
    211    return;
    212  }
    213 
    214  MOZ_ASSERT(mSocket || mSocketChild);
    215 
    216  NS_ConvertUTF16toUTF8 address(aMulticastGroupAddress);
    217 
    218  if (mSocket) {
    219    MOZ_ASSERT(!mSocketChild);
    220 
    221    aRv = mSocket->JoinMulticast(address, ""_ns);
    222    NS_WARNING_ASSERTION(!aRv.Failed(), "JoinMulticast failed");
    223 
    224    return;
    225  }
    226 
    227  MOZ_ASSERT(mSocketChild);
    228 
    229  mSocketChild->JoinMulticast(address, ""_ns);
    230 }
    231 
    232 void UDPSocket::LeaveMulticastGroup(const nsAString& aMulticastGroupAddress,
    233                                    ErrorResult& aRv) {
    234  if (mReadyState == SocketReadyState::Closed) {
    235    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    236    return;
    237  }
    238 
    239  if (mReadyState == SocketReadyState::Opening) {
    240    MulticastCommand leaveCommand(MulticastCommand::Leave,
    241                                  aMulticastGroupAddress);
    242    mPendingMcastCommands.AppendElement(leaveCommand);
    243    return;
    244  }
    245 
    246  MOZ_ASSERT(mSocket || mSocketChild);
    247 
    248  nsCString address = NS_ConvertUTF16toUTF8(aMulticastGroupAddress);
    249  if (mSocket) {
    250    MOZ_ASSERT(!mSocketChild);
    251 
    252    aRv = mSocket->LeaveMulticast(address, ""_ns);
    253    NS_WARNING_ASSERTION(!aRv.Failed(), "mSocket->LeaveMulticast failed");
    254    return;
    255  }
    256 
    257  MOZ_ASSERT(mSocketChild);
    258 
    259  mSocketChild->LeaveMulticast(address, ""_ns);
    260 }
    261 
    262 nsresult UDPSocket::DoPendingMcastCommand() {
    263  MOZ_ASSERT(mReadyState == SocketReadyState::Open,
    264             "Multicast command can only be executed after socket opened");
    265 
    266  for (uint32_t i = 0; i < mPendingMcastCommands.Length(); ++i) {
    267    MulticastCommand& command = mPendingMcastCommands[i];
    268    ErrorResult rv;
    269 
    270    switch (command.mCommand) {
    271      case MulticastCommand::Join: {
    272        JoinMulticastGroup(command.mAddress, rv);
    273        break;
    274      }
    275      case MulticastCommand::Leave: {
    276        LeaveMulticastGroup(command.mAddress, rv);
    277        break;
    278      }
    279    }
    280 
    281    if (NS_WARN_IF(rv.Failed())) {
    282      return rv.StealNSResult();
    283    }
    284  }
    285 
    286  mPendingMcastCommands.Clear();
    287  return NS_OK;
    288 }
    289 
    290 bool UDPSocket::Send(const StringOrBlobOrArrayBufferOrArrayBufferView& aData,
    291                     const Optional<nsAString>& aRemoteAddress,
    292                     const Optional<Nullable<uint16_t>>& aRemotePort,
    293                     ErrorResult& aRv) {
    294  if (mReadyState != SocketReadyState::Open) {
    295    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    296    return false;
    297  }
    298 
    299  MOZ_ASSERT(mSocket || mSocketChild);
    300 
    301  // If the remote address and port were not specified in the constructor or as
    302  // arguments, throw InvalidAccessError.
    303  nsCString remoteAddress;
    304  if (aRemoteAddress.WasPassed()) {
    305    CopyUTF16toUTF8(aRemoteAddress.Value(), remoteAddress);
    306    UDPSOCKET_LOG(("%s: Send to %s", __FUNCTION__, remoteAddress.get()));
    307  } else if (!mRemoteAddress.IsVoid()) {
    308    remoteAddress = mRemoteAddress;
    309    UDPSOCKET_LOG(("%s: Send to %s", __FUNCTION__, remoteAddress.get()));
    310  } else {
    311    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    312    return false;
    313  }
    314 
    315  uint16_t remotePort;
    316  if (aRemotePort.WasPassed() && !aRemotePort.Value().IsNull()) {
    317    remotePort = aRemotePort.Value().Value();
    318  } else if (!mRemotePort.IsNull()) {
    319    remotePort = mRemotePort.Value();
    320  } else {
    321    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    322    return false;
    323  }
    324 
    325  nsCOMPtr<nsIInputStream> stream;
    326  if (aData.IsBlob()) {
    327    Blob& blob = aData.GetAsBlob();
    328 
    329    blob.CreateInputStream(getter_AddRefs(stream), aRv);
    330    if (NS_WARN_IF(aRv.Failed())) {
    331      return false;
    332    }
    333  } else {
    334    nsresult rv;
    335    nsCOMPtr<nsIStringInputStream> strStream =
    336        do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
    337    if (NS_WARN_IF(NS_FAILED(rv))) {
    338      aRv.Throw(rv);
    339      return false;
    340    }
    341 
    342    if (aData.IsString()) {
    343      aRv = strStream->SetUTF8Data(NS_ConvertUTF16toUTF8(aData.GetAsString()));
    344    } else {
    345      Vector<char> data;
    346      if (!AppendTypedArrayDataTo(aData, data)) {
    347        aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    348        return false;
    349      }
    350      size_t length = data.length();
    351      aRv = strStream->AdoptData(data.extractOrCopyRawBuffer(), length);
    352    }
    353 
    354    if (NS_WARN_IF(aRv.Failed())) {
    355      return false;
    356    }
    357 
    358    stream = strStream;
    359  }
    360 
    361  if (mSocket) {
    362    aRv = mSocket->SendBinaryStream(remoteAddress, remotePort, stream);
    363  } else if (mSocketChild) {
    364    aRv = mSocketChild->SendBinaryStream(remoteAddress, remotePort, stream);
    365  }
    366 
    367  if (NS_WARN_IF(aRv.Failed())) {
    368    return false;
    369  }
    370 
    371  return true;
    372 }
    373 
    374 nsresult UDPSocket::InitLocal(const nsAString& aLocalAddress,
    375                              const uint16_t& aLocalPort) {
    376  nsresult rv;
    377  nsCOMPtr<nsIUDPSocket> sock =
    378      do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
    379  if (NS_FAILED(rv)) {
    380    return rv;
    381  }
    382 
    383  nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
    384  if (!global) {
    385    return NS_ERROR_FAILURE;
    386  }
    387 
    388  nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
    389  if (!principal) {
    390    return NS_ERROR_FAILURE;
    391  }
    392 
    393  if (aLocalAddress.IsEmpty()) {
    394    rv = sock->Init(aLocalPort, /* loopback = */ false, principal,
    395                    mAddressReuse, /* optionalArgc = */ 1);
    396  } else {
    397    PRNetAddr prAddr;
    398    PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr);
    399    PR_StringToNetAddr(NS_ConvertUTF16toUTF8(aLocalAddress).BeginReading(),
    400                       &prAddr);
    401    UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__,
    402                   NS_ConvertUTF16toUTF8(aLocalAddress).get(), aLocalPort));
    403 
    404    mozilla::net::NetAddr addr(&prAddr);
    405    rv = sock->InitWithAddress(&addr, principal, mAddressReuse,
    406                               /* optionalArgc = */ 1);
    407  }
    408  if (NS_FAILED(rv)) {
    409    return rv;
    410  }
    411 
    412  rv = sock->SetMulticastLoopback(mLoopback);
    413  if (NS_FAILED(rv)) {
    414    return rv;
    415  }
    416 
    417  mSocket = sock;
    418 
    419  // Get real local address and local port
    420  nsCOMPtr<nsINetAddr> localAddr;
    421  rv = mSocket->GetLocalAddr(getter_AddRefs(localAddr));
    422  if (NS_FAILED(rv)) {
    423    return rv;
    424  }
    425 
    426  nsCString localAddress;
    427  rv = localAddr->GetAddress(localAddress);
    428  if (NS_FAILED(rv)) {
    429    return rv;
    430  }
    431  CopyUTF8toUTF16(localAddress, mLocalAddress);
    432 
    433  uint16_t localPort;
    434  rv = localAddr->GetPort(&localPort);
    435  if (NS_FAILED(rv)) {
    436    return rv;
    437  }
    438  mLocalPort.SetValue(localPort);
    439 
    440  mListenerProxy = new ListenerProxy(this);
    441 
    442  rv = mSocket->AsyncListen(mListenerProxy);
    443  if (NS_FAILED(rv)) {
    444    return rv;
    445  }
    446 
    447  mReadyState = SocketReadyState::Open;
    448  rv = DoPendingMcastCommand();
    449  if (NS_FAILED(rv)) {
    450    return rv;
    451  }
    452 
    453  mOpened->MaybeResolveWithUndefined();
    454 
    455  return NS_OK;
    456 }
    457 
    458 nsresult UDPSocket::InitRemote(const nsAString& aLocalAddress,
    459                               const uint16_t& aLocalPort) {
    460  RefPtr<UDPSocketChild> sock = new UDPSocketChild();
    461 
    462  mListenerProxy = new ListenerProxy(this);
    463 
    464  nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
    465  if (!global) {
    466    return NS_ERROR_FAILURE;
    467  }
    468 
    469  nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
    470  if (!principal) {
    471    return NS_ERROR_FAILURE;
    472  }
    473 
    474  nsresult rv = sock->Bind(mListenerProxy, principal,
    475                           NS_ConvertUTF16toUTF8(aLocalAddress), aLocalPort,
    476                           mAddressReuse, mLoopback, 0, 0);
    477 
    478  if (NS_FAILED(rv)) {
    479    return rv;
    480  }
    481 
    482  mSocketChild = sock;
    483 
    484  return NS_OK;
    485 }
    486 
    487 nsresult UDPSocket::Init(const nsString& aLocalAddress,
    488                         const Nullable<uint16_t>& aLocalPort,
    489                         const bool& aAddressReuse, const bool& aLoopback) {
    490  MOZ_ASSERT(!mSocket && !mSocketChild);
    491 
    492  mLocalAddress = aLocalAddress;
    493  mLocalPort = aLocalPort;
    494  mAddressReuse = aAddressReuse;
    495  mLoopback = aLoopback;
    496 
    497  nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
    498 
    499  ErrorResult rv;
    500  mOpened = Promise::Create(global, rv);
    501  if (NS_WARN_IF(rv.Failed())) {
    502    return rv.StealNSResult();
    503  }
    504 
    505  mClosed = Promise::Create(global, rv);
    506  if (NS_WARN_IF(rv.Failed())) {
    507    return rv.StealNSResult();
    508  }
    509 
    510  class OpenSocketRunnable final : public Runnable {
    511   public:
    512    explicit OpenSocketRunnable(UDPSocket* aSocket)
    513        : mozilla::Runnable("OpenSocketRunnable"), mSocket(aSocket) {}
    514 
    515    NS_IMETHOD Run() override {
    516      MOZ_ASSERT(mSocket);
    517 
    518      if (mSocket->mReadyState != SocketReadyState::Opening) {
    519        return NS_OK;
    520      }
    521 
    522      uint16_t localPort = 0;
    523      if (!mSocket->mLocalPort.IsNull()) {
    524        localPort = mSocket->mLocalPort.Value();
    525      }
    526 
    527      nsresult rv;
    528      if (!XRE_IsParentProcess()) {
    529        rv = mSocket->InitRemote(mSocket->mLocalAddress, localPort);
    530      } else {
    531        rv = mSocket->InitLocal(mSocket->mLocalAddress, localPort);
    532      }
    533 
    534      if (NS_WARN_IF(NS_FAILED(rv))) {
    535        mSocket->CloseWithReason(NS_ERROR_DOM_NETWORK_ERR);
    536      }
    537 
    538      return NS_OK;
    539    }
    540 
    541   private:
    542    RefPtr<UDPSocket> mSocket;
    543  };
    544 
    545  nsCOMPtr<nsIRunnable> runnable = new OpenSocketRunnable(this);
    546 
    547  return NS_DispatchToMainThread(runnable);
    548 }
    549 
    550 void UDPSocket::HandleReceivedData(const nsACString& aRemoteAddress,
    551                                   const uint16_t& aRemotePort,
    552                                   const nsTArray<uint8_t>& aData) {
    553  if (mReadyState != SocketReadyState::Open) {
    554    return;
    555  }
    556 
    557  if (NS_FAILED(CheckCurrentGlobalCorrectness())) {
    558    return;
    559  }
    560 
    561  if (NS_FAILED(DispatchReceivedData(aRemoteAddress, aRemotePort, aData))) {
    562    CloseWithReason(NS_ERROR_UNEXPECTED);
    563  }
    564 }
    565 
    566 nsresult UDPSocket::DispatchReceivedData(const nsACString& aRemoteAddress,
    567                                         const uint16_t& aRemotePort,
    568                                         const nsTArray<uint8_t>& aData) {
    569  AutoJSAPI jsapi;
    570 
    571  if (NS_WARN_IF(!jsapi.Init(GetOwnerWindow()))) {
    572    return NS_ERROR_FAILURE;
    573  }
    574 
    575  JSContext* cx = jsapi.cx();
    576 
    577  // Copy packet data to ArrayBuffer
    578  ErrorResult error;
    579  JS::Rooted<JSObject*> arrayBuf(cx, ArrayBuffer::Create(cx, aData, error));
    580 
    581  error.WouldReportJSException();
    582  if (NS_WARN_IF(error.Failed())) {
    583    return error.StealNSResult();
    584  }
    585 
    586  JS::Rooted<JS::Value> jsData(cx, JS::ObjectValue(*arrayBuf));
    587 
    588  // Create DOM event
    589  RootedDictionary<UDPMessageEventInit> init(cx);
    590  CopyUTF8toUTF16(aRemoteAddress, init.mRemoteAddress);
    591  init.mRemotePort = aRemotePort;
    592  init.mData = jsData;
    593 
    594  RefPtr<UDPMessageEvent> udpEvent =
    595      UDPMessageEvent::Constructor(this, u"message"_ns, init);
    596 
    597  if (NS_WARN_IF(!udpEvent)) {
    598    return NS_ERROR_FAILURE;
    599  }
    600 
    601  udpEvent->SetTrusted(true);
    602 
    603  RefPtr<AsyncEventDispatcher> asyncDispatcher =
    604      new AsyncEventDispatcher(this, udpEvent.forget());
    605 
    606  return asyncDispatcher->PostDOMEvent();
    607 }
    608 
    609 // nsIUDPSocketListener
    610 
    611 NS_IMETHODIMP
    612 UDPSocket::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage) {
    613  // nsIUDPSocketListener callbacks should be invoked on main thread.
    614  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
    615 
    616  // Create appropriate JS object for message
    617  FallibleTArray<uint8_t>& buffer = aMessage->GetDataAsTArray();
    618 
    619  nsCOMPtr<nsINetAddr> addr;
    620  if (NS_WARN_IF(NS_FAILED(aMessage->GetFromAddr(getter_AddRefs(addr))))) {
    621    return NS_OK;
    622  }
    623 
    624  nsCString remoteAddress;
    625  if (NS_WARN_IF(NS_FAILED(addr->GetAddress(remoteAddress)))) {
    626    return NS_OK;
    627  }
    628 
    629  uint16_t remotePort;
    630  if (NS_WARN_IF(NS_FAILED(addr->GetPort(&remotePort)))) {
    631    return NS_OK;
    632  }
    633 
    634  HandleReceivedData(remoteAddress, remotePort, buffer);
    635  return NS_OK;
    636 }
    637 
    638 NS_IMETHODIMP
    639 UDPSocket::OnStopListening(nsIUDPSocket* aSocket, nsresult aStatus) {
    640  // nsIUDPSocketListener callbacks should be invoked on main thread.
    641  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
    642 
    643  CloseWithReason(aStatus);
    644 
    645  return NS_OK;
    646 }
    647 
    648 // nsIUDPSocketInternal
    649 
    650 NS_IMETHODIMP
    651 UDPSocket::CallListenerError(const nsACString& aMessage,
    652                             const nsACString& aFilename,
    653                             uint32_t aLineNumber) {
    654  CloseWithReason(NS_ERROR_DOM_NETWORK_ERR);
    655 
    656  return NS_OK;
    657 }
    658 
    659 NS_IMETHODIMP
    660 UDPSocket::CallListenerReceivedData(const nsACString& aRemoteAddress,
    661                                    uint16_t aRemotePort,
    662                                    const nsTArray<uint8_t>& aData) {
    663  HandleReceivedData(aRemoteAddress, aRemotePort, aData);
    664 
    665  return NS_OK;
    666 }
    667 
    668 NS_IMETHODIMP
    669 UDPSocket::CallListenerOpened() {
    670  if (mReadyState != SocketReadyState::Opening) {
    671    return NS_OK;
    672  }
    673 
    674  MOZ_ASSERT(mSocketChild);
    675 
    676  // Get real local address and local port
    677  CopyUTF8toUTF16(mSocketChild->LocalAddress(), mLocalAddress);
    678 
    679  mLocalPort.SetValue(mSocketChild->LocalPort());
    680 
    681  mReadyState = SocketReadyState::Open;
    682  nsresult rv = DoPendingMcastCommand();
    683 
    684  if (NS_WARN_IF(NS_FAILED(rv))) {
    685    CloseWithReason(rv);
    686    return NS_OK;
    687  }
    688 
    689  mOpened->MaybeResolveWithUndefined();
    690 
    691  return NS_OK;
    692 }
    693 
    694 NS_IMETHODIMP
    695 UDPSocket::CallListenerConnected() {
    696  // This shouldn't be called here.
    697  MOZ_CRASH();
    698 
    699  return NS_OK;
    700 }
    701 
    702 NS_IMETHODIMP
    703 UDPSocket::CallListenerClosed() {
    704  CloseWithReason(NS_OK);
    705 
    706  return NS_OK;
    707 }
    708 
    709 }  // namespace mozilla::dom