Bug 1170466: Implement accept and connect in |ConnectionOrientedSocketIO|, r=kmachulis
authorThomas Zimmermann <tdz@users.sourceforge.net>
Wed, 03 Jun 2015 11:53:50 +0200
changeset 246913 eecddaa2cc3c5348976886c87bc32b3b22eeee02
parent 246912 3bd34542b7c17a1c8361bd20a1e8dced96721e31
child 246914 86ab6cc5a3ae6ae92d7924d96f57a9df3d615755
push id28846
push userryanvm@gmail.com
push dateWed, 03 Jun 2015 19:51:00 +0000
treeherdermozilla-central@e5ee2c56963c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmachulis
bugs1170466
milestone41.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 1170466: Implement accept and connect in |ConnectionOrientedSocketIO|, r=kmachulis |ConnectionOrientedSocketIO| now handles accepting and connecting sockets. All sub-classes have been changed accordingly.
ipc/bluetooth/BluetoothDaemonConnection.cpp
ipc/unixsocket/ConnectionOrientedSocket.cpp
ipc/unixsocket/ConnectionOrientedSocket.h
ipc/unixsocket/StreamSocket.cpp
--- a/ipc/bluetooth/BluetoothDaemonConnection.cpp
+++ b/ipc/bluetooth/BluetoothDaemonConnection.cpp
@@ -7,17 +7,16 @@
 #include "BluetoothDaemonConnection.h"
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
 #include <unistd.h>
 #include "mozilla/ipc/BluetoothDaemonConnectionConsumer.h"
 #include "mozilla/ipc/DataSocket.h"
-#include "mozilla/ipc/UnixSocketConnector.h"
 #include "nsTArray.h"
 #include "nsXULAppAPI.h"
 
 #ifdef CHROMIUM_LOG
 #undef CHROMIUM_LOG
 #endif
 
 #if defined(MOZ_WIDGET_GONK)
@@ -201,26 +200,20 @@ BluetoothDaemonPDUConsumer::~BluetoothDa
 //
 
 class BluetoothDaemonConnectionIO final : public ConnectionOrientedSocketIO
 {
 public:
   BluetoothDaemonConnectionIO(nsIThread* aConsumerThread,
                               MessageLoop* aIOLoop,
                               int aFd, ConnectionStatus aConnectionStatus,
+                              UnixSocketConnector* aConnector,
                               BluetoothDaemonConnection* aConnection,
                               BluetoothDaemonPDUConsumer* aConsumer);
 
-  // Methods for |ConnectionOrientedSocketIO|
-  //
-
-  nsresult Accept(int aFd,
-                  const struct sockaddr* aAddress,
-                  socklen_t aAddressLength) override;
-
   // Methods for |DataSocketIO|
   //
 
   nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override;
   void ConsumeBuffer() override;
   void DiscardBuffer() override;
 
   // Methods for |SocketIOBase|
@@ -241,56 +234,32 @@ private:
   bool mShuttingDownOnIOThread;
 };
 
 BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
   nsIThread* aConsumerThread,
   MessageLoop* aIOLoop,
   int aFd,
   ConnectionStatus aConnectionStatus,
+  UnixSocketConnector* aConnector,
   BluetoothDaemonConnection* aConnection,
   BluetoothDaemonPDUConsumer* aConsumer)
   : ConnectionOrientedSocketIO(aConsumerThread,
                                aIOLoop,
                                aFd,
-                               aConnectionStatus)
+                               aConnectionStatus,
+                               aConnector)
   , mConnection(aConnection)
   , mConsumer(aConsumer)
   , mShuttingDownOnIOThread(false)
 {
   MOZ_ASSERT(mConnection);
   MOZ_ASSERT(mConsumer);
 }
 
