/src/mozilla-central/dom/network/UDPSocketParent.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 "nsIServiceManager.h" |
8 | | #include "UDPSocketParent.h" |
9 | | #include "nsComponentManagerUtils.h" |
10 | | #include "nsIUDPSocket.h" |
11 | | #include "nsINetAddr.h" |
12 | | #include "mozilla/Unused.h" |
13 | | #include "mozilla/ipc/InputStreamUtils.h" |
14 | | #include "mozilla/net/DNS.h" |
15 | | #include "mozilla/net/NeckoCommon.h" |
16 | | #include "mozilla/net/PNeckoParent.h" |
17 | | #include "nsIPermissionManager.h" |
18 | | #include "nsIScriptSecurityManager.h" |
19 | | #include "mozilla/ipc/PBackgroundParent.h" |
20 | | #include "mtransport/runnable_utils.h" |
21 | | |
22 | | namespace mozilla { |
23 | | |
24 | | using namespace net; |
25 | | |
26 | | namespace dom { |
27 | | |
28 | | NS_IMPL_ISUPPORTS(UDPSocketParent, nsIUDPSocketListener) |
29 | | |
30 | | UDPSocketParent::UDPSocketParent(PBackgroundParent* aManager) |
31 | | : mBackgroundManager(aManager) |
32 | | , mIPCOpen(true) |
33 | 0 | { |
34 | 0 | } |
35 | | |
36 | | UDPSocketParent::UDPSocketParent(PNeckoParent* aManager) |
37 | | : mBackgroundManager(nullptr) |
38 | | , mIPCOpen(true) |
39 | 0 | { |
40 | 0 | } |
41 | | |
42 | | UDPSocketParent::~UDPSocketParent() |
43 | 0 | { |
44 | 0 | } |
45 | | |
46 | | bool |
47 | | UDPSocketParent::Init(const IPC::Principal& aPrincipal, |
48 | | const nsACString& aFilter) |
49 | 0 | { |
50 | 0 | MOZ_ASSERT_IF(mBackgroundManager, !aPrincipal); |
51 | 0 | // will be used once we move all UDPSocket to PBackground, or |
52 | 0 | // if we add in Principal checking for mtransport |
53 | 0 | Unused << mBackgroundManager; |
54 | 0 |
|
55 | 0 | mPrincipal = aPrincipal; |
56 | 0 | if (net::UsingNeckoIPCSecurity() && |
57 | 0 | mPrincipal && |
58 | 0 | !ContentParent::IgnoreIPCPrincipal()) { |
59 | 0 | nsCOMPtr<nsIPermissionManager> permMgr = |
60 | 0 | services::GetPermissionManager(); |
61 | 0 | if (!permMgr) { |
62 | 0 | NS_WARNING("No PermissionManager available!"); |
63 | 0 | return false; |
64 | 0 | } |
65 | 0 |
|
66 | 0 | uint32_t permission = nsIPermissionManager::DENY_ACTION; |
67 | 0 | permMgr->TestExactPermissionFromPrincipal(mPrincipal, "udp-socket", |
68 | 0 | &permission); |
69 | 0 | if (permission != nsIPermissionManager::ALLOW_ACTION) { |
70 | 0 | return false; |
71 | 0 | } |
72 | 0 | } |
73 | 0 | |
74 | 0 | if (!aFilter.IsEmpty()) { |
75 | 0 | nsAutoCString contractId(NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX); |
76 | 0 | contractId.Append(aFilter); |
77 | 0 | nsCOMPtr<nsISocketFilterHandler> filterHandler = |
78 | 0 | do_GetService(contractId.get()); |
79 | 0 | if (filterHandler) { |
80 | 0 | nsresult rv = filterHandler->NewFilter(getter_AddRefs(mFilter)); |
81 | 0 | if (NS_FAILED(rv)) { |
82 | 0 | printf_stderr("Cannot create filter that content specified. " |
83 | 0 | "filter name: %s, error code: %u.", aFilter.BeginReading(), static_cast<uint32_t>(rv)); |
84 | 0 | return false; |
85 | 0 | } |
86 | 0 | } else { |
87 | 0 | printf_stderr("Content doesn't have a valid filter. " |
88 | 0 | "filter name: %s.", aFilter.BeginReading()); |
89 | 0 | return false; |
90 | 0 | } |
91 | 0 | } |
92 | 0 | // We don't have browser actors in xpcshell, and hence can't run automated |
93 | 0 | // tests without this loophole. |
94 | 0 | if (net::UsingNeckoIPCSecurity() && !mFilter && |
95 | 0 | (!mPrincipal || ContentParent::IgnoreIPCPrincipal())) { |
96 | 0 | return false; |
97 | 0 | } |
98 | 0 | return true; |
99 | 0 | } |
100 | | |
101 | | // PUDPSocketParent methods |
102 | | |
103 | | mozilla::ipc::IPCResult |
104 | | UDPSocketParent::RecvBind(const UDPAddressInfo& aAddressInfo, |
105 | | const bool& aAddressReuse, const bool& aLoopback, |
106 | | const uint32_t& recvBufferSize, |
107 | | const uint32_t& sendBufferSize) |
108 | 0 | { |
109 | 0 | UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, aAddressInfo.addr().get(), aAddressInfo.port())); |
110 | 0 |
|
111 | 0 | if (NS_FAILED(BindInternal(aAddressInfo.addr(), aAddressInfo.port(), |
112 | 0 | aAddressReuse, aLoopback, recvBufferSize, |
113 | 0 | sendBufferSize))) { |
114 | 0 | FireInternalError(__LINE__); |
115 | 0 | return IPC_OK(); |
116 | 0 | } |
117 | 0 |
|
118 | 0 | nsCOMPtr<nsINetAddr> localAddr; |
119 | 0 | mSocket->GetLocalAddr(getter_AddRefs(localAddr)); |
120 | 0 |
|
121 | 0 | nsCString addr; |
122 | 0 | if (NS_FAILED(localAddr->GetAddress(addr))) { |
123 | 0 | FireInternalError(__LINE__); |
124 | 0 | return IPC_OK(); |
125 | 0 | } |
126 | 0 |
|
127 | 0 | uint16_t port; |
128 | 0 | if (NS_FAILED(localAddr->GetPort(&port))) { |
129 | 0 | FireInternalError(__LINE__); |
130 | 0 | return IPC_OK(); |
131 | 0 | } |
132 | 0 |
|
133 | 0 | UDPSOCKET_LOG(("%s: SendCallbackOpened: %s:%u", __FUNCTION__, addr.get(), port)); |
134 | 0 | mozilla::Unused << SendCallbackOpened(UDPAddressInfo(addr, port)); |
135 | 0 |
|
136 | 0 | return IPC_OK(); |
137 | 0 | } |
138 | | |
139 | | nsresult |
140 | | UDPSocketParent::BindInternal(const nsCString& aHost, const uint16_t& aPort, |
141 | | const bool& aAddressReuse, const bool& aLoopback, |
142 | | const uint32_t& recvBufferSize, |
143 | | const uint32_t& sendBufferSize) |
144 | 0 | { |
145 | 0 | nsresult rv; |
146 | 0 |
|
147 | 0 | UDPSOCKET_LOG(("%s: [this=%p] %s:%u addressReuse: %d loopback: %d recvBufferSize: %" |
148 | 0 | PRIu32 ", sendBufferSize: %" PRIu32, |
149 | 0 | __FUNCTION__, this, nsCString(aHost).get(), aPort, |
150 | 0 | aAddressReuse, aLoopback, recvBufferSize, sendBufferSize)); |
151 | 0 |
|
152 | 0 | nsCOMPtr<nsIUDPSocket> sock = |
153 | 0 | do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv); |
154 | 0 |
|
155 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
156 | 0 | return rv; |
157 | 0 | } |
158 | 0 | |
159 | 0 | if (aHost.IsEmpty()) { |
160 | 0 | rv = sock->Init(aPort, false, mPrincipal, aAddressReuse, |
161 | 0 | /* optional_argc = */ 1); |
162 | 0 | } else { |
163 | 0 | PRNetAddr prAddr; |
164 | 0 | PR_InitializeNetAddr(PR_IpAddrAny, aPort, &prAddr); |
165 | 0 | PRStatus status = PR_StringToNetAddr(aHost.BeginReading(), &prAddr); |
166 | 0 | if (status != PR_SUCCESS) { |
167 | 0 | return NS_ERROR_FAILURE; |
168 | 0 | } |
169 | 0 | |
170 | 0 | mozilla::net::NetAddr addr; |
171 | 0 | PRNetAddrToNetAddr(&prAddr, &addr); |
172 | 0 | rv = sock->InitWithAddress(&addr, mPrincipal, aAddressReuse, |
173 | 0 | /* optional_argc = */ 1); |
174 | 0 | } |
175 | 0 |
|
176 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
177 | 0 | return rv; |
178 | 0 | } |
179 | 0 | |
180 | 0 | nsCOMPtr<nsINetAddr> laddr; |
181 | 0 | rv = sock->GetLocalAddr(getter_AddRefs(laddr)); |
182 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
183 | 0 | return rv; |
184 | 0 | } |
185 | 0 | uint16_t family; |
186 | 0 | rv = laddr->GetFamily(&family); |
187 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
188 | 0 | return rv; |
189 | 0 | } |
190 | 0 | if (family == nsINetAddr::FAMILY_INET) { |
191 | 0 | rv = sock->SetMulticastLoopback(aLoopback); |
192 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
193 | 0 | return rv; |
194 | 0 | } |
195 | 0 | } |
196 | 0 | // TODO: once bug 1252759 is fixed query buffer first and only increase |
197 | 0 | if (recvBufferSize != 0) { |
198 | 0 | rv = sock->SetRecvBufferSize(recvBufferSize); |
199 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
200 | 0 | UDPSOCKET_LOG(("%s: [this=%p] %s:%u failed to set recv buffer size to: %" PRIu32, __FUNCTION__, this, nsCString(aHost).get(), aPort, recvBufferSize)); |
201 | 0 | } |
202 | 0 | } |
203 | 0 | if (sendBufferSize != 0) { |
204 | 0 | rv = sock->SetSendBufferSize(sendBufferSize); |
205 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
206 | 0 | UDPSOCKET_LOG(("%s: [this=%p] %s:%u failed to set send buffer size to: %" PRIu32, __FUNCTION__, this, nsCString(aHost).get(), aPort, sendBufferSize)); |
207 | 0 | } |
208 | 0 | } |
209 | 0 |
|
210 | 0 | // register listener |
211 | 0 | rv = sock->AsyncListen(this); |
212 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
213 | 0 | return rv; |
214 | 0 | } |
215 | 0 | |
216 | 0 | mSocket = sock; |
217 | 0 |
|
218 | 0 | return NS_OK; |
219 | 0 | } |
220 | | |
221 | | |
222 | | static nsCOMPtr<nsIEventTarget> GetSTSThread() |
223 | 0 | { |
224 | 0 | nsresult rv; |
225 | 0 |
|
226 | 0 | nsCOMPtr<nsIEventTarget> sts_thread; |
227 | 0 |
|
228 | 0 | sts_thread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); |
229 | 0 | MOZ_ASSERT(NS_SUCCEEDED(rv)); |
230 | 0 |
|
231 | 0 | return sts_thread; |
232 | 0 | } |
233 | | |
234 | | static void CheckSTSThread() |
235 | 0 | { |
236 | 0 | DebugOnly<nsCOMPtr<nsIEventTarget>> sts_thread = GetSTSThread(); |
237 | 0 |
|
238 | 0 | ASSERT_ON_THREAD(sts_thread.value); |
239 | 0 | } |
240 | | |
241 | | |
242 | | // Proxy the Connect() request to the STS thread, since it may block and |
243 | | // should be done there. |
244 | | mozilla::ipc::IPCResult |
245 | | UDPSocketParent::RecvConnect(const UDPAddressInfo& aAddressInfo) |
246 | 0 | { |
247 | 0 | nsCOMPtr<nsIEventTarget> target = GetCurrentThreadEventTarget(); |
248 | 0 | Unused << |
249 | 0 | NS_WARN_IF(NS_FAILED(GetSTSThread()->Dispatch(WrapRunnable( |
250 | 0 | RefPtr<UDPSocketParent>(this), |
251 | 0 | &UDPSocketParent::DoConnect, |
252 | 0 | mSocket, |
253 | 0 | target, |
254 | 0 | aAddressInfo), |
255 | 0 | NS_DISPATCH_NORMAL))); |
256 | 0 | return IPC_OK(); |
257 | 0 | } |
258 | | |
259 | | void |
260 | | UDPSocketParent::DoSendConnectResponse(const UDPAddressInfo& aAddressInfo) |
261 | 0 | { |
262 | 0 | // can't use directly with WrapRunnable due to warnings |
263 | 0 | mozilla::Unused << SendCallbackConnected(aAddressInfo); |
264 | 0 | } |
265 | | |
266 | | void |
267 | | UDPSocketParent::SendConnectResponse(nsIEventTarget *aThread, |
268 | | const UDPAddressInfo& aAddressInfo) |
269 | 0 | { |
270 | 0 | Unused << |
271 | 0 | NS_WARN_IF(NS_FAILED(aThread->Dispatch(WrapRunnable( |
272 | 0 | RefPtr<UDPSocketParent>(this), |
273 | 0 | &UDPSocketParent::DoSendConnectResponse, |
274 | 0 | aAddressInfo), |
275 | 0 | NS_DISPATCH_NORMAL))); |
276 | 0 | } |
277 | | |
278 | | // Runs on STS thread |
279 | | void |
280 | | UDPSocketParent::DoConnect(nsCOMPtr<nsIUDPSocket>& aSocket, |
281 | | nsCOMPtr<nsIEventTarget>& aReturnThread, |
282 | | const UDPAddressInfo& aAddressInfo) |
283 | 0 | { |
284 | 0 | UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, aAddressInfo.addr().get(), aAddressInfo.port())); |
285 | 0 | if (NS_FAILED(ConnectInternal(aAddressInfo.addr(), aAddressInfo.port()))) { |
286 | 0 | SendInternalError(aReturnThread, __LINE__); |
287 | 0 | return; |
288 | 0 | } |
289 | 0 | CheckSTSThread(); |
290 | 0 |
|
291 | 0 | nsCOMPtr<nsINetAddr> localAddr; |
292 | 0 | aSocket->GetLocalAddr(getter_AddRefs(localAddr)); |
293 | 0 |
|
294 | 0 | nsCString addr; |
295 | 0 | if (NS_FAILED(localAddr->GetAddress(addr))) { |
296 | 0 | SendInternalError(aReturnThread, __LINE__); |
297 | 0 | return; |
298 | 0 | } |
299 | 0 | |
300 | 0 | uint16_t port; |
301 | 0 | if (NS_FAILED(localAddr->GetPort(&port))) { |
302 | 0 | SendInternalError(aReturnThread, __LINE__); |
303 | 0 | return; |
304 | 0 | } |
305 | 0 | |
306 | 0 | UDPSOCKET_LOG(("%s: SendConnectResponse: %s:%u", __FUNCTION__, addr.get(), port)); |
307 | 0 | SendConnectResponse(aReturnThread, UDPAddressInfo(addr, port)); |
308 | 0 | } |
309 | | |
310 | | nsresult |
311 | | UDPSocketParent::ConnectInternal(const nsCString& aHost, const uint16_t& aPort) |
312 | 0 | { |
313 | 0 | nsresult rv; |
314 | 0 |
|
315 | 0 | UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, nsCString(aHost).get(), aPort)); |
316 | 0 |
|
317 | 0 | if (!mSocket) { |
318 | 0 | return NS_ERROR_NOT_AVAILABLE; |
319 | 0 | } |
320 | 0 | |
321 | 0 | PRNetAddr prAddr; |
322 | 0 | memset(&prAddr, 0, sizeof(prAddr)); |
323 | 0 | PR_InitializeNetAddr(PR_IpAddrAny, aPort, &prAddr); |
324 | 0 | PRStatus status = PR_StringToNetAddr(aHost.BeginReading(), &prAddr); |
325 | 0 | if (status != PR_SUCCESS) { |
326 | 0 | return NS_ERROR_FAILURE; |
327 | 0 | } |
328 | 0 | |
329 | 0 | mozilla::net::NetAddr addr; |
330 | 0 | PRNetAddrToNetAddr(&prAddr, &addr); |
331 | 0 |
|
332 | 0 | rv = mSocket->Connect(&addr); |
333 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
334 | 0 | return rv; |
335 | 0 | } |
336 | 0 | |
337 | 0 | return NS_OK; |
338 | 0 | } |
339 | | |
340 | | mozilla::ipc::IPCResult |
341 | | UDPSocketParent::RecvOutgoingData(const UDPData& aData, |
342 | | const UDPSocketAddr& aAddr) |
343 | 0 | { |
344 | 0 | if (!mSocket) { |
345 | 0 | NS_WARNING("sending socket is closed"); |
346 | 0 | FireInternalError(__LINE__); |
347 | 0 | return IPC_OK(); |
348 | 0 | } |
349 | 0 |
|
350 | 0 | nsresult rv; |
351 | 0 | if (mFilter) { |
352 | 0 | if (aAddr.type() != UDPSocketAddr::TNetAddr) { |
353 | 0 | return IPC_OK(); |
354 | 0 | } |
355 | 0 |
|
356 | 0 | // TODO, Packet filter doesn't support input stream yet. |
357 | 0 | if (aData.type() != UDPData::TArrayOfuint8_t) { |
358 | 0 | return IPC_OK(); |
359 | 0 | } |
360 | 0 |
|
361 | 0 | bool allowed; |
362 | 0 | const InfallibleTArray<uint8_t>& data(aData.get_ArrayOfuint8_t()); |
363 | 0 | rv = mFilter->FilterPacket(&aAddr.get_NetAddr(), data.Elements(), |
364 | 0 | data.Length(), nsISocketFilter::SF_OUTGOING, |
365 | 0 | &allowed); |
366 | 0 |
|
367 | 0 | // Sending unallowed data, kill content. |
368 | 0 | if (NS_WARN_IF(NS_FAILED(rv)) || !allowed) { |
369 | 0 | return IPC_FAIL(this, "Content tried to send non STUN packet"); |
370 | 0 | } |
371 | 0 | } |
372 | 0 |
|
373 | 0 | switch(aData.type()) { |
374 | 0 | case UDPData::TArrayOfuint8_t: |
375 | 0 | Send(aData.get_ArrayOfuint8_t(), aAddr); |
376 | 0 | break; |
377 | 0 | case UDPData::TIPCStream: |
378 | 0 | Send(aData.get_IPCStream(), aAddr); |
379 | 0 | break; |
380 | 0 | default: |
381 | 0 | MOZ_ASSERT(false, "Invalid data type!"); |
382 | 0 | return IPC_OK(); |
383 | 0 | } |
384 | 0 | |
385 | 0 | return IPC_OK(); |
386 | 0 | } |
387 | | |
388 | | void |
389 | | UDPSocketParent::Send(const InfallibleTArray<uint8_t>& aData, |
390 | | const UDPSocketAddr& aAddr) |
391 | 0 | { |
392 | 0 | nsresult rv; |
393 | 0 | uint32_t count; |
394 | 0 | switch(aAddr.type()) { |
395 | 0 | case UDPSocketAddr::TUDPAddressInfo: { |
396 | 0 | const UDPAddressInfo& addrInfo(aAddr.get_UDPAddressInfo()); |
397 | 0 | rv = mSocket->Send(addrInfo.addr(), addrInfo.port(), |
398 | 0 | aData.Elements(), aData.Length(), &count); |
399 | 0 | break; |
400 | 0 | } |
401 | 0 | case UDPSocketAddr::TNetAddr: { |
402 | 0 | const NetAddr& addr(aAddr.get_NetAddr()); |
403 | 0 | rv = mSocket->SendWithAddress(&addr, aData.Elements(), |
404 | 0 | aData.Length(), &count); |
405 | 0 | break; |
406 | 0 | } |
407 | 0 | default: |
408 | 0 | MOZ_ASSERT(false, "Invalid address type!"); |
409 | 0 | return; |
410 | 0 | } |
411 | 0 |
|
412 | 0 | if (NS_WARN_IF(NS_FAILED(rv)) || count == 0) { |
413 | 0 | FireInternalError(__LINE__); |
414 | 0 | } |
415 | 0 | } |
416 | | |
417 | | void |
418 | | UDPSocketParent::Send(const IPCStream& aStream, |
419 | | const UDPSocketAddr& aAddr) |
420 | 0 | { |
421 | 0 | nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aStream); |
422 | 0 |
|
423 | 0 | if (NS_WARN_IF(!stream)) { |
424 | 0 | return; |
425 | 0 | } |
426 | 0 | |
427 | 0 | nsresult rv; |
428 | 0 | switch(aAddr.type()) { |
429 | 0 | case UDPSocketAddr::TUDPAddressInfo: { |
430 | 0 | const UDPAddressInfo& addrInfo(aAddr.get_UDPAddressInfo()); |
431 | 0 | rv = mSocket->SendBinaryStream(addrInfo.addr(), addrInfo.port(), stream); |
432 | 0 | break; |
433 | 0 | } |
434 | 0 | case UDPSocketAddr::TNetAddr: { |
435 | 0 | const NetAddr& addr(aAddr.get_NetAddr()); |
436 | 0 | rv = mSocket->SendBinaryStreamWithAddress(&addr, stream); |
437 | 0 | break; |
438 | 0 | } |
439 | 0 | default: |
440 | 0 | MOZ_ASSERT(false, "Invalid address type!"); |
441 | 0 | return; |
442 | 0 | } |
443 | 0 |
|
444 | 0 | if (NS_FAILED(rv)) { |
445 | 0 | FireInternalError(__LINE__); |
446 | 0 | } |
447 | 0 | } |
448 | | |
449 | | mozilla::ipc::IPCResult |
450 | | UDPSocketParent::RecvJoinMulticast(const nsCString& aMulticastAddress, |
451 | | const nsCString& aInterface) |
452 | 0 | { |
453 | 0 | if (!mSocket) { |
454 | 0 | NS_WARNING("multicast socket is closed"); |
455 | 0 | FireInternalError(__LINE__); |
456 | 0 | return IPC_OK(); |
457 | 0 | } |
458 | 0 |
|
459 | 0 | nsresult rv = mSocket->JoinMulticast(aMulticastAddress, aInterface); |
460 | 0 |
|
461 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
462 | 0 | FireInternalError(__LINE__); |
463 | 0 | } |
464 | 0 |
|
465 | 0 | return IPC_OK(); |
466 | 0 | } |
467 | | |
468 | | mozilla::ipc::IPCResult |
469 | | UDPSocketParent::RecvLeaveMulticast(const nsCString& aMulticastAddress, |
470 | | const nsCString& aInterface) |
471 | 0 | { |
472 | 0 | if (!mSocket) { |
473 | 0 | NS_WARNING("multicast socket is closed"); |
474 | 0 | FireInternalError(__LINE__); |
475 | 0 | return IPC_OK(); |
476 | 0 | } |
477 | 0 |
|
478 | 0 | nsresult rv = mSocket->LeaveMulticast(aMulticastAddress, aInterface); |
479 | 0 |
|
480 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
481 | 0 | FireInternalError(__LINE__); |
482 | 0 | } |
483 | 0 |
|
484 | 0 | return IPC_OK(); |
485 | 0 | } |
486 | | |
487 | | mozilla::ipc::IPCResult |
488 | | UDPSocketParent::RecvClose() |
489 | 0 | { |
490 | 0 | if (!mSocket) { |
491 | 0 | return IPC_OK(); |
492 | 0 | } |
493 | 0 |
|
494 | 0 | nsresult rv = mSocket->Close(); |
495 | 0 | mSocket = nullptr; |
496 | 0 |
|
497 | 0 | mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); |
498 | 0 |
|
499 | 0 | return IPC_OK(); |
500 | 0 | } |
501 | | |
502 | | mozilla::ipc::IPCResult |
503 | | UDPSocketParent::RecvRequestDelete() |
504 | 0 | { |
505 | 0 | mozilla::Unused << Send__delete__(this); |
506 | 0 | return IPC_OK(); |
507 | 0 | } |
508 | | |
509 | | void |
510 | | UDPSocketParent::ActorDestroy(ActorDestroyReason why) |
511 | 0 | { |
512 | 0 | MOZ_ASSERT(mIPCOpen); |
513 | 0 | mIPCOpen = false; |
514 | 0 | if (mSocket) { |
515 | 0 | mSocket->Close(); |
516 | 0 | } |
517 | 0 | mSocket = nullptr; |
518 | 0 | } |
519 | | |
520 | | // nsIUDPSocketListener |
521 | | |
522 | | NS_IMETHODIMP |
523 | | UDPSocketParent::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage) |
524 | 0 | { |
525 | 0 | // receiving packet from remote host, forward the message content to child process |
526 | 0 | if (!mIPCOpen) { |
527 | 0 | return NS_OK; |
528 | 0 | } |
529 | 0 | |
530 | 0 | uint16_t port; |
531 | 0 | nsCString ip; |
532 | 0 | nsCOMPtr<nsINetAddr> fromAddr; |
533 | 0 | aMessage->GetFromAddr(getter_AddRefs(fromAddr)); |
534 | 0 | fromAddr->GetPort(&port); |
535 | 0 | fromAddr->GetAddress(ip); |
536 | 0 |
|
537 | 0 | nsCString data; |
538 | 0 | aMessage->GetData(data); |
539 | 0 |
|
540 | 0 | const char* buffer = data.get(); |
541 | 0 | uint32_t len = data.Length(); |
542 | 0 | UDPSOCKET_LOG(("%s: %s:%u, length %u", __FUNCTION__, ip.get(), port, len)); |
543 | 0 |
|
544 | 0 | if (mFilter) { |
545 | 0 | bool allowed; |
546 | 0 | mozilla::net::NetAddr addr; |
547 | 0 | fromAddr->GetNetAddr(&addr); |
548 | 0 | nsresult rv = mFilter->FilterPacket(&addr, |
549 | 0 | (const uint8_t*)buffer, len, |
550 | 0 | nsISocketFilter::SF_INCOMING, |
551 | 0 | &allowed); |
552 | 0 | // Receiving unallowed data, drop. |
553 | 0 | if (NS_WARN_IF(NS_FAILED(rv)) || !allowed) { |
554 | 0 | if (!allowed) { |
555 | 0 | UDPSOCKET_LOG(("%s: not allowed", __FUNCTION__)); |
556 | 0 | } |
557 | 0 | return NS_OK; |
558 | 0 | } |
559 | 0 | } |
560 | 0 |
|
561 | 0 | FallibleTArray<uint8_t> fallibleArray; |
562 | 0 | if (!fallibleArray.InsertElementsAt(0, buffer, len, fallible)) { |
563 | 0 | FireInternalError(__LINE__); |
564 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
565 | 0 | } |
566 | 0 | InfallibleTArray<uint8_t> infallibleArray; |
567 | 0 | infallibleArray.SwapElements(fallibleArray); |
568 | 0 |
|
569 | 0 | // compose callback |
570 | 0 | mozilla::Unused << SendCallbackReceivedData(UDPAddressInfo(ip, port), infallibleArray); |
571 | 0 |
|
572 | 0 | return NS_OK; |
573 | 0 | } |
574 | | |
575 | | NS_IMETHODIMP |
576 | | UDPSocketParent::OnStopListening(nsIUDPSocket* aSocket, nsresult aStatus) |
577 | 0 | { |
578 | 0 | // underlying socket is dead, send state update to child process |
579 | 0 | if (mIPCOpen) { |
580 | 0 | mozilla::Unused << SendCallbackClosed(); |
581 | 0 | } |
582 | 0 | return NS_OK; |
583 | 0 | } |
584 | | |
585 | | void |
586 | | UDPSocketParent::FireInternalError(uint32_t aLineNo) |
587 | 0 | { |
588 | 0 | if (!mIPCOpen) { |
589 | 0 | return; |
590 | 0 | } |
591 | 0 | |
592 | 0 | mozilla::Unused << SendCallbackError(NS_LITERAL_CSTRING("Internal error"), |
593 | 0 | NS_LITERAL_CSTRING(__FILE__), aLineNo); |
594 | 0 | } |
595 | | |
596 | | void |
597 | | UDPSocketParent::SendInternalError(nsIEventTarget *aThread, |
598 | | uint32_t aLineNo) |
599 | 0 | { |
600 | 0 | UDPSOCKET_LOG(("SendInternalError: %u", aLineNo)); |
601 | 0 | Unused << |
602 | 0 | NS_WARN_IF(NS_FAILED(aThread->Dispatch(WrapRunnable( |
603 | 0 | RefPtr<UDPSocketParent>(this), |
604 | 0 | &UDPSocketParent::FireInternalError, |
605 | 0 | aLineNo), |
606 | 0 | NS_DISPATCH_NORMAL))); |
607 | 0 | } |
608 | | |
609 | | } // namespace dom |
610 | | } // namespace mozilla |