/src/mozilla-central/dom/network/UDPSocketChild.cpp
Line | Count | Source (jump to first uncovered line) |
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 "UDPSocketChild.h" |
8 | | #include "mozilla/Unused.h" |
9 | | #include "mozilla/ipc/IPCStreamUtils.h" |
10 | | #include "mozilla/net/NeckoChild.h" |
11 | | #include "mozilla/dom/ContentChild.h" |
12 | | #include "mozilla/dom/PermissionMessageUtils.h" |
13 | | #include "mozilla/ipc/BackgroundChild.h" |
14 | | #include "mozilla/ipc/PBackgroundChild.h" |
15 | | #include "mozilla/ipc/BackgroundUtils.h" |
16 | | #include "mozilla/ipc/PBackgroundSharedTypes.h" |
17 | | |
18 | | using mozilla::net::gNeckoChild; |
19 | | |
20 | | namespace mozilla { |
21 | | namespace dom { |
22 | | |
23 | | NS_IMPL_ISUPPORTS(UDPSocketChildBase, nsIUDPSocketChild) |
24 | | |
25 | | UDPSocketChildBase::UDPSocketChildBase() |
26 | | : mIPCOpen(false) |
27 | 0 | { |
28 | 0 | } |
29 | | |
30 | | UDPSocketChildBase::~UDPSocketChildBase() |
31 | 0 | { |
32 | 0 | } |
33 | | |
34 | | void |
35 | | UDPSocketChildBase::ReleaseIPDLReference() |
36 | 0 | { |
37 | 0 | MOZ_ASSERT(mIPCOpen); |
38 | 0 | mIPCOpen = false; |
39 | 0 | mSocket = nullptr; |
40 | 0 | this->Release(); |
41 | 0 | } |
42 | | |
43 | | void |
44 | | UDPSocketChildBase::AddIPDLReference() |
45 | 0 | { |
46 | 0 | MOZ_ASSERT(!mIPCOpen); |
47 | 0 | mIPCOpen = true; |
48 | 0 | this->AddRef(); |
49 | 0 | } |
50 | | |
51 | | NS_IMETHODIMP_(MozExternalRefCountType) UDPSocketChild::Release(void) |
52 | 0 | { |
53 | 0 | nsrefcnt refcnt = UDPSocketChildBase::Release(); |
54 | 0 | if (refcnt == 1 && mIPCOpen) { |
55 | 0 | PUDPSocketChild::SendRequestDelete(); |
56 | 0 | return 1; |
57 | 0 | } |
58 | 0 | return refcnt; |
59 | 0 | } |
60 | | |
61 | | UDPSocketChild::UDPSocketChild() |
62 | | :mBackgroundManager(nullptr) |
63 | | ,mLocalPort(0) |
64 | 0 | { |
65 | 0 | } |
66 | | |
67 | | UDPSocketChild::~UDPSocketChild() |
68 | 0 | { |
69 | 0 | } |
70 | | |
71 | | // nsIUDPSocketChild Methods |
72 | | |
73 | | NS_IMETHODIMP |
74 | | UDPSocketChild::SetBackgroundSpinsEvents() |
75 | 0 | { |
76 | 0 | using mozilla::ipc::BackgroundChild; |
77 | 0 |
|
78 | 0 | mBackgroundManager = |
79 | 0 | BackgroundChild::GetOrCreateForCurrentThread(); |
80 | 0 | if (NS_WARN_IF(!mBackgroundManager)) { |
81 | 0 | return NS_ERROR_FAILURE; |
82 | 0 | } |
83 | 0 | |
84 | 0 | return NS_OK; |
85 | 0 | } |
86 | | |
87 | | NS_IMETHODIMP |
88 | | UDPSocketChild::Bind(nsIUDPSocketInternal* aSocket, |
89 | | nsIPrincipal* aPrincipal, |
90 | | const nsACString& aHost, |
91 | | uint16_t aPort, |
92 | | bool aAddressReuse, |
93 | | bool aLoopback, |
94 | | uint32_t recvBufferSize, |
95 | | uint32_t sendBufferSize, |
96 | | nsIEventTarget* aMainThreadEventTarget) |
97 | 0 | { |
98 | 0 | UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort)); |
99 | 0 |
|
100 | 0 | NS_ENSURE_ARG(aSocket); |
101 | 0 |
|
102 | 0 | mSocket = aSocket; |
103 | 0 | AddIPDLReference(); |
104 | 0 |
|
105 | 0 | if (mBackgroundManager) { |
106 | 0 | // If we want to support a passed-in principal here we'd need to |
107 | 0 | // convert it to a PrincipalInfo |
108 | 0 | MOZ_ASSERT(!aPrincipal); |
109 | 0 | mBackgroundManager->SendPUDPSocketConstructor(this, void_t(), mFilterName); |
110 | 0 | } else { |
111 | 0 | if (aMainThreadEventTarget) { |
112 | 0 | gNeckoChild->SetEventTargetForActor(this, aMainThreadEventTarget); |
113 | 0 | } |
114 | 0 | gNeckoChild->SendPUDPSocketConstructor(this, IPC::Principal(aPrincipal), |
115 | 0 | mFilterName); |
116 | 0 | } |
117 | 0 |
|
118 | 0 | SendBind(UDPAddressInfo(nsCString(aHost), aPort), aAddressReuse, aLoopback, |
119 | 0 | recvBufferSize, sendBufferSize); |
120 | 0 | return NS_OK; |
121 | 0 | } |
122 | | |
123 | | NS_IMETHODIMP |
124 | | UDPSocketChild::Connect(nsIUDPSocketInternal* aSocket, const nsACString & aHost, uint16_t aPort) |
125 | 0 | { |
126 | 0 | UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort)); |
127 | 0 |
|
128 | 0 | mSocket = aSocket; |
129 | 0 |
|
130 | 0 | SendConnect(UDPAddressInfo(nsCString(aHost), aPort)); |
131 | 0 |
|
132 | 0 | return NS_OK; |
133 | 0 | } |
134 | | |
135 | | NS_IMETHODIMP |
136 | | UDPSocketChild::Close() |
137 | 0 | { |
138 | 0 | SendClose(); |
139 | 0 | return NS_OK; |
140 | 0 | } |
141 | | |
142 | | NS_IMETHODIMP |
143 | | UDPSocketChild::Send(const nsACString& aHost, |
144 | | uint16_t aPort, |
145 | | const uint8_t* aData, |
146 | | uint32_t aByteLength) |
147 | 0 | { |
148 | 0 | NS_ENSURE_ARG(aData); |
149 | 0 |
|
150 | 0 | UDPSOCKET_LOG(("%s: %s:%u - %u bytes", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort, aByteLength)); |
151 | 0 | return SendDataInternal(UDPSocketAddr(UDPAddressInfo(nsCString(aHost), aPort)), |
152 | 0 | aData, aByteLength); |
153 | 0 | } |
154 | | |
155 | | NS_IMETHODIMP |
156 | | UDPSocketChild::SendWithAddr(nsINetAddr* aAddr, |
157 | | const uint8_t* aData, |
158 | | uint32_t aByteLength) |
159 | 0 | { |
160 | 0 | NS_ENSURE_ARG(aAddr); |
161 | 0 | NS_ENSURE_ARG(aData); |
162 | 0 |
|
163 | 0 | NetAddr addr; |
164 | 0 | aAddr->GetNetAddr(&addr); |
165 | 0 |
|
166 | 0 | UDPSOCKET_LOG(("%s: %u bytes", __FUNCTION__, aByteLength)); |
167 | 0 | return SendDataInternal(UDPSocketAddr(addr), aData, aByteLength); |
168 | 0 | } |
169 | | |
170 | | NS_IMETHODIMP |
171 | | UDPSocketChild::SendWithAddress(const NetAddr* aAddr, |
172 | | const uint8_t* aData, |
173 | | uint32_t aByteLength) |
174 | 0 | { |
175 | 0 | NS_ENSURE_ARG(aAddr); |
176 | 0 | NS_ENSURE_ARG(aData); |
177 | 0 |
|
178 | 0 | UDPSOCKET_LOG(("%s: %u bytes", __FUNCTION__, aByteLength)); |
179 | 0 | return SendDataInternal(UDPSocketAddr(*aAddr), aData, aByteLength); |
180 | 0 | } |
181 | | |
182 | | nsresult |
183 | | UDPSocketChild::SendDataInternal(const UDPSocketAddr& aAddr, |
184 | | const uint8_t* aData, |
185 | | const uint32_t aByteLength) |
186 | 0 | { |
187 | 0 | NS_ENSURE_ARG(aData); |
188 | 0 |
|
189 | 0 | FallibleTArray<uint8_t> fallibleArray; |
190 | 0 | if (!fallibleArray.InsertElementsAt(0, aData, aByteLength, fallible)) { |
191 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
192 | 0 | } |
193 | 0 | |
194 | 0 | InfallibleTArray<uint8_t> array; |
195 | 0 | array.SwapElements(fallibleArray); |
196 | 0 |
|
197 | 0 | SendOutgoingData(array, aAddr); |
198 | 0 |
|
199 | 0 | return NS_OK; |
200 | 0 | } |
201 | | |
202 | | NS_IMETHODIMP |
203 | | UDPSocketChild::SendBinaryStream(const nsACString& aHost, |
204 | | uint16_t aPort, |
205 | | nsIInputStream* aStream) |
206 | 0 | { |
207 | 0 | NS_ENSURE_ARG(aStream); |
208 | 0 |
|
209 | 0 | mozilla::ipc::AutoIPCStream autoStream; |
210 | 0 | autoStream.Serialize(aStream, |
211 | 0 | static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager())); |
212 | 0 |
|
213 | 0 | UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort)); |
214 | 0 | SendOutgoingData(UDPData(autoStream.TakeOptionalValue()), |
215 | 0 | UDPSocketAddr(UDPAddressInfo(nsCString(aHost), aPort))); |
216 | 0 |
|
217 | 0 | return NS_OK; |
218 | 0 | } |
219 | | |
220 | | NS_IMETHODIMP |
221 | | UDPSocketChild::JoinMulticast(const nsACString& aMulticastAddress, |
222 | | const nsACString& aInterface) |
223 | 0 | { |
224 | 0 | SendJoinMulticast(nsCString(aMulticastAddress), nsCString(aInterface)); |
225 | 0 | return NS_OK; |
226 | 0 | } |
227 | | |
228 | | NS_IMETHODIMP |
229 | | UDPSocketChild::LeaveMulticast(const nsACString& aMulticastAddress, |
230 | | const nsACString& aInterface) |
231 | 0 | { |
232 | 0 | SendLeaveMulticast(nsCString(aMulticastAddress), nsCString(aInterface)); |
233 | 0 | return NS_OK; |
234 | 0 | } |
235 | | |
236 | | NS_IMETHODIMP |
237 | | UDPSocketChild::GetLocalPort(uint16_t* aLocalPort) |
238 | 0 | { |
239 | 0 | NS_ENSURE_ARG_POINTER(aLocalPort); |
240 | 0 |
|
241 | 0 | *aLocalPort = mLocalPort; |
242 | 0 | return NS_OK; |
243 | 0 | } |
244 | | |
245 | | NS_IMETHODIMP |
246 | | UDPSocketChild::GetLocalAddress(nsACString& aLocalAddress) |
247 | 0 | { |
248 | 0 | aLocalAddress = mLocalAddress; |
249 | 0 | return NS_OK; |
250 | 0 | } |
251 | | |
252 | | NS_IMETHODIMP |
253 | | UDPSocketChild::SetFilterName(const nsACString& aFilterName) |
254 | 0 | { |
255 | 0 | if (!mFilterName.IsEmpty()) { |
256 | 0 | // filter name can only be set once. |
257 | 0 | return NS_ERROR_FAILURE; |
258 | 0 | } |
259 | 0 | mFilterName = aFilterName; |
260 | 0 | return NS_OK; |
261 | 0 | } |
262 | | |
263 | | NS_IMETHODIMP |
264 | | UDPSocketChild::GetFilterName(nsACString& aFilterName) |
265 | 0 | { |
266 | 0 | aFilterName = mFilterName; |
267 | 0 | return NS_OK; |
268 | 0 | } |
269 | | |
270 | | // PUDPSocketChild Methods |
271 | | mozilla::ipc::IPCResult |
272 | | UDPSocketChild::RecvCallbackOpened(const UDPAddressInfo& aAddressInfo) |
273 | 0 | { |
274 | 0 | mLocalAddress = aAddressInfo.addr(); |
275 | 0 | mLocalPort = aAddressInfo.port(); |
276 | 0 |
|
277 | 0 | UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, mLocalAddress.get(), mLocalPort)); |
278 | 0 | nsresult rv = mSocket->CallListenerOpened(); |
279 | 0 | mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); |
280 | 0 |
|
281 | 0 | return IPC_OK(); |
282 | 0 | } |
283 | | |
284 | | // PUDPSocketChild Methods |
285 | | mozilla::ipc::IPCResult |
286 | | UDPSocketChild::RecvCallbackConnected(const UDPAddressInfo& aAddressInfo) |
287 | 0 | { |
288 | 0 | mLocalAddress = aAddressInfo.addr(); |
289 | 0 | mLocalPort = aAddressInfo.port(); |
290 | 0 |
|
291 | 0 | UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, mLocalAddress.get(), mLocalPort)); |
292 | 0 | nsresult rv = mSocket->CallListenerConnected(); |
293 | 0 | mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); |
294 | 0 |
|
295 | 0 | return IPC_OK(); |
296 | 0 | } |
297 | | |
298 | | mozilla::ipc::IPCResult |
299 | | UDPSocketChild::RecvCallbackClosed() |
300 | 0 | { |
301 | 0 | nsresult rv = mSocket->CallListenerClosed(); |
302 | 0 | mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); |
303 | 0 |
|
304 | 0 | return IPC_OK(); |
305 | 0 | } |
306 | | |
307 | | mozilla::ipc::IPCResult |
308 | | UDPSocketChild::RecvCallbackReceivedData(const UDPAddressInfo& aAddressInfo, |
309 | | InfallibleTArray<uint8_t>&& aData) |
310 | 0 | { |
311 | 0 | UDPSOCKET_LOG(("%s: %s:%u length %zu", __FUNCTION__, |
312 | 0 | aAddressInfo.addr().get(), aAddressInfo.port(), aData.Length())); |
313 | 0 | nsresult rv = mSocket->CallListenerReceivedData(aAddressInfo.addr(), aAddressInfo.port(), |
314 | 0 | aData.Elements(), aData.Length()); |
315 | 0 | mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); |
316 | 0 |
|
317 | 0 | return IPC_OK(); |
318 | 0 | } |
319 | | |
320 | | mozilla::ipc::IPCResult |
321 | | UDPSocketChild::RecvCallbackError(const nsCString& aMessage, |
322 | | const nsCString& aFilename, |
323 | | const uint32_t& aLineNumber) |
324 | 0 | { |
325 | 0 | UDPSOCKET_LOG(("%s: %s:%s:%u", __FUNCTION__, aMessage.get(), aFilename.get(), aLineNumber)); |
326 | 0 | nsresult rv = mSocket->CallListenerError(aMessage, aFilename, aLineNumber); |
327 | 0 | mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); |
328 | 0 |
|
329 | 0 | return IPC_OK(); |
330 | 0 | } |
331 | | |
332 | | } // namespace dom |
333 | | } // namespace mozilla |