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