-// |ConnectionOrientedSocketIO|
-
-nsresult
-BluetoothDaemonConnectionIO::Accept(int aFd,
-                                    const struct sockaddr* aAddress,
-                                    socklen_t aAddressLength)
-{
-  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
-  MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
-
-  // File-descriptor setup
-
-  if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) {
-    OnError("fcntl", errno);
-    ScopedClose cleanupFd(aFd);
-    return NS_ERROR_FAILURE;
-  }
-
-  SetSocket(aFd, SOCKET_IS_CONNECTED);
-
-  // Signal success
-  OnConnected();
-
-  return NS_OK;
-}
-
 // |DataSocketIO|
 
 nsresult
 BluetoothDaemonConnectionIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
 {
   MOZ_ASSERT(aBuffer);
 
   if (!mPDU) {
@@ -381,26 +350,21 @@ BluetoothDaemonConnection::~BluetoothDae
 nsresult
 BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
                                          nsIThread* aConsumerThread,
                                          MessageLoop* aIOLoop,
                                          ConnectionOrientedSocketIO*& aIO)
 {
   MOZ_ASSERT(!mIO);
 
-  // |BluetoothDaemonConnection| now owns the connector, but doesn't
-  // actually use it. So the connector is stored in an auto pointer
-  // to be deleted at the end of the method.
-  nsAutoPtr<UnixSocketConnector> connector(aConnector);
-
   SetConnectionStatus(SOCKET_CONNECTING);
 
   mIO = new BluetoothDaemonConnectionIO(
     aConsumerThread, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
-    this, mPDUConsumer);
+    aConnector, this, mPDUConsumer);
   aIO = mIO;
 
   return NS_OK;
 }
 
 // |DataSocket|
 
 void
