Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/mtransport/nr_socket_prsock.h
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=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
// Original author: ekr@rtfm.com
8
9
/* Some source code here from nICEr. Copyright is:
10
11
Copyright (c) 2007, Adobe Systems, Incorporated
12
All rights reserved.
13
14
Redistribution and use in source and binary forms, with or without
15
modification, are permitted provided that the following conditions are
16
met:
17
18
* Redistributions of source code must retain the above copyright
19
  notice, this list of conditions and the following disclaimer.
20
21
* Redistributions in binary form must reproduce the above copyright
22
  notice, this list of conditions and the following disclaimer in the
23
  documentation and/or other materials provided with the distribution.
24
25
* Neither the name of Adobe Systems, Network Resonance nor the names of its
26
  contributors may be used to endorse or promote products derived from
27
  this software without specific prior written permission.
28
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
*/
41
42
43
// Implementation of nICEr/nr_socket that is tied to the Gecko
44
// SocketTransportService.
45
46
#ifndef nr_socket_prsock__
47
#define nr_socket_prsock__
48
49
#include <queue>
50
51
#include "nspr.h"
52
#include "prio.h"
53
54
#include "nsAutoPtr.h"
55
#include "nsCOMPtr.h"
56
#include "nsASocketHandler.h"
57
#include "nsISocketTransportService.h"
58
#include "nsXPCOM.h"
59
#include "nsIEventTarget.h"
60
#include "nsIUDPSocketChild.h"
61
#include "nsProxyRelease.h"
62
#include "nsThreadUtils.h"
63
64
#include "nsITCPSocketCallback.h"
65
#include "mediapacket.h"
66
#include "m_cpp_utils.h"
67
#include "mozilla/ReentrantMonitor.h"
68
#include "mozilla/RefPtr.h"
69
#include "mozilla/TimeStamp.h"
70
#include "mozilla/ClearOnShutdown.h"
71
72
// Stub declaration for nICEr type
73
typedef struct nr_socket_vtbl_ nr_socket_vtbl;
74
typedef struct nr_socket_ nr_socket;
75
76
#if defined(MOZILLA_INTERNAL_API)
77
namespace mozilla {
78
namespace dom {
79
class TCPSocketChild;
80
}
81
}
82
#endif
83
84
namespace mozilla {
85
86
namespace net {
87
  union NetAddr;
88
}
89
90
class NrSocketBase {
91
public:
92
0
  NrSocketBase() : connect_invoked_(false), poll_flags_(0) {
93
0
    memset(cbs_, 0, sizeof(cbs_));
94
0
    memset(cb_args_, 0, sizeof(cb_args_));
95
0
    memset(&my_addr_, 0, sizeof(my_addr_));
96
0
  }
97
0
  virtual ~NrSocketBase() {}
98
99
  // Factory method; will create either an NrSocket, NrUdpSocketIpc, or
100
  // NrTcpSocketIpc as appropriate.
101
  static int CreateSocket(nr_transport_addr *addr, RefPtr<NrSocketBase> *sock);
102
103
  // the nr_socket APIs
104
  virtual int create(nr_transport_addr *addr) = 0;
105
  virtual int sendto(const void *msg, size_t len,
106
                     int flags, nr_transport_addr *to) = 0;
107
  virtual int recvfrom(void * buf, size_t maxlen,
108
                       size_t *len, int flags,
109
                       nr_transport_addr *from) = 0;
110
  virtual int getaddr(nr_transport_addr *addrp) = 0;
111
  virtual void close() = 0;
112
  virtual int connect(nr_transport_addr *addr) = 0;
113
  virtual int write(const void *msg, size_t len, size_t *written) = 0;
114
  virtual int read(void* buf, size_t maxlen, size_t *len) = 0;
115
  virtual int listen(int backlog) = 0;
116
  virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) = 0;
117
118
   // Implementations of the async_event APIs
119
  virtual int async_wait(int how, NR_async_cb cb, void *cb_arg,
120
                         char *function, int line);
121
  virtual int cancel(int how);
122
123
  // nsISupport reference counted interface
124
  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
125
126
0
  uint32_t poll_flags() {
127
0
    return poll_flags_;
128
0
  }
129
130
  virtual nr_socket_vtbl *vtbl();  // To access in test classes.
131
132
  static TimeStamp short_term_violation_time();
133
  static TimeStamp long_term_violation_time();
134
0
  const nr_transport_addr& my_addr() const {
135
0
    return my_addr_;
136
0
  }
137
138
  void fire_callback(int how);
139
140
protected:
141
142
  bool connect_invoked_;
143
  nr_transport_addr my_addr_;
144
145
private:
146
  NR_async_cb cbs_[NR_ASYNC_WAIT_WRITE + 1];
147
  void *cb_args_[NR_ASYNC_WAIT_WRITE + 1];
148
  uint32_t poll_flags_;
149
};
150
151
class NrSocket : public NrSocketBase,
152
                 public nsASocketHandler {
153
public:
154
0
  NrSocket() : fd_(nullptr) {}
155
156
  // Implement nsASocket
157
  virtual void OnSocketReady(PRFileDesc *fd, int16_t outflags) override;
158
  virtual void OnSocketDetached(PRFileDesc *fd) override;
159
  virtual void IsLocal(bool *aIsLocal) override;
160
0
  virtual uint64_t ByteCountSent() override { return 0; }
161
0
  virtual uint64_t ByteCountReceived() override { return 0; }
162
163
  // nsISupports methods
164
  NS_DECL_THREADSAFE_ISUPPORTS
165
166
  // Implementations of the async_event APIs
167
  virtual int async_wait(int how, NR_async_cb cb, void *cb_arg,
168
                         char *function, int line) override;
169
  virtual int cancel(int how) override;
170
171
172
  // Implementations of the nr_socket APIs
173
  virtual int create(nr_transport_addr *addr) override; // (really init, but it's called create)
174
  virtual int sendto(const void *msg, size_t len,
175
                     int flags, nr_transport_addr *to) override;
176
  virtual int recvfrom(void * buf, size_t maxlen,
177
                       size_t *len, int flags,
178
                       nr_transport_addr *from) override;
179
  virtual int getaddr(nr_transport_addr *addrp) override;
180
  virtual void close() override;
181
  virtual int connect(nr_transport_addr *addr) override;
182
  virtual int write(const void *msg, size_t len, size_t *written) override;
183
  virtual int read(void* buf, size_t maxlen, size_t *len) override;
184
  virtual int listen(int backlog) override;
185
  virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
186
187
protected:
188
0
  virtual ~NrSocket() {
189
0
    if (fd_)
190
0
      PR_Close(fd_);
191
0
  }
192
193
  DISALLOW_COPY_ASSIGN(NrSocket);
194
195
  PRFileDesc *fd_;
196
  nsCOMPtr<nsIEventTarget> ststhread_;
197
};
198
199
struct nr_udp_message {
200
  nr_udp_message(const PRNetAddr &from, nsAutoPtr<MediaPacket> &data)
201
0
      : from(from), data(data) {
202
0
  }
203
204
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_udp_message);
205
206
  PRNetAddr from;
