michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Original author: ekr@rtfm.com michael@0: michael@0: /* Some source code here from nICEr. Copyright is: michael@0: michael@0: Copyright (c) 2007, Adobe Systems, Incorporated michael@0: All rights reserved. michael@0: michael@0: Redistribution and use in source and binary forms, with or without michael@0: modification, are permitted provided that the following conditions are michael@0: met: michael@0: michael@0: * Redistributions of source code must retain the above copyright michael@0: notice, this list of conditions and the following disclaimer. michael@0: michael@0: * Redistributions in binary form must reproduce the above copyright michael@0: notice, this list of conditions and the following disclaimer in the michael@0: documentation and/or other materials provided with the distribution. michael@0: michael@0: * Neither the name of Adobe Systems, Network Resonance nor the names of its michael@0: contributors may be used to endorse or promote products derived from michael@0: this software without specific prior written permission. michael@0: michael@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: */ michael@0: michael@0: michael@0: // Implementation of nICEr/nr_socket that is tied to the Gecko michael@0: // SocketTransportService. michael@0: michael@0: #ifndef nr_socket_prsock__ michael@0: #define nr_socket_prsock__ michael@0: michael@0: #include michael@0: michael@0: #include "nspr.h" michael@0: #include "prio.h" michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsASocketHandler.h" michael@0: #include "nsISocketTransportService.h" michael@0: #include "nsXPCOM.h" michael@0: #include "nsIEventTarget.h" michael@0: #include "nsIUDPSocketChild.h" michael@0: michael@0: #include "databuffer.h" michael@0: #include "m_cpp_utils.h" michael@0: #include "mozilla/ReentrantMonitor.h" michael@0: #include "mozilla/RefPtr.h" michael@0: michael@0: // Stub declaration for nICEr type michael@0: typedef struct nr_socket_vtbl_ nr_socket_vtbl; michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace net { michael@0: union NetAddr; michael@0: } michael@0: michael@0: class NrSocketBase { michael@0: public: michael@0: NrSocketBase() : connect_invoked_(false), poll_flags_(0) { michael@0: memset(cbs_, 0, sizeof(cbs_)); michael@0: memset(cb_args_, 0, sizeof(cb_args_)); michael@0: memset(&my_addr_, 0, sizeof(my_addr_)); michael@0: } michael@0: virtual ~NrSocketBase() {} michael@0: michael@0: // the nr_socket APIs michael@0: virtual int create(nr_transport_addr *addr) = 0; michael@0: virtual int sendto(const void *msg, size_t len, michael@0: int flags, nr_transport_addr *to) = 0; michael@0: virtual int recvfrom(void * buf, size_t maxlen, michael@0: size_t *len, int flags, michael@0: nr_transport_addr *from) = 0; michael@0: virtual int getaddr(nr_transport_addr *addrp) = 0; michael@0: virtual void close() = 0; michael@0: virtual int connect(nr_transport_addr *addr) = 0; michael@0: virtual int write(const void *msg, size_t len, size_t *written) = 0; michael@0: virtual int read(void* buf, size_t maxlen, size_t *len) = 0; michael@0: michael@0: // Implementations of the async_event APIs michael@0: virtual int async_wait(int how, NR_async_cb cb, void *cb_arg, michael@0: char *function, int line); michael@0: virtual int cancel(int how); michael@0: michael@0: // nsISupport reference counted interface michael@0: NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; michael@0: NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; michael@0: michael@0: uint32_t poll_flags() { michael@0: return poll_flags_; michael@0: } michael@0: michael@0: virtual nr_socket_vtbl *vtbl(); // To access in test classes. michael@0: michael@0: protected: michael@0: void fire_callback(int how); michael@0: michael@0: bool connect_invoked_; michael@0: nr_transport_addr my_addr_; michael@0: michael@0: private: michael@0: NR_async_cb cbs_[NR_ASYNC_WAIT_WRITE + 1]; michael@0: void *cb_args_[NR_ASYNC_WAIT_WRITE + 1]; michael@0: uint32_t poll_flags_; michael@0: }; michael@0: michael@0: class NrSocket : public NrSocketBase, michael@0: public nsASocketHandler { michael@0: public: michael@0: NrSocket() : fd_(nullptr) {} michael@0: virtual ~NrSocket() { michael@0: PR_Close(fd_); michael@0: } michael@0: michael@0: // Implement nsASocket michael@0: virtual void OnSocketReady(PRFileDesc *fd, int16_t outflags); michael@0: virtual void OnSocketDetached(PRFileDesc *fd); michael@0: virtual void IsLocal(bool *aIsLocal); michael@0: virtual uint64_t ByteCountSent() { return 0; } michael@0: virtual uint64_t ByteCountReceived() { return 0; } michael@0: michael@0: // nsISupports methods michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: michael@0: // Implementations of the async_event APIs michael@0: virtual int async_wait(int how, NR_async_cb cb, void *cb_arg, michael@0: char *function, int line); michael@0: virtual int cancel(int how); michael@0: michael@0: michael@0: // Implementations of the nr_socket APIs michael@0: virtual int create(nr_transport_addr *addr); // (really init, but it's called create) michael@0: virtual int sendto(const void *msg, size_t len, michael@0: int flags, nr_transport_addr *to); michael@0: virtual int recvfrom(void * buf, size_t maxlen, michael@0: size_t *len, int flags, michael@0: nr_transport_addr *from); michael@0: virtual int getaddr(nr_transport_addr *addrp); michael@0: virtual void close(); michael@0: virtual int connect(nr_transport_addr *addr); michael@0: virtual int write(const void *msg, size_t len, size_t *written); michael@0: virtual int read(void* buf, size_t maxlen, size_t *len); michael@0: michael@0: private: michael@0: DISALLOW_COPY_ASSIGN(NrSocket); michael@0: michael@0: PRFileDesc *fd_; michael@0: nsCOMPtr ststhread_; michael@0: }; michael@0: michael@0: struct nr_udp_message { michael@0: nr_udp_message(const PRNetAddr &from, nsAutoPtr &data) michael@0: : from(from), data(data) { michael@0: } michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_udp_message); michael@0: michael@0: PRNetAddr from; michael@0: nsAutoPtr data; michael@0: michael@0: private: michael@0: DISALLOW_COPY_ASSIGN(nr_udp_message); michael@0: }; michael@0: michael@0: class NrSocketIpc : public NrSocketBase, michael@0: public nsIUDPSocketInternal { michael@0: public: michael@0: michael@0: enum NrSocketIpcState { michael@0: NR_INIT, michael@0: NR_CONNECTING, michael@0: NR_CONNECTED, michael@0: NR_CLOSING, michael@0: NR_CLOSED, michael@0: }; michael@0: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSIUDPSOCKETINTERNAL michael@0: michael@0: NrSocketIpc(const nsCOMPtr &main_thread); michael@0: virtual ~NrSocketIpc() {}; michael@0: michael@0: // Implementations of the NrSocketBase APIs michael@0: virtual int create(nr_transport_addr *addr); michael@0: virtual int sendto(const void *msg, size_t len, michael@0: int flags, nr_transport_addr *to); michael@0: virtual int recvfrom(void * buf, size_t maxlen, michael@0: size_t *len, int flags, michael@0: nr_transport_addr *from); michael@0: virtual int getaddr(nr_transport_addr *addrp); michael@0: virtual void close(); michael@0: virtual int connect(nr_transport_addr *addr); michael@0: virtual int write(const void *msg, size_t len, size_t *written); michael@0: virtual int read(void* buf, size_t maxlen, size_t *len); michael@0: michael@0: private: michael@0: DISALLOW_COPY_ASSIGN(NrSocketIpc); michael@0: michael@0: // Main thread executors of the NrSocketBase APIs michael@0: void create_m(const nsACString &host, const uint16_t port); michael@0: void sendto_m(const net::NetAddr &addr, nsAutoPtr buf); michael@0: void close_m(); michael@0: // STS thread executor michael@0: void recv_callback_s(RefPtr msg); michael@0: michael@0: bool err_; michael@0: NrSocketIpcState state_; michael@0: std::queue > received_msgs_; michael@0: michael@0: nsCOMPtr socket_child_; michael@0: nsCOMPtr sts_thread_; michael@0: const nsCOMPtr main_thread_; michael@0: ReentrantMonitor monitor_; michael@0: }; michael@0: michael@0: int nr_netaddr_to_transport_addr(const net::NetAddr *netaddr, michael@0: nr_transport_addr *addr, michael@0: int protocol); michael@0: int nr_praddr_to_transport_addr(const PRNetAddr *praddr, michael@0: nr_transport_addr *addr, michael@0: int protocol, int keep); michael@0: int nr_transport_addr_get_addrstring_and_port(nr_transport_addr *addr, michael@0: nsACString *host, int32_t *port); michael@0: } // close namespace michael@0: #endif