diff --git a/ipc/unixsocket/SocketBase.cpp b/ipc/unixsocket/SocketBase.cpp new file mode 100644 index 00000000000..f0509ad07ed --- /dev/null +++ b/ipc/unixsocket/SocketBase.cpp @@ -0,0 +1,126 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* 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/. + */ + +#include "SocketBase.h" +#include +#include "nsThreadUtils.h" + +namespace mozilla { +namespace ipc { + +// +// UnixSocketRawData +// + +UnixSocketRawData::UnixSocketRawData(size_t aSize) +: mSize(aSize) +, mCurrentWriteOffset(0) +{ + mData = new uint8_t[mSize]; +} + +UnixSocketRawData::UnixSocketRawData(const void* aData, size_t aSize) +: mSize(aSize) +, mCurrentWriteOffset(0) +{ + MOZ_ASSERT(aData || !mSize); + + mData = new uint8_t[mSize]; + memcpy(mData, aData, mSize); +} + +// +// SocketConsumerBase +// + +SocketConsumerBase::~SocketConsumerBase() +{ + MOZ_ASSERT(mConnectionStatus == SOCKET_DISCONNECTED); +} + +SocketConnectionStatus +SocketConsumerBase::GetConnectionStatus() const +{ + MOZ_ASSERT(NS_IsMainThread()); + + return mConnectionStatus; +} + +int +SocketConsumerBase::GetSuggestedConnectDelayMs() const +{ + MOZ_ASSERT(NS_IsMainThread()); + + return mConnectDelayMs; +} + +void +SocketConsumerBase::NotifySuccess() +{ + MOZ_ASSERT(NS_IsMainThread()); + + mConnectionStatus = SOCKET_CONNECTED; + mConnectTimestamp = PR_IntervalNow(); + OnConnectSuccess(); +} + +void +SocketConsumerBase::NotifyError() +{ + MOZ_ASSERT(NS_IsMainThread()); + + mConnectionStatus = SOCKET_DISCONNECTED; + mConnectDelayMs = CalculateConnectDelayMs(); + OnConnectError(); +} + +void +SocketConsumerBase::NotifyDisconnect() +{ + MOZ_ASSERT(NS_IsMainThread()); + + mConnectionStatus = SOCKET_DISCONNECTED; + mConnectDelayMs = CalculateConnectDelayMs(); + OnDisconnect(); +} + +uint32_t +SocketConsumerBase::CalculateConnectDelayMs() const +{ + MOZ_ASSERT(NS_IsMainThread()); + + uint32_t connectDelayMs = mConnectDelayMs; + + if ((PR_IntervalNow()-mConnectTimestamp) > connectDelayMs) { + // reset delay if connection has been opened for a while, or... + connectDelayMs = 0; + } else if (!connectDelayMs) { + // ...start with a delay of ~1 sec, or... + connectDelayMs = 1<<10; + } else if (connectDelayMs < (1<<16)) { + // ...otherwise increase delay by a factor of 2 + connectDelayMs <<= 1; + } + return connectDelayMs; +} + +SocketConsumerBase::SocketConsumerBase() +: mConnectionStatus(SOCKET_DISCONNECTED) +, mConnectTimestamp(0) +, mConnectDelayMs(0) +{ } + +void +SocketConsumerBase::SetConnectionStatus( + SocketConnectionStatus aConnectionStatus) +{ + mConnectionStatus = aConnectionStatus; +} + +} +} diff --git a/ipc/unixsocket/SocketBase.h b/ipc/unixsocket/SocketBase.h new file mode 100644 index 00000000000..afabd89c584 --- /dev/null +++ b/ipc/unixsocket/SocketBase.h @@ -0,0 +1,135 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* 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/. + */ + +#ifndef mozilla_ipc_SocketBase_h +#define mozilla_ipc_SocketBase_h + +#include "nsAutoPtr.h" + +namespace mozilla { +namespace ipc { + +// +// UnixSocketRawData +// + +class UnixSocketRawData +{ +public: + // Number of octets in mData. + size_t mSize; + size_t mCurrentWriteOffset; + nsAutoArrayPtr mData; + + /** + * Constructor for situations where only size is known beforehand + * (for example, when being assigned strings) + */ + UnixSocketRawData(size_t aSize); + + /** + * Constructor for situations where size and data is known + * beforehand (for example, when being assigned strings) + */ + UnixSocketRawData(const void* aData, size_t aSize); +}; + +enum SocketConnectionStatus { + SOCKET_DISCONNECTED = 0, + SOCKET_LISTENING = 1, + SOCKET_CONNECTING = 2, + SOCKET_CONNECTED = 3 +}; + +// +// SocketConsumerBase +// + +class SocketConsumerBase +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SocketConsumerBase) + + virtual ~SocketConsumerBase(); + + SocketConnectionStatus GetConnectionStatus() const; + + int GetSuggestedConnectDelayMs() const; + + /** + * Queues the internal representation of socket for deletion. Can be called + * from main thread. + */ + virtual void CloseSocket() = 0; + + /** + * Function to be called whenever data is received. This is only called on the + * main thread. + * + * @param aMessage Data received from the socket. + */ + virtual void ReceiveSocketData(nsAutoPtr& aMessage) = 0; + + /** + * Queue data to be sent to the socket on the IO thread. Can only be called on + * originating thread. + * + * @param aMessage Data to be sent to socket + * + * @return true if data is queued, false otherwise (i.e. not connected) + */ + virtual bool SendSocketData(UnixSocketRawData* aMessage) = 0; + + /** + * Callback for socket connect/accept success. Called after connect/accept has + * finished. Will be run on main thread, before any reads take place. + */ + virtual void OnConnectSuccess() = 0; + + /** + * Callback for socket connect/accept error. Will be run on main thread. + */ + virtual void OnConnectError() = 0; + + /** + * Callback for socket disconnect. Will be run on main thread. + */ + virtual void OnDisconnect() = 0; + + /** + * Called by implementation to notify consumer of success. + */ + void NotifySuccess(); + + /** + * Called by implementation to notify consumer of error. + */ + void NotifyError(); + + /** + * Called by implementation to notify consumer of disconnect. + */ + void NotifyDisconnect(); + +protected: + SocketConsumerBase(); + + void SetConnectionStatus(SocketConnectionStatus aConnectionStatus); + +private: + uint32_t CalculateConnectDelayMs() const; + + SocketConnectionStatus mConnectionStatus; + PRIntervalTime mConnectTimestamp; + uint32_t mConnectDelayMs; +}; + +} +} + +#endif diff --git a/ipc/unixsocket/UnixSocket.cpp b/ipc/unixsocket/UnixSocket.cpp index 06465d36309..14f0a7d3083 100644 --- a/ipc/unixsocket/UnixSocket.cpp +++ b/ipc/unixsocket/UnixSocket.cpp @@ -19,6 +19,10 @@ static const size_t MAX_READ_SIZE = 1 << 16; namespace mozilla { namespace ipc { +// +// UnixSocketImpl +// + class UnixSocketImpl : public UnixSocketWatcher { public: @@ -740,16 +744,16 @@ UnixSocketImpl::OnSocketCanSendWithoutBlocking() } } -UnixSocketConsumer::UnixSocketConsumer() : mImpl(nullptr) - , mConnectionStatus(SOCKET_DISCONNECTED) - , mConnectTimestamp(0) - , mConnectDelayMs(0) -{ -} +// +// UnixSocketConsumer +// + +UnixSocketConsumer::UnixSocketConsumer() +: mImpl(nullptr) +{ } UnixSocketConsumer::~UnixSocketConsumer() { - MOZ_ASSERT(mConnectionStatus == SOCKET_DISCONNECTED); MOZ_ASSERT(!mImpl); } @@ -813,40 +817,13 @@ void UnixSocketConsumer::GetSocketAddr(nsAString& aAddrStr) { aAddrStr.Truncate(); - if (!mImpl || mConnectionStatus != SOCKET_CONNECTED) { + if (!mImpl || GetConnectionStatus() != SOCKET_CONNECTED) { NS_WARNING("No socket currently open!"); return; } mImpl->GetSocketAddr(aAddrStr); } -void -UnixSocketConsumer::NotifySuccess() -{ - MOZ_ASSERT(NS_IsMainThread()); - mConnectionStatus = SOCKET_CONNECTED; - mConnectTimestamp = PR_IntervalNow(); - OnConnectSuccess(); -} - -void -UnixSocketConsumer::NotifyError() -{ - MOZ_ASSERT(NS_IsMainThread()); - mConnectionStatus = SOCKET_DISCONNECTED; - mConnectDelayMs = CalculateConnectDelayMs(); - OnConnectError(); -} - -void -UnixSocketConsumer::NotifyDisconnect() -{ - MOZ_ASSERT(NS_IsMainThread()); - mConnectionStatus = SOCKET_DISCONNECTED; - mConnectDelayMs = CalculateConnectDelayMs(); - OnDisconnect(); -} - bool UnixSocketConsumer::ConnectSocket(UnixSocketConnector* aConnector, const char* aAddress, @@ -865,7 +842,7 @@ UnixSocketConsumer::ConnectSocket(UnixSocketConnector* aConnector, nsCString addr(aAddress); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); mImpl = new UnixSocketImpl(ioLoop, this, connector.forget(), addr); - mConnectionStatus = SOCKET_CONNECTING; + SetConnectionStatus(SOCKET_CONNECTING); if (aDelayMs > 0) { SocketDelayedConnectTask* connectTask = new SocketDelayedConnectTask(mImpl); mImpl->SetDelayedConnectTask(connectTask); @@ -891,31 +868,11 @@ UnixSocketConsumer::ListenSocket(UnixSocketConnector* aConnector) mImpl = new UnixSocketImpl(XRE_GetIOMessageLoop(), this, connector.forget(), EmptyCString()); - mConnectionStatus = SOCKET_LISTENING; + SetConnectionStatus(SOCKET_LISTENING); XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketListenTask(mImpl)); return true; } -uint32_t -UnixSocketConsumer::CalculateConnectDelayMs() const -{ - MOZ_ASSERT(NS_IsMainThread()); - - uint32_t connectDelayMs = mConnectDelayMs; - - if ((PR_IntervalNow()-mConnectTimestamp) > connectDelayMs) { - // reset delay if connection has been opened for a while, or... - connectDelayMs = 0; - } else if (!connectDelayMs) { - // ...start with a delay of ~1 sec, or... - connectDelayMs = 1<<10; - } else if (connectDelayMs < (1<<16)) { - // ...otherwise increase delay by a factor of 2 - connectDelayMs <<= 1; - } - return connectDelayMs; -} - } // namespace ipc } // namespace mozilla diff --git a/ipc/unixsocket/UnixSocket.h b/ipc/unixsocket/UnixSocket.h index 7e643906fc2..b353f50bbb8 100644 --- a/ipc/unixsocket/UnixSocket.h +++ b/ipc/unixsocket/UnixSocket.h @@ -7,50 +7,17 @@ #ifndef mozilla_ipc_UnixSocket_h #define mozilla_ipc_UnixSocket_h - #include #include "nsAutoPtr.h" #include "nsString.h" #include "nsThreadUtils.h" #include "mozilla/ipc/UnixSocketWatcher.h" +#include "mozilla/ipc/SocketBase.h" #include "mozilla/RefPtr.h" namespace mozilla { namespace ipc { -class UnixSocketRawData -{ -public: - // Number of octets in mData. - size_t mSize; - size_t mCurrentWriteOffset; - nsAutoArrayPtr mData; - - /** - * Constructor for situations where only size is known beforehand - * (for example, when being assigned strings) - */ - UnixSocketRawData(size_t aSize) : - mSize(aSize), - mCurrentWriteOffset(0) - { - mData = new uint8_t[mSize]; - } - - /** - * Constructor for situations where size and data is known - * beforehand (for example, when being assigned strings) - */ - UnixSocketRawData(const void* aData, size_t aSize) - : mSize(aSize), - mCurrentWriteOffset(0) - { - MOZ_ASSERT(aData || !mSize); - mData = new uint8_t[mSize]; - memcpy(mData, aData, mSize); - } -}; - class UnixSocketImpl; /** @@ -128,43 +95,14 @@ public: }; -enum SocketConnectionStatus { - SOCKET_DISCONNECTED = 0, - SOCKET_LISTENING = 1, - SOCKET_CONNECTING = 2, - SOCKET_CONNECTED = 3 -}; - -class UnixSocketConsumer +class UnixSocketConsumer : public SocketConsumerBase { protected: virtual ~UnixSocketConsumer(); public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UnixSocketConsumer) - UnixSocketConsumer(); - SocketConnectionStatus GetConnectionStatus() const - { - MOZ_ASSERT(NS_IsMainThread()); - return mConnectionStatus; - } - - int GetSuggestedConnectDelayMs() const - { - MOZ_ASSERT(NS_IsMainThread()); - return mConnectDelayMs; - } - - /** - * Function to be called whenever data is received. This is only called on the - * main thread. - * - * @param aMessage Data received from the socket. - */ - virtual void ReceiveSocketData(nsAutoPtr& aMessage) = 0; - /** * Queue data to be sent to the socket on the IO thread. Can only be called on * originating thread. @@ -216,49 +154,13 @@ public: */ void CloseSocket(); - /** - * Callback for socket connect/accept success. Called after connect/accept has - * finished. Will be run on main thread, before any reads take place. - */ - virtual void OnConnectSuccess() = 0; - - /** - * Callback for socket connect/accept error. Will be run on main thread. - */ - virtual void OnConnectError() = 0; - - /** - * Callback for socket disconnect. Will be run on main thread. - */ - virtual void OnDisconnect() = 0; - - /** - * Called by implementation to notify consumer of success. - */ - void NotifySuccess(); - - /** - * Called by implementation to notify consumer of error. - */ - void NotifyError(); - - /** - * Called by implementation to notify consumer of disconnect. - */ - void NotifyDisconnect(); - /** * Get the current sockaddr for the socket */ void GetSocketAddr(nsAString& aAddrStr); private: - uint32_t CalculateConnectDelayMs() const; - UnixSocketImpl* mImpl; - SocketConnectionStatus mConnectionStatus; - PRIntervalTime mConnectTimestamp; - uint32_t mConnectDelayMs; }; } // namespace ipc diff --git a/ipc/unixsocket/moz.build b/ipc/unixsocket/moz.build index 68a0d245a65..7c365f720da 100644 --- a/ipc/unixsocket/moz.build +++ b/ipc/unixsocket/moz.build @@ -5,11 +5,13 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS.mozilla.ipc += [ - 'UnixSocket.h', + 'SocketBase.h', + 'UnixSocket.h' ] SOURCES += [ - 'UnixSocket.cpp', + 'SocketBase.cpp', + 'UnixSocket.cpp' ] FAIL_ON_WARNINGS = True