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/. */
7 #include "UDPSocketChild.h"
9 #include "mozilla/Unused.h"
10 #include "mozilla/ipc/IPCStreamUtils.h"
11 #include "mozilla/net/NeckoChild.h"
12 #include "mozilla/dom/ContentChild.h"
13 #include "mozilla/dom/PermissionMessageUtils.h"
14 #include "mozilla/ipc/BackgroundChild.h"
15 #include "mozilla/ipc/PBackgroundChild.h"
16 #include "mozilla/ipc/BackgroundUtils.h"
17 #include "mozilla/ipc/PBackgroundSharedTypes.h"
19 using mozilla::net::gNeckoChild
;
21 namespace mozilla::dom
{
23 NS_IMPL_ISUPPORTS(UDPSocketChildBase
, nsISupports
)
25 UDPSocketChildBase::UDPSocketChildBase() : mIPCOpen(false) {}
27 UDPSocketChildBase::~UDPSocketChildBase() = default;
29 void UDPSocketChildBase::ReleaseIPDLReference() {
36 void UDPSocketChildBase::AddIPDLReference() {
37 MOZ_ASSERT(!mIPCOpen
);
42 NS_IMETHODIMP_(MozExternalRefCountType
) UDPSocketChild::Release(void) {
43 nsrefcnt refcnt
= UDPSocketChildBase::Release();
44 if (refcnt
== 1 && mIPCOpen
) {
45 PUDPSocketChild::SendRequestDelete();
51 UDPSocketChild::UDPSocketChild() : mBackgroundManager(nullptr), mLocalPort(0) {}
53 UDPSocketChild::~UDPSocketChild() = default;
55 nsresult
UDPSocketChild::SetBackgroundSpinsEvents() {
56 using mozilla::ipc::BackgroundChild
;
58 mBackgroundManager
= BackgroundChild::GetOrCreateForCurrentThread();
59 if (NS_WARN_IF(!mBackgroundManager
)) {
60 return NS_ERROR_FAILURE
;
66 nsresult
UDPSocketChild::Bind(nsIUDPSocketInternal
* aSocket
,
67 nsIPrincipal
* aPrincipal
, const nsACString
& aHost
,
68 uint16_t aPort
, bool aAddressReuse
,
69 bool aLoopback
, uint32_t recvBufferSize
,
70 uint32_t sendBufferSize
) {
72 ("%s: %s:%u", __FUNCTION__
, PromiseFlatCString(aHost
).get(), aPort
));
74 NS_ENSURE_ARG(aSocket
);
76 if (NS_IsMainThread()) {
77 if (!gNeckoChild
->SendPUDPSocketConstructor(this, aPrincipal
,
79 return NS_ERROR_FAILURE
;
82 if (!mBackgroundManager
) {
83 return NS_ERROR_NOT_AVAILABLE
;
86 // If we want to support a passed-in principal here we'd need to
87 // convert it to a PrincipalInfo
88 MOZ_ASSERT(!aPrincipal
);
89 if (!mBackgroundManager
->SendPUDPSocketConstructor(this, Nothing(),
91 return NS_ERROR_FAILURE
;
98 SendBind(UDPAddressInfo(nsCString(aHost
), aPort
), aAddressReuse
, aLoopback
,
99 recvBufferSize
, sendBufferSize
);
103 void UDPSocketChild::Connect(nsIUDPSocketInternal
* aSocket
,
104 const nsACString
& aHost
, uint16_t aPort
) {
106 ("%s: %s:%u", __FUNCTION__
, PromiseFlatCString(aHost
).get(), aPort
));
110 SendConnect(UDPAddressInfo(nsCString(aHost
), aPort
));
113 void UDPSocketChild::Close() { SendClose(); }
115 nsresult
UDPSocketChild::SendWithAddress(const NetAddr
* aAddr
,
116 const uint8_t* aData
,
117 uint32_t aByteLength
) {
118 NS_ENSURE_ARG(aAddr
);
119 NS_ENSURE_ARG(aData
);
121 UDPSOCKET_LOG(("%s: %u bytes", __FUNCTION__
, aByteLength
));
122 return SendDataInternal(UDPSocketAddr(*aAddr
), aData
, aByteLength
);
125 nsresult
UDPSocketChild::SendDataInternal(const UDPSocketAddr
& aAddr
,
126 const uint8_t* aData
,
127 const uint32_t aByteLength
) {
128 NS_ENSURE_ARG(aData
);
130 FallibleTArray
<uint8_t> fallibleArray
;
131 if (!fallibleArray
.InsertElementsAt(0, aData
, aByteLength
, fallible
)) {
132 return NS_ERROR_OUT_OF_MEMORY
;
135 SendOutgoingData(UDPData
{std::move(fallibleArray
)}, aAddr
);
140 nsresult
UDPSocketChild::SendBinaryStream(const nsACString
& aHost
,
142 nsIInputStream
* aStream
) {
143 NS_ENSURE_ARG(aStream
);
145 mozilla::ipc::IPCStream stream
;
146 if (NS_WARN_IF(!mozilla::ipc::SerializeIPCStream(do_AddRef(aStream
), stream
,
147 /* aAllowLazy */ false))) {
148 return NS_ERROR_UNEXPECTED
;
152 ("%s: %s:%u", __FUNCTION__
, PromiseFlatCString(aHost
).get(), aPort
));
153 SendOutgoingData(UDPData(stream
),
154 UDPSocketAddr(UDPAddressInfo(nsCString(aHost
), aPort
)));
159 void UDPSocketChild::JoinMulticast(const nsACString
& aMulticastAddress
,
160 const nsACString
& aInterface
) {
161 SendJoinMulticast(aMulticastAddress
, aInterface
);
164 void UDPSocketChild::LeaveMulticast(const nsACString
& aMulticastAddress
,
165 const nsACString
& aInterface
) {
166 SendLeaveMulticast(aMulticastAddress
, aInterface
);
169 nsresult
UDPSocketChild::SetFilterName(const nsACString
& aFilterName
) {
170 if (!mFilterName
.IsEmpty()) {
171 // filter name can only be set once.
172 return NS_ERROR_FAILURE
;
174 mFilterName
= aFilterName
;
178 // PUDPSocketChild Methods
179 mozilla::ipc::IPCResult
UDPSocketChild::RecvCallbackOpened(
180 const UDPAddressInfo
& aAddressInfo
) {
181 mLocalAddress
= aAddressInfo
.addr();
182 mLocalPort
= aAddressInfo
.port();
184 UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__
, mLocalAddress
.get(), mLocalPort
));
185 nsresult rv
= mSocket
->CallListenerOpened();
186 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
191 // PUDPSocketChild Methods
192 mozilla::ipc::IPCResult
UDPSocketChild::RecvCallbackConnected(
193 const UDPAddressInfo
& aAddressInfo
) {
194 mLocalAddress
= aAddressInfo
.addr();
195 mLocalPort
= aAddressInfo
.port();
197 UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__
, mLocalAddress
.get(), mLocalPort
));
198 nsresult rv
= mSocket
->CallListenerConnected();
199 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
204 mozilla::ipc::IPCResult
UDPSocketChild::RecvCallbackClosed() {
205 nsresult rv
= mSocket
->CallListenerClosed();
206 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
211 mozilla::ipc::IPCResult
UDPSocketChild::RecvCallbackReceivedData(
212 const UDPAddressInfo
& aAddressInfo
, nsTArray
<uint8_t>&& aData
) {
213 UDPSOCKET_LOG(("%s: %s:%u length %zu", __FUNCTION__
,
214 aAddressInfo
.addr().get(), aAddressInfo
.port(),
216 nsresult rv
= mSocket
->CallListenerReceivedData(aAddressInfo
.addr(),
217 aAddressInfo
.port(), aData
);
218 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
223 mozilla::ipc::IPCResult
UDPSocketChild::RecvCallbackError(
224 const nsCString
& aMessage
, const nsCString
& aFilename
,
225 const uint32_t& aLineNumber
) {
226 UDPSOCKET_LOG(("%s: %s:%s:%u", __FUNCTION__
, aMessage
.get(), aFilename
.get(),
228 nsresult rv
= mSocket
->CallListenerError(aMessage
, aFilename
, aLineNumber
);
229 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
234 } // namespace mozilla::dom