nr_socket_prsock.h (11038B)
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 // Implementation of nICEr/nr_socket that is tied to the Gecko 43 // SocketTransportService. 44 45 #ifndef nr_socket_prsock__ 46 #define nr_socket_prsock__ 47 48 #include <memory> 49 #include <queue> 50 51 #include "m_cpp_utils.h" 52 #include "mediapacket.h" 53 #include "mozilla/ClearOnShutdown.h" 54 #include "mozilla/ReentrantMonitor.h" 55 #include "mozilla/RefPtr.h" 56 #include "mozilla/TimeStamp.h" 57 #include "nsASocketHandler.h" 58 #include "nsCOMPtr.h" 59 #include "nsIEventTarget.h" 60 #include "nsIUDPSocketChild.h" 61 #include "nsProxyRelease.h" 62 #include "nsThreadUtils.h" 63 #include "nsXPCOM.h" 64 #include "nspr.h" 65 #include "prio.h" 66 67 // nICEr includes 68 extern "C" { 69 #include "async_wait.h" 70 #include "transport_addr.h" 71 } 72 73 // Stub declaration for nICEr type 74 typedef struct nr_socket_vtbl_ nr_socket_vtbl; 75 typedef struct nr_socket_ nr_socket; 76 77 #if defined(MOZILLA_INTERNAL_API) 78 namespace mozilla { 79 class NrSocketProxyConfig; 80 } // namespace mozilla 81 #endif 82 83 namespace mozilla { 84 85 namespace net { 86 union NetAddr; 87 } 88 89 namespace dom { 90 class UDPSocketChild; 91 } // namespace dom 92 93 class NrSocketBase { 94 public: 95 NrSocketBase() : connect_invoked_(false), poll_flags_(0) { 96 memset(cbs_, 0, sizeof(cbs_)); 97 memset(cb_args_, 0, sizeof(cb_args_)); 98 memset(&my_addr_, 0, sizeof(my_addr_)); 99 } 100 virtual ~NrSocketBase() = default; 101 102 // Factory method; will create either an NrSocket, NrUdpSocketIpc, or 103 // NrTcpSocketIpc as appropriate. 104 static int CreateSocket(nr_transport_addr* addr, RefPtr<NrSocketBase>* sock, 105 const std::shared_ptr<NrSocketProxyConfig>& config); 106 static bool IsForbiddenAddress(nr_transport_addr* addr); 107 108 // the nr_socket APIs 109 virtual int create(nr_transport_addr* addr) = 0; 110 virtual int sendto(const void* msg, size_t len, int flags, 111 const nr_transport_addr* to) = 0; 112 virtual int recvfrom(void* buf, size_t maxlen, size_t* len, int flags, 113 nr_transport_addr* from) = 0; 114 virtual int getaddr(nr_transport_addr* addrp) = 0; 115 virtual void close() = 0; 116 virtual int connect(const nr_transport_addr* addr) = 0; 117 virtual int write(const void* msg, size_t len, size_t* written) = 0; 118 virtual int read(void* buf, size_t maxlen, size_t* len) = 0; 119 virtual int listen(int backlog) = 0; 120 virtual int accept(nr_transport_addr* addrp, nr_socket** sockp) = 0; 121 122 // Implementations of the async_event APIs 123 virtual int async_wait(int how, NR_async_cb cb, void* cb_arg, char* function, 124 int line); 125 virtual int cancel(int how); 126 127 // nsISupport reference counted interface 128 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 129 130 uint32_t poll_flags() { return poll_flags_; } 131 132 virtual nr_socket_vtbl* vtbl(); // To access in test classes. 133 134 static TimeStamp short_term_violation_time(); 135 static TimeStamp long_term_violation_time(); 136 const nr_transport_addr& my_addr() const { return my_addr_; } 137 138 void fire_callback(int how); 139 140 protected: 141 bool connect_invoked_; 142 nr_transport_addr my_addr_; 143 144 private: 145 NR_async_cb cbs_[NR_ASYNC_WAIT_WRITE + 1]; 146 void* cb_args_[NR_ASYNC_WAIT_WRITE + 1]; 147 uint32_t poll_flags_; 148 }; 149 150 class NrSocket : public NrSocketBase, public nsASocketHandler { 151 public: 152 NrSocket() : fd_(nullptr) {} 153 154 // Implement nsASocket 155 virtual void OnSocketReady(PRFileDesc* fd, int16_t outflags) override; 156 virtual void OnSocketDetached(PRFileDesc* fd) override; 157 virtual void IsLocal(bool* aIsLocal) override; 158 virtual uint64_t ByteCountSent() override { return 0; } 159 virtual uint64_t ByteCountReceived() override { return 0; } 160 161 // nsISupports methods 162 NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; 163 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DESTROY(NrSocket, Destroy(), 164 override); 165 virtual void Destroy() { delete this; } 166 167 // Implementations of the async_event APIs 168 virtual int async_wait(int how, NR_async_cb cb, void* cb_arg, char* function, 169 int line) override; 170 virtual int cancel(int how) override; 171 172 // Implementations of the nr_socket APIs 173 virtual int create(nr_transport_addr* addr) 174 override; // (really init, but it's called create) 175 virtual int sendto(const void* msg, size_t len, int flags, 176 const nr_transport_addr* to) override; 177 virtual int recvfrom(void* buf, size_t maxlen, 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(const 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 virtual ~NrSocket() { 189 if (fd_) PR_Close(fd_); 190 } 191 192 DISALLOW_COPY_ASSIGN(NrSocket); 193 194 PRFileDesc* fd_; 195 nsCOMPtr<nsIEventTarget> ststhread_; 196 }; 197 198 struct nr_udp_message { 199 nr_udp_message(const PRNetAddr& from, UniquePtr<MediaPacket>&& data) 200 : from(from), data(std::move(data)) {} 201 202 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_udp_message); 203 204 PRNetAddr from; 205 UniquePtr<MediaPacket> data; 206 207 private: 208 ~nr_udp_message() = default; 209 DISALLOW_COPY_ASSIGN(nr_udp_message); 210 }; 211 212 class NrSocketIpc : public NrSocketBase { 213 public: 214 enum NrSocketIpcState { 215 NR_INIT, 216 NR_CONNECTING, 217 NR_CONNECTED, 218 NR_CLOSING, 219 NR_CLOSED, 220 }; 221 222 NrSocketIpc(nsIEventTarget* aThread); 223 224 protected: 225 nsCOMPtr<nsIEventTarget> sts_thread_; 226 // Note: for UDP PBackground, this is a thread held by SingletonThreadHolder. 227 // For TCP PNecko, this is MainThread (and TCPSocket requires MainThread 228 // currently) 229 const nsCOMPtr<nsIEventTarget> io_thread_; 230 virtual ~NrSocketIpc() = default; 231 232 private: 233 DISALLOW_COPY_ASSIGN(NrSocketIpc); 234 }; 235 236 class NrUdpSocketIpc : public NrSocketIpc { 237 public: 238 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrUdpSocketIpc, override) 239 240 NS_IMETHODIMP CallListenerError(const nsACString& message, 241 const nsACString& filename, 242 uint32_t line_number); 243 NS_IMETHODIMP CallListenerReceivedData(const nsACString& host, uint16_t port, 244 const nsTArray<uint8_t>& data); 245 NS_IMETHODIMP CallListenerOpened(); 246 NS_IMETHODIMP CallListenerConnected(); 247 NS_IMETHODIMP CallListenerClosed(); 248 249 NrUdpSocketIpc(); 250 251 // Implementations of the NrSocketBase APIs 252 virtual int create(nr_transport_addr* addr) override; 253 virtual int sendto(const void* msg, size_t len, int flags, 254 const nr_transport_addr* to) override; 255 virtual int recvfrom(void* buf, size_t maxlen, size_t* len, int flags, 256 nr_transport_addr* from) override; 257 virtual int getaddr(nr_transport_addr* addrp) override; 258 virtual void close() override; 259 virtual int connect(const nr_transport_addr* addr) override; 260 virtual int write(const void* msg, size_t len, size_t* written) override; 261 virtual int read(void* buf, size_t maxlen, size_t* len) override; 262 virtual int listen(int backlog) override; 263 virtual int accept(nr_transport_addr* addrp, nr_socket** sockp) override; 264 265 private: 266 virtual ~NrUdpSocketIpc(); 267 virtual void Destroy(); 268 269 DISALLOW_COPY_ASSIGN(NrUdpSocketIpc); 270 271 nsresult SetAddress() 272 MOZ_REQUIRES(monitor_); // Set the local address from parent info. 273 274 // Main or private thread executors of the NrSocketBase APIs 275 void create_i(const nsACString& host, const uint16_t port); 276 void connect_i(const nsACString& host, const uint16_t port); 277 void sendto_i(const net::NetAddr& addr, UniquePtr<MediaPacket> buf); 278 void close_i(); 279 #if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API) 280 void destroy_i(); 281 #endif 282 // STS thread executor 283 void recv_callback_s(RefPtr<nr_udp_message> msg); 284 285 ReentrantMonitor monitor_ MOZ_UNANNOTATED; // protects err_and state_ 286 bool err_; 287 NrSocketIpcState state_; 288 289 std::queue<RefPtr<nr_udp_message>> received_msgs_; 290 291 // only accessed from the io_thread 292 RefPtr<dom::UDPSocketChild> socket_child_; 293 }; 294 295 // The socket child holds onto one of these, which just passes callbacks 296 // through and makes sure the ref to the NrSocketIpc is released on STS. 297 class NrUdpSocketIpcProxy : public nsIUDPSocketInternal { 298 public: 299 NS_DECL_THREADSAFE_ISUPPORTS 300 NS_DECL_NSIUDPSOCKETINTERNAL 301 302 nsresult Init(const RefPtr<NrUdpSocketIpc>& socket); 303 304 private: 305 virtual ~NrUdpSocketIpcProxy(); 306 307 RefPtr<NrUdpSocketIpc> socket_; 308 nsCOMPtr<nsIEventTarget> sts_thread_; 309 }; 310 311 int nr_netaddr_to_transport_addr(const net::NetAddr* netaddr, 312 nr_transport_addr* addr, int protocol); 313 int nr_praddr_to_transport_addr(const PRNetAddr* praddr, 314 nr_transport_addr* addr, int protocol, 315 int keep); 316 int nr_transport_addr_get_addrstring_and_port(const nr_transport_addr* addr, 317 nsACString* host, int32_t* port); 318 } // namespace mozilla 319 #endif