summaryrefslogtreecommitdiffstats
path: root/media/mtransport/nr_socket_prsock.h
diff options
context:
space:
mode:
Diffstat (limited to 'media/mtransport/nr_socket_prsock.h')
-rw-r--r--media/mtransport/nr_socket_prsock.h411
1 files changed, 411 insertions, 0 deletions
diff --git a/media/mtransport/nr_socket_prsock.h b/media/mtransport/nr_socket_prsock.h
new file mode 100644
index 000000000..0883ef7a5
--- /dev/null
+++ b/media/mtransport/nr_socket_prsock.h
@@ -0,0 +1,411 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Original author: ekr@rtfm.com
+
+/* Some source code here from nICEr. Copyright is:
+
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+// Implementation of nICEr/nr_socket that is tied to the Gecko
+// SocketTransportService.
+
+#ifndef nr_socket_prsock__
+#define nr_socket_prsock__
+
+#include <queue>
+
+#include "nspr.h"
+#include "prio.h"
+
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "nsASocketHandler.h"
+#include "nsISocketTransportService.h"
+#include "nsXPCOM.h"
+#include "nsIEventTarget.h"
+#include "nsIUDPSocketChild.h"
+#include "nsProxyRelease.h"
+#include "nsThreadUtils.h"
+
+#include "nsITCPSocketCallback.h"
+#include "databuffer.h"
+#include "m_cpp_utils.h"
+#include "mozilla/ReentrantMonitor.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/TimeStamp.h"
+#include "mozilla/ClearOnShutdown.h"
+
+// Stub declaration for nICEr type
+typedef struct nr_socket_vtbl_ nr_socket_vtbl;
+typedef struct nr_socket_ nr_socket;
+
+#if defined(MOZILLA_INTERNAL_API)
+namespace mozilla {
+namespace dom {
+class TCPSocketChild;
+}
+}
+#endif
+
+namespace mozilla {
+
+namespace net {
+ union NetAddr;
+}
+
+class NrSocketBase {
+public:
+ NrSocketBase() : connect_invoked_(false), poll_flags_(0) {
+ memset(cbs_, 0, sizeof(cbs_));
+ memset(cb_args_, 0, sizeof(cb_args_));
+ memset(&my_addr_, 0, sizeof(my_addr_));
+ }
+ virtual ~NrSocketBase() {}
+
+ // Factory method; will create either an NrSocket, NrUdpSocketIpc, or
+ // NrTcpSocketIpc as appropriate.
+ static int CreateSocket(nr_transport_addr *addr, RefPtr<NrSocketBase> *sock);
+
+ // the nr_socket APIs
+ virtual int create(nr_transport_addr *addr) = 0;
+ virtual int sendto(const void *msg, size_t len,
+ int flags, nr_transport_addr *to) = 0;
+ virtual int recvfrom(void * buf, size_t maxlen,
+ size_t *len, int flags,
+ nr_transport_addr *from) = 0;
+ virtual int getaddr(nr_transport_addr *addrp) = 0;
+ virtual void close() = 0;
+ virtual int connect(nr_transport_addr *addr) = 0;
+ virtual int write(const void *msg, size_t len, size_t *written) = 0;
+ virtual int read(void* buf, size_t maxlen, size_t *len) = 0;
+ virtual int listen(int backlog) = 0;
+ virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) = 0;
+
+ // Implementations of the async_event APIs
+ virtual int async_wait(int how, NR_async_cb cb, void *cb_arg,
+ char *function, int line);
+ virtual int cancel(int how);
+
+ // nsISupport reference counted interface
+ NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
+ NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
+
+ uint32_t poll_flags() {
+ return poll_flags_;
+ }
+
+ virtual nr_socket_vtbl *vtbl(); // To access in test classes.
+
+ static TimeStamp short_term_violation_time();
+ static TimeStamp long_term_violation_time();
+ const nr_transport_addr& my_addr() const {
+ return my_addr_;
+ }
+
+ void fire_callback(int how);
+
+protected:
+
+ bool connect_invoked_;
+ nr_transport_addr my_addr_;
+
+private:
+ NR_async_cb cbs_[NR_ASYNC_WAIT_WRITE + 1];
+ void *cb_args_[NR_ASYNC_WAIT_WRITE + 1];
+ uint32_t poll_flags_;
+};
+
+class NrSocket : public NrSocketBase,
+ public nsASocketHandler {
+public:
+ NrSocket() : fd_(nullptr) {}
+
+ // Implement nsASocket
+ virtual void OnSocketReady(PRFileDesc *fd, int16_t outflags) override;
+ virtual void OnSocketDetached(PRFileDesc *fd) override;
+ virtual void IsLocal(bool *aIsLocal) override;
+ virtual uint64_t ByteCountSent() override { return 0; }
+ virtual uint64_t ByteCountReceived() override { return 0; }
+
+ // nsISupports methods
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ // Implementations of the async_event APIs
+ virtual int async_wait(int how, NR_async_cb cb, void *cb_arg,
+ char *function, int line) override;
+ virtual int cancel(int how) override;
+
+
+ // Implementations of the nr_socket APIs
+ virtual int create(nr_transport_addr *addr) override; // (really init, but it's called create)
+ virtual int sendto(const void *msg, size_t len,
+ int flags, nr_transport_addr *to) override;
+ virtual int recvfrom(void * buf, size_t maxlen,
+ size_t *len, int flags,
+ nr_transport_addr *from) override;
+ virtual int getaddr(nr_transport_addr *addrp) override;
+ virtual void close() override;
+ virtual int connect(nr_transport_addr *addr) override;
+ virtual int write(const void *msg, size_t len, size_t *written) override;
+ virtual int read(void* buf, size_t maxlen, size_t *len) override;
+ virtual int listen(int backlog) override;
+ virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
+
+protected:
+ virtual ~NrSocket() {
+ if (fd_)
+ PR_Close(fd_);
+ }
+
+ DISALLOW_COPY_ASSIGN(NrSocket);
+
+ PRFileDesc *fd_;
+ nsCOMPtr<nsIEventTarget> ststhread_;
+};
+
+struct nr_udp_message {
+ nr_udp_message(const PRNetAddr &from, nsAutoPtr<DataBuffer> &data)
+ : from(from), data(data) {
+ }
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_udp_message);
+
+ PRNetAddr from;
+ nsAutoPtr<DataBuffer> data;
+
+private:
+ ~nr_udp_message() {}
+ DISALLOW_COPY_ASSIGN(nr_udp_message);
+};
+
+class NrSocketIpc : public NrSocketBase {
+public:
+
+ enum NrSocketIpcState {
+ NR_INIT,
+ NR_CONNECTING,
+ NR_CONNECTED,
+ NR_CLOSING,
+ NR_CLOSED,
+ };
+
+ NrSocketIpc(nsIEventTarget* aThread);
+
+protected:
+ nsCOMPtr<nsIEventTarget> sts_thread_;
+ // Note: for UDP PBackground, this is a thread held by SingletonThreadHolder.
+ // For TCP PNecko, this is MainThread (and TCPSocket requires MainThread currently)
+ const nsCOMPtr<nsIEventTarget> io_thread_;
+ virtual ~NrSocketIpc() {};
+
+private:
+ DISALLOW_COPY_ASSIGN(NrSocketIpc);
+};
+
+class NrUdpSocketIpc : public NrSocketIpc {
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrUdpSocketIpc, override)
+
+ NS_IMETHODIMP CallListenerError(const nsACString &message,
+ const nsACString &filename,
+ uint32_t line_number);
+ NS_IMETHODIMP CallListenerReceivedData(const nsACString &host,
+ uint16_t port,
+ const uint8_t *data,
+ uint32_t data_length);
+ NS_IMETHODIMP CallListenerOpened();
+ NS_IMETHODIMP CallListenerConnected();
+ NS_IMETHODIMP CallListenerClosed();
+
+ NrUdpSocketIpc();
+
+ // Implementations of the NrSocketBase APIs
+ virtual int create(nr_transport_addr *addr) override;
+ virtual int sendto(const void *msg, size_t len,
+ int flags, nr_transport_addr *to) override;
+ virtual int recvfrom(void * buf, size_t maxlen,
+ size_t *len, int flags,
+ nr_transport_addr *from) override;
+ virtual int getaddr(nr_transport_addr *addrp) override;
+ virtual void close() override;
+ virtual int connect(nr_transport_addr *addr) override;
+ virtual int write(const void *msg, size_t len, size_t *written) override;
+ virtual int read(void* buf, size_t maxlen, size_t *len) override;
+ virtual int listen(int backlog) override;
+ virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
+
+private:
+ virtual ~NrUdpSocketIpc();
+
+ DISALLOW_COPY_ASSIGN(NrUdpSocketIpc);
+
+ nsresult SetAddress(); // Set the local address from parent info.
+
+ // Main or private thread executors of the NrSocketBase APIs
+ void create_i(const nsACString &host, const uint16_t port);
+ void connect_i(const nsACString &host, const uint16_t port);
+ void sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf);
+ void close_i();
+#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
+ static void release_child_i(nsIUDPSocketChild* aChild, nsCOMPtr<nsIEventTarget> ststhread);
+ static void release_use_s();
+#endif
+ // STS thread executor
+ void recv_callback_s(RefPtr<nr_udp_message> msg);
+
+ ReentrantMonitor monitor_; // protects err_and state_
+ bool err_;
+ NrSocketIpcState state_;
+
+ std::queue<RefPtr<nr_udp_message>> received_msgs_;
+
+ RefPtr<nsIUDPSocketChild> socket_child_; // only accessed from the io_thread
+};
+
+// The socket child holds onto one of these, which just passes callbacks
+// through and makes sure the ref to the NrSocketIpc is released on STS.
+class NrUdpSocketIpcProxy : public nsIUDPSocketInternal {
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIUDPSOCKETINTERNAL
+
+ nsresult Init(const RefPtr<NrUdpSocketIpc>& socket);
+
+private:
+ virtual ~NrUdpSocketIpcProxy();
+
+ RefPtr<NrUdpSocketIpc> socket_;
+ nsCOMPtr<nsIEventTarget> sts_thread_;
+};
+
+struct nr_tcp_message {
+ explicit nr_tcp_message(nsAutoPtr<DataBuffer> &data)
+ : read_bytes(0)
+ , data(data) {
+ }
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_tcp_message);
+
+ const uint8_t *reading_pointer() const {
+ return data->data() + read_bytes;
+ }
+
+ size_t unread_bytes() const {
+ return data->len() - read_bytes;
+ }
+
+ size_t read_bytes;
+
+private:
+ ~nr_tcp_message() {}
+ DISALLOW_COPY_ASSIGN(nr_tcp_message);
+
+ nsAutoPtr<DataBuffer> data;
+};
+
+#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
+class NrTcpSocketIpc : public NrSocketIpc,
+ public nsITCPSocketCallback {
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSITCPSOCKETCALLBACK
+
+ explicit NrTcpSocketIpc(nsIThread* aThread);
+
+ // Implementations of the NrSocketBase APIs
+ virtual int create(nr_transport_addr *addr) override;
+ virtual int sendto(const void *msg, size_t len,
+ int flags, nr_transport_addr *to) override;
+ virtual int recvfrom(void * buf, size_t maxlen,
+ size_t *len, int flags,
+ nr_transport_addr *from) override;
+ virtual int getaddr(nr_transport_addr *addrp) override;
+ virtual void close() override;
+ virtual int connect(nr_transport_addr *addr) override;
+ virtual int write(const void *msg, size_t len, size_t *written) override;
+ virtual int read(void* buf, size_t maxlen, size_t *len) override;
+ virtual int listen(int backlog) override;
+ virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
+
+private:
+ class TcpSocketReadyRunner;
+ DISALLOW_COPY_ASSIGN(NrTcpSocketIpc);
+ virtual ~NrTcpSocketIpc();
+
+ // Main thread executors of the NrSocketBase APIs
+ void connect_i(const nsACString &remote_addr,
+ uint16_t remote_port,
+ const nsACString &local_addr,
+ uint16_t local_port);
+ void write_i(nsAutoPtr<InfallibleTArray<uint8_t>> buf,
+ uint32_t tracking_number);
+ void close_i();
+
+ static void release_child_i(dom::TCPSocketChild* aChild, nsCOMPtr<nsIEventTarget> ststhread);
+
+ // STS thread executor
+ void message_sent_s(uint32_t bufferedAmount, uint32_t tracking_number);
+ void recv_message_s(nr_tcp_message *msg);
+ void update_state_s(NrSocketIpcState next_state);
+ void maybe_post_socket_ready();
+
+ // Accessed from UpdateReadyState (not sts_thread) to avoid sending
+ // runnables when not needed
+ NrSocketIpcState mirror_state_;
+
+ // variables that can only be accessed on STS.
+ NrSocketIpcState state_;
+ std::queue<RefPtr<nr_tcp_message>> msg_queue_;
+ uint32_t buffered_bytes_;
+ uint32_t tracking_number_;
+ std::deque<size_t> writes_in_flight_;
+
+ // main thread.
+ RefPtr<dom::TCPSocketChild> socket_child_;
+};
+#endif
+
+int nr_netaddr_to_transport_addr(const net::NetAddr *netaddr,
+ nr_transport_addr *addr,
+ int protocol);
+int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
+ nr_transport_addr *addr,
+ int protocol, int keep);
+int nr_transport_addr_get_addrstring_and_port(nr_transport_addr *addr,
+ nsACString *host, int32_t *port);
+} // close namespace
+#endif