Bug 1046109: Add |SocketConsumerBase| and inherit |UnixSocketConsumer| from it, r=kyle
☠☠ backed out by 24b6b4da7893 ☠ ☠
authorThomas Zimmermann <tdz@users.sourceforge.net>
Thu, 31 Jul 2014 09:29:17 +0200
changeset 197076 56a5acbceadbd4ae6d742ba8382e7ca5fdaf0e25
parent 197075 43156be71b3b5ae35dfd0856b66695c7010e9b7b
child 197077 ddb118aa2648de18301ee25a6acd1b278b059e30
push id27231
push userryanvm@gmail.com
push dateThu, 31 Jul 2014 19:54:16 +0000
treeherdermozilla-central@17396ce2587d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskyle
bugs1046109
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1046109: Add |SocketConsumerBase| and inherit |UnixSocketConsumer| from it, r=kyle |SocketConsumerBase| handles connection state for |UnixSocketConsumer| and its derived classes. Implementing classes must override a number of virtual methods, to handle notifications about changes to the state of the connection.
ipc/unixsocket/SocketBase.cpp
ipc/unixsocket/SocketBase.h
ipc/unixsocket/UnixSocket.cpp
ipc/unixsocket/UnixSocket.h
ipc/unixsocket/moz.build
new file mode 100644
--- /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 <string.h>
+#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;
+}
+
+}
+}
new file mode 100644
--- /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<uint8_t> 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<UnixSocketRawData>& 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
--- a/ipc/unixsocket/UnixSocket.cpp
+++ b/ipc/unixsocket/UnixSocket.cpp
@@ -14,16 +14,20 @@
 using namespace mozilla::tasktracer;
 #endif
 
 static const size_t MAX_READ_SIZE = 1 << 16;
 
 namespace mozilla {
 namespace ipc {
 
+//
+// UnixSocketImpl
+//
+
 class UnixSocketImpl : public UnixSocketWatcher
 {
 public:
   UnixSocketImpl(MessageLoop* mIOLoop,
                  UnixSocketConsumer* aConsumer, UnixSocketConnector* aConnector,
                  const nsACString& aAddress)
     : UnixSocketWatcher(mIOLoop)
     , mConsumer(aConsumer)
@@ -735,26 +739,26 @@ UnixSocketImpl::OnSocketCanSendWithoutBl
       AddWatchers(WRITE_WATCHER, false);
       return;
     }
     mOutgoingQ.RemoveElementAt(0);
     delete data;
   }
 }
 
-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);
 }
 
 bool
 UnixSocketConsumer::SendSocketData(UnixSocketRawData* aData)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!mImpl) {
@@ -808,50 +812,23 @@ UnixSocketConsumer::CloseSocket()
 
   NotifyDisconnect();
 }
 
 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,
                                   int aDelayMs)
 {
   MOZ_ASSERT(aConnector);
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -860,17 +837,17 @@ UnixSocketConsumer::ConnectSocket(UnixSo
   if (mImpl) {
     NS_WARNING("Socket already connecting/connected!");
     return false;
   }
 
   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);
     MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
   } else {
     ioLoop->PostTask(FROM_HERE, new SocketConnectTask(mImpl));
   }
   return true;
@@ -886,36 +863,16 @@ UnixSocketConsumer::ListenSocket(UnixSoc
 
   if (mImpl) {
     NS_WARNING("Socket already connecting/connected!");
     return false;
   }
 
   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
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -2,60 +2,27 @@
 /* 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_UnixSocket_h
 #define mozilla_ipc_UnixSocket_h
 
-
 #include <stdlib.h>
 #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<uint8_t> 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;
 
 /**
  * UnixSocketConnector defines the socket creation and connection/listening
  * functions for a UnixSocketConsumer. Due to the fact that socket setup can
  * vary between protocols (unix sockets, tcp sockets, bluetooth sockets, etc),
  * this allows the user to create whatever connection mechanism they need while
  * still depending on libevent for non-blocking communication handling.
@@ -123,53 +90,24 @@ public:
    * @param aAddr Address struct
    * @param aAddrStr String to store address to
    */
   virtual void GetSocketAddr(const sockaddr_any& aAddr,
                              nsAString& aAddrStr) = 0;
 
 };
 
-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<UnixSocketRawData>& 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)
    */
@@ -212,56 +150,20 @@ public:
 
   /**
    * Queues the internal representation of socket for deletion. Can be called
    * from main thread.
    */
   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
 } // namepsace mozilla
 
 #endif // mozilla_ipc_Socket_h
--- a/ipc/unixsocket/moz.build
+++ b/ipc/unixsocket/moz.build
@@ -1,19 +1,21 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS.mozilla.ipc += [
-    'UnixSocket.h',
+    'SocketBase.h',
+    'UnixSocket.h'
 ]
 
 SOURCES += [
-    'UnixSocket.cpp',
+    'SocketBase.cpp',
+    'UnixSocket.cpp'
 ]
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'