Coverage Report

Created: 2018-09-25 14:53

/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