--- a/ipc/unixsocket/ConnectionOrientedSocket.cpp
+++ b/ipc/unixsocket/ConnectionOrientedSocket.cpp
@@ -1,42 +1,107 @@
 /* -*- 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 "ConnectionOrientedSocket.h"
+#include "UnixSocketConnector.h"
 
 namespace mozilla {
 namespace ipc {
 
 //
 // ConnectionOrientedSocketIO
 //
 
 ConnectionOrientedSocketIO::ConnectionOrientedSocketIO(
   nsIThread* aConsumerThread,
   MessageLoop* aIOLoop,
   int aFd,
-  ConnectionStatus aConnectionStatus)
+  ConnectionStatus aConnectionStatus,
+  UnixSocketConnector* aConnector)
   : DataSocketIO(aConsumerThread)
   , UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
-{ }
+  , mConnector(aConnector)
+  , mPeerAddressLength(0)
+{
+  MOZ_ASSERT(mConnector);
+}
 
 ConnectionOrientedSocketIO::ConnectionOrientedSocketIO(
   nsIThread* aConsumerThread,
-  MessageLoop* aIOLoop)
+  MessageLoop* aIOLoop,
+  UnixSocketConnector* aConnector)
   : DataSocketIO(aConsumerThread)
   , UnixSocketWatcher(aIOLoop)
-{ }
+  , mConnector(aConnector)
+  , mPeerAddressLength(0)
+{
+  MOZ_ASSERT(mConnector);
+}
 
 ConnectionOrientedSocketIO::~ConnectionOrientedSocketIO()
 { }
 
+nsresult
+ConnectionOrientedSocketIO::Accept(int aFd,
+                                   const struct sockaddr* aPeerAddress,
+                                   socklen_t aPeerAddressLength)
+{
+  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
+  MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
+
+  SetSocket(aFd, SOCKET_IS_CONNECTED);
+
+  // Address setup
+  mPeerAddressLength = aPeerAddressLength;
+  memcpy(&mPeerAddress, aPeerAddress, mPeerAddressLength);
+
+  // Signal success and start data transfer
+  OnConnected();
+
+  return NS_OK;
+}
+
+nsresult
+ConnectionOrientedSocketIO::Connect()
+{
+  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
+  MOZ_ASSERT(!IsOpen());
+
+  struct sockaddr* peerAddress =
+    reinterpret_cast<struct sockaddr*>(&mPeerAddress);
+  mPeerAddressLength = sizeof(mPeerAddress);
+
+  int fd;
+  nsresult rv = mConnector->CreateStreamSocket(peerAddress,
+                                               &mPeerAddressLength,
+                                               fd);
+  if (NS_FAILED(rv)) {
+    // Tell the consumer thread we've errored
+    GetConsumerThread()->Dispatch(
+      new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
+      NS_DISPATCH_NORMAL);
+    return NS_ERROR_FAILURE;
+  }
+
+  SetFd(fd);
+
+  // calls OnConnected() on success, or OnError() otherwise
+  rv = UnixSocketWatcher::Connect(peerAddress, mPeerAddressLength);
+
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
 void
 ConnectionOrientedSocketIO::Send(UnixSocketIOBuffer* aBuffer)
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
 
   EnqueueData(aBuffer);
   AddWatchers(WRITE_WATCHER, false);
 }
--- a/ipc/unixsocket/ConnectionOrientedSocket.h
+++ b/ipc/unixsocket/ConnectionOrientedSocket.h
@@ -26,19 +26,21 @@ class UnixSocketConnector;
 
 class ConnectionOrientedSocketIO
   : public DataSocketIO
   , public UnixSocketWatcher
 {
 public:
   virtual ~ConnectionOrientedSocketIO();
 
-  virtual nsresult Accept(int aFd,
-                          const struct sockaddr* aAddress,
-                          socklen_t aAddressLength) = 0;
+  nsresult Accept(int aFd,
+                  const struct sockaddr* aAddress,
+                  socklen_t aAddressLength);
+
+  nsresult Connect();
 
   void Send(UnixSocketIOBuffer* aBuffer);
 
   // Methods for |UnixSocketWatcher|
   //
 
   void OnSocketCanReceiveWithoutBlocking() final;
   void OnSocketCanSendWithoutBlocking() final;
@@ -50,29 +52,49 @@ public:
 protected:
   /**
    * Constructs an instance of |ConnectionOrientedSocketIO|
    *
    * @param aConsumerThread The socket's consumer thread.
    * @param aIOLoop The socket's I/O loop.
    * @param aFd The socket file descriptor.
    * @param aConnectionStatus The connection status for |aFd|.
+   * @param aConnector Connector object for socket-type-specific methods.
    */
   ConnectionOrientedSocketIO(nsIThread* aConsumerThread,
                              MessageLoop* aIOLoop,
-                             int aFd, ConnectionStatus aConnectionStatus);
+                             int aFd, ConnectionStatus aConnectionStatus,
+                             UnixSocketConnector* aConnector);
 
   /**
    * Constructs an instance of |ConnectionOrientedSocketIO|
    *
    * @param aConsumerThread The socket's consumer thread.
    * @param aIOLoop The socket's I/O loop.
+   * @param aConnector Connector object for socket-type-specific methods.
    */
   ConnectionOrientedSocketIO(nsIThread* aConsumerThread,
-                             MessageLoop* aIOLoop);
+                             MessageLoop* aIOLoop,
+                             UnixSocketConnector* aConnector);
+
+private:
+  /**
+   * Connector object used to create the connection we are currently using.
+   */
+  nsAutoPtr<UnixSocketConnector> mConnector;
+
+  /**
+   * Number of valid bytes in |mPeerAddress|.
+   */
+  socklen_t mPeerAddressLength;
+
+  /**
+   * Address of the socket's current peer.
+   */
+  struct sockaddr_storage mPeerAddress;
 };
 
 class ConnectionOrientedSocket : public DataSocket
 {
 public:
   /**
    * Prepares an instance of |ConnectionOrientedSocket| in DISCONNECTED
    * state for accepting a connection. Consumer-thread only.
--- a/ipc/unixsocket/StreamSocket.cpp
+++ b/ipc/unixsocket/StreamSocket.cpp
@@ -43,31 +43,16 @@ public:
 
   // Delayed-task handling
   //
 
   void SetDelayedConnectTask(CancelableTask* aTask);
   void ClearDelayedConnectTask();
   void CancelDelayedConnectTask();
 
-  // Task callback methods
-  //
-
-  /**
-   * Connect to a socket
-   */
-  void Connect();
-
-  // Methods for |ConnectionOrientedSocketIO|
-  //
-
-  nsresult Accept(int aFd,
-                  const struct sockaddr* aAddress,
-                  socklen_t aAddressLength) override;
-
   // Methods for |DataSocket|
   //
 
   nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override;
   void ConsumeBuffer() override;
   void DiscardBuffer() override;
 
   // Methods for |SocketIOBase|
@@ -77,89 +62,67 @@ public:
 
   bool IsShutdownOnConsumerThread() const override;
   bool IsShutdownOnIOThread() const override;
 
   void ShutdownOnConsumerThread() override;
   void ShutdownOnIOThread() override;
 
 private:
-  void FireSocketError();
-
   /**
    * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
    * directly from consumer thread. All non-consumer-thread accesses should
    * happen with mIO as container.
    */
   RefPtr<StreamSocket> mStreamSocket;
 
   /**
-   * Connector object used to create the connection we are currently using.
-   */
-  nsAutoPtr<UnixSocketConnector> mConnector;
-
-  /**
    * If true, do not requeue whatever task we're running
    */
   bool mShuttingDownOnIOThread;
 
   /**
-   * Number of valid bytes in |mAddress|
-   */
-  socklen_t mAddressLength;
-
-  /**
-   * Address structure of the socket currently in use
-   */
-  struct sockaddr_storage mAddress;
-
-  /**
    * Task member for delayed connect task. Should only be access on consumer
    * thread.
    */
   CancelableTask* mDelayedConnectTask;
 
   /**
    * I/O buffer for received data
    */
   nsAutoPtr<UnixSocketRawData> mBuffer;
 };
 
 StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
                                MessageLoop* aIOLoop,
                                StreamSocket* aStreamSocket,
                                UnixSocketConnector* aConnector)
