LCOV - code coverage report
Current view: top level - dom/network - UDPSocket.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 376 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13