207
  nsAutoPtr<MediaPacket> data;
208
209
private:
210
0
  ~nr_udp_message() {}
211
  DISALLOW_COPY_ASSIGN(nr_udp_message);
212
};
213
214
class NrSocketIpc : public NrSocketBase {
215
public:
216
217
  enum NrSocketIpcState {
218
    NR_INIT,
219
    NR_CONNECTING,
220
    NR_CONNECTED,
221
    NR_CLOSING,
222
    NR_CLOSED,
223
  };
224
225
  NrSocketIpc(nsIEventTarget* aThread);
226
227
protected:
228
  nsCOMPtr<nsIEventTarget> sts_thread_;
229
  // Note: for UDP PBackground, this is a thread held by SingletonThreadHolder.
230
  // For TCP PNecko, this is MainThread (and TCPSocket requires MainThread currently)
231
  const nsCOMPtr<nsIEventTarget> io_thread_;
232
0
  virtual ~NrSocketIpc() {};
233
234
private:
235
  DISALLOW_COPY_ASSIGN(NrSocketIpc);
236
};
237
238
class NrUdpSocketIpc : public NrSocketIpc {
239
public:
240
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrUdpSocketIpc, override)
241
242
  NS_IMETHODIMP CallListenerError(const nsACString &message,
243
                                  const nsACString &filename,
244
                                  uint32_t line_number);
245
  NS_IMETHODIMP CallListenerReceivedData(const nsACString &host,
246
                                         uint16_t port,
247
                                         const uint8_t *data,
248
                                         uint32_t data_length);
249
  NS_IMETHODIMP CallListenerOpened();
250
  NS_IMETHODIMP CallListenerConnected();
251
  NS_IMETHODIMP CallListenerClosed();
252
253
  NrUdpSocketIpc();
254
255
  // Implementations of the NrSocketBase APIs
256
  virtual int create(nr_transport_addr *addr) override;
257
  virtual int sendto(const void *msg, size_t len,
258
                     int flags, nr_transport_addr *to) override;
259
  virtual int recvfrom(void * buf, size_t maxlen,
260
                       size_t *len, int flags,
261
                       nr_transport_addr *from) override;
262
  virtual int getaddr(nr_transport_addr *addrp) override;
263
  virtual void close() override;
264
  virtual int connect(nr_transport_addr *addr) override;
265
  virtual int write(const void *msg, size_t len, size_t *written) override;
266
  virtual int read(void* buf, size_t maxlen, size_t *len) override;
267
  virtual int listen(int backlog) override;
268
  virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
269
270
private:
271
  virtual ~NrUdpSocketIpc();
272
273
  DISALLOW_COPY_ASSIGN(NrUdpSocketIpc);
274
275
  nsresult SetAddress();  // Set the local address from parent info.
276
277
  // Main or private thread executors of the NrSocketBase APIs
278
  void create_i(const nsACString &host, const uint16_t port);
279
  void connect_i(const nsACString &host, const uint16_t port);
280
  void sendto_i(const net::NetAddr &addr, nsAutoPtr<MediaPacket> buf);
281
  void close_i();