-  : ConnectionOrientedSocketIO(aConsumerThread, aIOLoop)
+  : ConnectionOrientedSocketIO(aConsumerThread, aIOLoop, aConnector)
   , mStreamSocket(aStreamSocket)
-  , mConnector(aConnector)
   , mShuttingDownOnIOThread(false)
-  , mAddressLength(0)
   , mDelayedConnectTask(nullptr)
 {
   MOZ_ASSERT(mStreamSocket);
-  MOZ_ASSERT(mConnector);
 }
 
 StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
                                MessageLoop* aIOLoop,
                                int aFd, ConnectionStatus aConnectionStatus,
                                StreamSocket* aStreamSocket,
                                UnixSocketConnector* aConnector)
   : ConnectionOrientedSocketIO(aConsumerThread,
                                aIOLoop,
                                aFd,
-                               aConnectionStatus)
+                               aConnectionStatus,
+                               aConnector)
   , mStreamSocket(aStreamSocket)
-  , mConnector(aConnector)
   , mShuttingDownOnIOThread(false)
-  , mAddressLength(0)
   , mDelayedConnectTask(nullptr)
 {
   MOZ_ASSERT(mStreamSocket);
-  MOZ_ASSERT(mConnector);
 }
 
 StreamSocketIO::~StreamSocketIO()
 {
   MOZ_ASSERT(IsConsumerThread());
   MOZ_ASSERT(IsShutdownOnConsumerThread());
 }
 
@@ -199,83 +162,16 @@ StreamSocketIO::CancelDelayedConnectTask
   if (!mDelayedConnectTask) {
     return;
   }
 
   mDelayedConnectTask->Cancel();
   ClearDelayedConnectTask();
 }
 
-void
-StreamSocketIO::Connect()
-{
-  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
-  MOZ_ASSERT(mConnector);
-
-  MOZ_ASSERT(!IsOpen());
-
-  struct sockaddr* address = reinterpret_cast<struct sockaddr*>(&mAddress);
-  mAddressLength = sizeof(mAddress);
-
-  int fd;
-  nsresult rv = mConnector->CreateStreamSocket(address, &mAddressLength, fd);
-  if (NS_FAILED(rv)) {
-    FireSocketError();
-    return;
-  }
-  SetFd(fd);
-
-  // calls OnConnected() on success, or OnError() otherwise
-  rv = UnixSocketWatcher::Connect(address, mAddressLength);
-  NS_WARN_IF(NS_FAILED(rv));
-}
-
-void
-StreamSocketIO::FireSocketError()
-{
-  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
-
-  // Clean up watchers, statuses, fds
-  Close();
-
-  // Tell the consumer thread we've errored
-  GetConsumerThread()->Dispatch(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
-    NS_DISPATCH_NORMAL);
-}
-
-// |ConnectionOrientedSocketIO|
-
-nsresult
-StreamSocketIO::Accept(int aFd,
-                       const struct sockaddr* aAddress,
-                       socklen_t aAddressLength)
-{
-  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
-  MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
-
-  SetSocket(aFd, SOCKET_IS_CONNECTED);
-
-  // Address setup
-  mAddressLength = aAddressLength;
-  memcpy(&mAddress, aAddress, mAddressLength);
-
-  // Signal success
-  GetConsumerThread()->Dispatch(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
-    NS_DISPATCH_NORMAL);
-
-  AddWatchers(READ_WATCHER, true);
-  if (HasPendingData()) {
-    AddWatchers(WRITE_WATCHER, false);
-  }
-
-  return NS_OK;
-}
-
 // |DataSocketIO|
 
 nsresult
 StreamSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
 {
   MOZ_ASSERT(aBuffer);
 
   if (!mBuffer) {