Line data Source code
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 "databuffer.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 : }
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 : }
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 0 : nr_udp_message(const PRNetAddr &from, nsAutoPtr<DataBuffer> &data)
201 0 : : from(from), data(data) {
202 0 : }
203 :
204 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_udp_message);
205 :
206 : PRNetAddr from;
207 : nsAutoPtr<DataBuffer> 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 0 : 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<DataBuffer> buf);
281 : void close_i();
282 : #if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
283 : static void release_child_i(nsIUDPSocketChild* aChild);
284 : #endif
285 : // STS thread executor
286 : void recv_callback_s(RefPtr<nr_udp_message> msg);
287 :
288 : ReentrantMonitor monitor_; // protects err_and state_
289 : bool err_;
290 : NrSocketIpcState state_;
291 :
292 : std::queue<RefPtr<nr_udp_message>> received_msgs_;
293 :
294 : RefPtr<nsIUDPSocketChild> socket_child_; // only accessed from the io_thread
295 : };
296 :
297 : // The socket child holds onto one of these, which just passes callbacks
298 : // through and makes sure the ref to the NrSocketIpc is released on STS.
299 0 : class NrUdpSocketIpcProxy : public nsIUDPSocketInternal {
300 : public:
301 : NS_DECL_THREADSAFE_ISUPPORTS
302 : NS_DECL_NSIUDPSOCKETINTERNAL
303 :
304 : nsresult Init(const RefPtr<NrUdpSocketIpc>& socket);
305 :
306 : private:
307 : virtual ~NrUdpSocketIpcProxy();
308 :
309 : RefPtr<NrUdpSocketIpc> socket_;
310 : nsCOMPtr<nsIEventTarget> sts_thread_;
311 : };
312 :
313 : struct nr_tcp_message {
314 0 : explicit nr_tcp_message(nsAutoPtr<DataBuffer> &data)
315 0 : : read_bytes(0)
316 0 : , data(data) {
317 0 : }
318 :
319 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_tcp_message);
320 :
321 0 : const uint8_t *reading_pointer() const {
322 0 : return data->data() + read_bytes;
323 : }
324 :
325 0 : size_t unread_bytes() const {
326 0 : return data->len() - read_bytes;
327 : }
328 :
329 : size_t read_bytes;
330 :
331 : private:
332 0 : ~nr_tcp_message() {}
333 : DISALLOW_COPY_ASSIGN(nr_tcp_message);
334 :
335 : nsAutoPtr<DataBuffer> data;
336 : };
337 :
338 : #if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
339 : class NrTcpSocketIpc : public NrSocketIpc,
340 : public nsITCPSocketCallback {
341 : public:
342 : NS_DECL_THREADSAFE_ISUPPORTS
343 : NS_DECL_NSITCPSOCKETCALLBACK
344 :
345 : explicit NrTcpSocketIpc(nsIThread* aThread);
346 :
347 : // Implementations of the NrSocketBase APIs
348 : virtual int create(nr_transport_addr *addr) override;
349 : virtual int sendto(const void *msg, size_t len,
350 : int flags, nr_transport_addr *to) override;
351 : virtual int recvfrom(void * buf, size_t maxlen,
352 : size_t *len, int flags,
353 : nr_transport_addr *from) override;
354 : virtual int getaddr(nr_transport_addr *addrp) override;
355 : virtual void close() override;
356 : virtual int connect(nr_transport_addr *addr) override;
357 : virtual int write(const void *msg, size_t len, size_t *written) override;
358 : virtual int read(void* buf, size_t maxlen, size_t *len) override;
359 : virtual int listen(int backlog) override;
360 : virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
361 :
362 : private:
363 : class TcpSocketReadyRunner;
364 : DISALLOW_COPY_ASSIGN(NrTcpSocketIpc);
365 : virtual ~NrTcpSocketIpc();
366 :
367 : // Main thread executors of the NrSocketBase APIs
368 : void connect_i(const nsACString &remote_addr,
369 : uint16_t remote_port,
370 : const nsACString &local_addr,
371 : uint16_t local_port,
372 : const nsACString &tls_host);
373 : void write_i(nsAutoPtr<InfallibleTArray<uint8_t>> buf,
374 : uint32_t tracking_number);
375 : void close_i();
376 :
377 : static void release_child_i(dom::TCPSocketChild* aChild);
378 :
379 : // STS thread executor
380 : void message_sent_s(uint32_t bufferedAmount, uint32_t tracking_number);
381 : void recv_message_s(nr_tcp_message *msg);
382 : void update_state_s(NrSocketIpcState next_state);
383 : void maybe_post_socket_ready();
384 :
385 : // Accessed from UpdateReadyState (not sts_thread) to avoid sending
386 : // runnables when not needed
387 : NrSocketIpcState mirror_state_;
388 :
389 : // variables that can only be accessed on STS.
390 : NrSocketIpcState state_;
391 : std::queue<RefPtr<nr_tcp_message>> msg_queue_;
392 : uint32_t buffered_bytes_;
393 : uint32_t tracking_number_;
394 : std::deque<size_t> writes_in_flight_;
395 :
396 : // main thread.
397 : RefPtr<dom::TCPSocketChild> socket_child_;
398 : };
399 : #endif
400 :
401 : int nr_netaddr_to_transport_addr(const net::NetAddr *netaddr,
402 : nr_transport_addr *addr,
403 : int protocol);
404 : int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
405 : nr_transport_addr *addr,
406 : int protocol, int keep);
407 : int nr_transport_addr_get_addrstring_and_port(nr_transport_addr *addr,
408 : nsACString *host, int32_t *port);
409 : } // close namespace
410 : #endif
|