282
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
283
  static void destroy_i(nsIUDPSocketChild* aChild,
284
                        nsCOMPtr<nsIEventTarget>& aStsThread);
285
#endif
286
  // STS thread executor
287
  void recv_callback_s(RefPtr<nr_udp_message> msg);
288
289
  ReentrantMonitor monitor_; // protects err_and state_
290
  bool err_;
291
  NrSocketIpcState state_;
292
293
  std::queue<RefPtr<nr_udp_message>> received_msgs_;
294
295
  RefPtr<nsIUDPSocketChild> socket_child_; // only accessed from the io_thread
296
};
297
298
// The socket child holds onto one of these, which just passes callbacks
299
// through and makes sure the ref to the NrSocketIpc is released on STS.
300
class NrUdpSocketIpcProxy : public nsIUDPSocketInternal {
301
public:
302
  NS_DECL_THREADSAFE_ISUPPORTS
303
  NS_DECL_NSIUDPSOCKETINTERNAL
304
305
  nsresult Init(const RefPtr<NrUdpSocketIpc>& socket);
306
307
private:
308
  virtual ~NrUdpSocketIpcProxy();
309
310
  RefPtr<NrUdpSocketIpc> socket_;
311
  nsCOMPtr<nsIEventTarget> sts_thread_;
312
};
313
314
struct nr_tcp_message {
315
  explicit nr_tcp_message(nsAutoPtr<MediaPacket> &data)
316
    : read_bytes(0)
317
0
    , data(data) {
318
0
  }
319
320
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_tcp_message);
321
322
0
  const uint8_t *reading_pointer() const {
323
0
    return data->data() + read_bytes;
324
0
  }
325
326
0
  size_t unread_bytes() const {
327
0
    return data->len() - read_bytes;
328
0
  }
329
330
  size_t read_bytes;
331
332
private:
333
0
  ~nr_tcp_message() {}
334
  DISALLOW_COPY_ASSIGN(nr_tcp_message);
335
336
  nsAutoPtr<MediaPacket> data;
337
};
338
339
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
340
class NrTcpSocketIpc : public NrSocketIpc,
341
                       public nsITCPSocketCallback {
342
public:
343
  NS_DECL_THREADSAFE_ISUPPORTS
344
  NS_DECL_NSITCPSOCKETCALLBACK
345
346
  explicit NrTcpSocketIpc(nsIThread* aThread);
347
348
  // Implementations of the NrSocketBase APIs
349
  virtual int create(nr_transport_addr *addr) override;
350
  virtual int sendto(const void *msg, size_t len,
351
                     int flags, nr_transport_addr *to) override;
352
  virtual int recvfrom(void * buf, size_t maxlen,
353
                       size_t *len, int flags,
354
                       nr_transport_addr *from) override;
355
  virtual int getaddr(nr_transport_addr *addrp) override;
356
  virtual void close() override;
357
  virtual int connect(nr_transport_addr *addr) override;
358
  virtual int write(const void *msg, size_t len, size_t *written) override;
359
  virtual int read(void* buf, size_t maxlen, size_t *len) override;
360
  virtual int listen(int backlog) override;
361
  virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
362
363
private:
364
  class TcpSocketReadyRunner;
365
  DISALLOW_COPY_ASSIGN(NrTcpSocketIpc);
366
  virtual ~NrTcpSocketIpc();
367
368
  // Main thread executors of the NrSocketBase APIs
369
  void connect_i(const nsACString &remote_addr,
370
                 uint16_t remote_port,
371
                 const nsACString &local_addr,
372
                 uint16_t local_port,
373
                 const nsACString &tls_host);
374
  void write_i(nsAutoPtr<InfallibleTArray<uint8_t>> buf,
375
               uint32_t tracking_number);
376
  void close_i();
377
378
  static void release_child_i(dom::TCPSocketChild* aChild);
379
380
  // STS thread executor
381
  void message_sent_s(uint32_t bufferedAmount, uint32_t tracking_number);
382
  void recv_message_s(nr_tcp_message *msg);
383
  void update_state_s(NrSocketIpcState next_state);
384
  void maybe_post_socket_ready();
385
386
  // Accessed from UpdateReadyState (not sts_thread) to avoid sending
387
  // runnables when not needed
388
  NrSocketIpcState mirror_state_;
389
390
  // variables that can only be accessed on STS.
391
  NrSocketIpcState state_;
392
  std::queue<RefPtr<nr_tcp_message>> msg_queue_;
393
  uint32_t buffered_bytes_;
394
  uint32_t tracking_number_;
395
  std::deque<size_t> writes_in_flight_;
396
397
  // main thread.
398
  RefPtr<dom::TCPSocketChild> socket_child_;
399
};
400
#endif
401
402
int nr_netaddr_to_transport_addr(const net::NetAddr *netaddr,
403
                                 nr_transport_addr *addr,
404
                                 int protocol);
405
int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
406
                                nr_transport_addr *addr,
407
                                int protocol, int keep);
408
int nr_transport_addr_get_addrstring_and_port(nr_transport_addr *addr,
409
                                              nsACString *host, int32_t *port);
410
}  // close namespace
411
#endif