michael@0: /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ 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 michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_ipc_UnixSocket_h michael@0: #define mozilla_ipc_UnixSocket_h michael@0: michael@0: michael@0: #include michael@0: #include "nsAutoPtr.h" michael@0: #include "nsString.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "mozilla/ipc/UnixSocketWatcher.h" michael@0: #include "mozilla/RefPtr.h" michael@0: michael@0: namespace mozilla { michael@0: namespace ipc { michael@0: michael@0: class UnixSocketRawData michael@0: { michael@0: public: michael@0: // Number of octets in mData. michael@0: size_t mSize; michael@0: size_t mCurrentWriteOffset; michael@0: nsAutoArrayPtr mData; michael@0: michael@0: /** michael@0: * Constructor for situations where only size is known beforehand michael@0: * (for example, when being assigned strings) michael@0: */ michael@0: UnixSocketRawData(size_t aSize) : michael@0: mSize(aSize), michael@0: mCurrentWriteOffset(0) michael@0: { michael@0: mData = new uint8_t[mSize]; michael@0: } michael@0: michael@0: /** michael@0: * Constructor for situations where size and data is known michael@0: * beforehand (for example, when being assigned strings) michael@0: */ michael@0: UnixSocketRawData(const void* aData, size_t aSize) michael@0: : mSize(aSize), michael@0: mCurrentWriteOffset(0) michael@0: { michael@0: MOZ_ASSERT(aData || !mSize); michael@0: mData = new uint8_t[mSize]; michael@0: memcpy(mData, aData, mSize); michael@0: } michael@0: }; michael@0: michael@0: class UnixSocketImpl; michael@0: michael@0: /** michael@0: * UnixSocketConnector defines the socket creation and connection/listening michael@0: * functions for a UnixSocketConsumer. Due to the fact that socket setup can michael@0: * vary between protocols (unix sockets, tcp sockets, bluetooth sockets, etc), michael@0: * this allows the user to create whatever connection mechanism they need while michael@0: * still depending on libevent for non-blocking communication handling. michael@0: * michael@0: * FIXME/Bug 793980: Currently only virtual, since we only support bluetooth. michael@0: * Should make connection functions for other unix sockets so we can support michael@0: * things like RIL. michael@0: */ michael@0: class UnixSocketConnector michael@0: { michael@0: public: michael@0: UnixSocketConnector() michael@0: {} michael@0: michael@0: virtual ~UnixSocketConnector() michael@0: {} michael@0: michael@0: /** michael@0: * Establishs a file descriptor for a socket. michael@0: * michael@0: * @return File descriptor for socket michael@0: */ michael@0: virtual int Create() = 0; michael@0: michael@0: /** michael@0: * Since most socket specifics are related to address formation into a michael@0: * sockaddr struct, this function is defined by subclasses and fills in the michael@0: * structure as needed for whatever connection it is trying to build michael@0: * michael@0: * @param aIsServer True is we are acting as a server socket michael@0: * @param aAddrSize Size of the struct michael@0: * @param aAddr Struct to fill michael@0: * @param aAddress If aIsServer is false, Address to connect to. nullptr otherwise. michael@0: * michael@0: * @return True if address is filled correctly, false otherwise michael@0: */ michael@0: virtual bool CreateAddr(bool aIsServer, michael@0: socklen_t& aAddrSize, michael@0: sockaddr_any& aAddr, michael@0: const char* aAddress) = 0; michael@0: michael@0: /** michael@0: * Does any socket type specific setup that may be needed, only for socket michael@0: * created by ConnectSocket() michael@0: * michael@0: * @param aFd File descriptor for opened socket michael@0: * michael@0: * @return true is successful, false otherwise michael@0: */ michael@0: virtual bool SetUp(int aFd) = 0; michael@0: michael@0: /** michael@0: * Perform socket setup for socket created by ListenSocket(), after listen(). michael@0: * michael@0: * @param aFd File descriptor for opened socket michael@0: * michael@0: * @return true is successful, false otherwise michael@0: */ michael@0: virtual bool SetUpListenSocket(int aFd) = 0; michael@0: michael@0: /** michael@0: * Get address of socket we're currently connected to. Return null string if michael@0: * not connected. michael@0: * michael@0: * @param aAddr Address struct michael@0: * @param aAddrStr String to store address to michael@0: */ michael@0: virtual void GetSocketAddr(const sockaddr_any& aAddr, michael@0: nsAString& aAddrStr) = 0; michael@0: michael@0: }; michael@0: michael@0: enum SocketConnectionStatus { michael@0: SOCKET_DISCONNECTED = 0, michael@0: SOCKET_LISTENING = 1, michael@0: SOCKET_CONNECTING = 2, michael@0: SOCKET_CONNECTED = 3 michael@0: }; michael@0: michael@0: class UnixSocketConsumer michael@0: { michael@0: protected: michael@0: virtual ~UnixSocketConsumer(); michael@0: michael@0: public: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UnixSocketConsumer) michael@0: michael@0: UnixSocketConsumer(); michael@0: michael@0: SocketConnectionStatus GetConnectionStatus() const michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: return mConnectionStatus; michael@0: } michael@0: michael@0: int GetSuggestedConnectDelayMs() const michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: return mConnectDelayMs; michael@0: } michael@0: michael@0: /** michael@0: * Function to be called whenever data is received. This is only called on the michael@0: * main thread. michael@0: * michael@0: * @param aMessage Data received from the socket. michael@0: */ michael@0: virtual void ReceiveSocketData(nsAutoPtr& aMessage) = 0; michael@0: michael@0: /** michael@0: * Queue data to be sent to the socket on the IO thread. Can only be called on michael@0: * originating thread. michael@0: * michael@0: * @param aMessage Data to be sent to socket michael@0: * michael@0: * @return true if data is queued, false otherwise (i.e. not connected) michael@0: */ michael@0: bool SendSocketData(UnixSocketRawData* aMessage); michael@0: michael@0: /** michael@0: * Convenience function for sending strings to the socket (common in bluetooth michael@0: * profile usage). Converts to a UnixSocketRawData struct. Can only be called michael@0: * on originating thread. michael@0: * michael@0: * @param aMessage String to be sent to socket michael@0: * michael@0: * @return true if data is queued, false otherwise (i.e. not connected) michael@0: */ michael@0: bool SendSocketData(const nsACString& aMessage); michael@0: michael@0: /** michael@0: * Starts a task on the socket that will try to connect to a socket in a michael@0: * non-blocking manner. michael@0: * michael@0: * @param aConnector Connector object for socket type specific functions michael@0: * @param aAddress Address to connect to. michael@0: * @param aDelayMs Time delay in milli-seconds. michael@0: * michael@0: * @return true on connect task started, false otherwise. michael@0: */ michael@0: bool ConnectSocket(UnixSocketConnector* aConnector, michael@0: const char* aAddress, michael@0: int aDelayMs = 0); michael@0: michael@0: /** michael@0: * Starts a task on the socket that will try to accept a new connection in a michael@0: * non-blocking manner. michael@0: * michael@0: * @param aConnector Connector object for socket type specific functions michael@0: * michael@0: * @return true on listen started, false otherwise michael@0: */ michael@0: bool ListenSocket(UnixSocketConnector* aConnector); michael@0: michael@0: /** michael@0: * Queues the internal representation of socket for deletion. Can be called michael@0: * from main thread. michael@0: */ michael@0: void CloseSocket(); michael@0: michael@0: /** michael@0: * Callback for socket connect/accept success. Called after connect/accept has michael@0: * finished. Will be run on main thread, before any reads take place. michael@0: */ michael@0: virtual void OnConnectSuccess() = 0; michael@0: michael@0: /** michael@0: * Callback for socket connect/accept error. Will be run on main thread. michael@0: */ michael@0: virtual void OnConnectError() = 0; michael@0: michael@0: /** michael@0: * Callback for socket disconnect. Will be run on main thread. michael@0: */ michael@0: virtual void OnDisconnect() = 0; michael@0: michael@0: /** michael@0: * Called by implementation to notify consumer of success. michael@0: */ michael@0: void NotifySuccess(); michael@0: michael@0: /** michael@0: * Called by implementation to notify consumer of error. michael@0: */ michael@0: void NotifyError(); michael@0: michael@0: /** michael@0: * Called by implementation to notify consumer of disconnect. michael@0: */ michael@0: void NotifyDisconnect(); michael@0: michael@0: /** michael@0: * Get the current sockaddr for the socket michael@0: */ michael@0: void GetSocketAddr(nsAString& aAddrStr); michael@0: michael@0: private: michael@0: uint32_t CalculateConnectDelayMs() const; michael@0: michael@0: UnixSocketImpl* mImpl; michael@0: SocketConnectionStatus mConnectionStatus; michael@0: PRIntervalTime mConnectTimestamp; michael@0: uint32_t mConnectDelayMs; michael@0: }; michael@0: michael@0: } // namespace ipc michael@0: } // namepsace mozilla michael@0: michael@0: #endif // mozilla_ipc_Socket_h