Bug 1161020: Implement new socket-connector interface for Bluetooth daemon socket, r=shuang
authorThomas Zimmermann <tdz@users.sourceforge.net>
Tue, 19 May 2015 13:28:46 +0200
changeset 244452 b8c39f01f5f4780b3b77cc2cc0c3572b555c4794
parent 244451 85939a63419fe98cf95a23cfb1272f469d7914f6
child 244453 854336cbcbb9ebd49ebdcf8085345de48b742bf5
push id15662
push usertdz@users.sourceforge.net
push dateTue, 19 May 2015 11:28:50 +0000
treeherderb2g-inbound@3529de81a668 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshuang
bugs1161020
milestone41.0a1
Bug 1161020: Implement new socket-connector interface for Bluetooth daemon socket, r=shuang This patch moves |BluetoothDaemonSocketConnector| into its own file, renames it to |BluetoothDaemonConnector| and implements the new socket- connector interface.
dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp
dom/bluetooth/bluedroid/BluetoothDaemonConnector.h
dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
dom/bluetooth/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp
@@ -0,0 +1,237 @@
+/* -*- 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 "BluetoothDaemonConnector.h"
+#include <fcntl.h>
+#include "nsThreadUtils.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+BluetoothDaemonConnector::BluetoothDaemonConnector(
+  const nsACString& aSocketName)
+  : mSocketName(aSocketName)
+{ }
+
+BluetoothDaemonConnector::~BluetoothDaemonConnector()
+{ }
+
+nsresult
+BluetoothDaemonConnector::CreateSocket(int& aFd) const
+{
+  aFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+  if (aFd < 0) {
+    BT_WARNING("Could not open Bluetooth daemon socket!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonConnector::SetSocketFlags(int aFd) const
+{
+  static const int sReuseAddress = 1;
+
+  // Set close-on-exec bit.
+  int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFD));
+  if (flags < 0) {
+    return NS_ERROR_FAILURE;
+  }
+  flags |= FD_CLOEXEC;
+  int res = TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFD, flags));
+  if (res < 0) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Set non-blocking status flag.
+  flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL));
+  if (flags < 0) {
+    return NS_ERROR_FAILURE;
+  }
+  flags |= O_NONBLOCK;
+  res = TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, flags));
+  if (res < 0) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Set socket addr to be reused even if kernel is still waiting to close.
+  res = setsockopt(aFd, SOL_SOCKET, SO_REUSEADDR, &sReuseAddress,
+                   sizeof(sReuseAddress));
+  if (res < 0) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonConnector::CreateAddress(struct sockaddr& aAddress,
+                                        socklen_t& aAddressLength) const
+{
+  static const size_t sNameOffset = 1;
+
+  struct sockaddr_un* address =
+    reinterpret_cast<struct sockaddr_un*>(&aAddress);
+
+  size_t namesiz = mSocketName.Length() + 1; // include trailing '\0'
+
+  if (NS_WARN_IF((sNameOffset + namesiz) > sizeof(address->sun_path))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  address->sun_family = AF_UNIX;
+  memset(address->sun_path, '\0', sNameOffset); // abstract socket
+  memcpy(address->sun_path + sNameOffset, mSocketName.get(), namesiz);
+
+  aAddressLength =
+    offsetof(struct sockaddr_un, sun_path) + sNameOffset + namesiz;
+
+  return NS_OK;
+}
+
+// |UnixSocketConnector|
+
+nsresult
+BluetoothDaemonConnector::ConvertAddressToString(
+  const struct sockaddr& aAddress, socklen_t aAddressLength,
+  nsACString& aAddressString)
+{
+  MOZ_ASSERT(aAddress.sa_family == AF_UNIX);
+
+  const struct sockaddr_un* un =
+    reinterpret_cast<const struct sockaddr_un*>(&aAddress);
+
+  size_t len = aAddressLength - offsetof(struct sockaddr_un, sun_path);
+
+  aAddressString.Assign(un->sun_path, len);
+
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonConnector::CreateListenSocket(struct sockaddr* aAddress,
+                                             socklen_t* aAddressLength,
+                                             int& aListenFd)
+{
+  ScopedClose fd;
+
+  nsresult rv = CreateSocket(fd.rwget());
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = SetSocketFlags(fd);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  if (aAddress && aAddressLength) {
+    rv = CreateAddress(*aAddress, *aAddressLength);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  }
+
+  aListenFd = fd.forget();
+
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonConnector::AcceptStreamSocket(int aListenFd,
+                                             struct sockaddr* aAddress,
+                                             socklen_t* aAddressLength,
+                                             int& aStreamFd)
+{
+  ScopedClose fd(
+    TEMP_FAILURE_RETRY(accept(aListenFd, aAddress, aAddressLength)));
+  if (fd < 0) {
+    NS_WARNING("Cannot accept file descriptor!");
+    return NS_ERROR_FAILURE;
+  }
+  nsresult rv = SetSocketFlags(fd);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  aStreamFd = fd.forget();
+
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonConnector::CreateStreamSocket(struct sockaddr* aAddress,
+                                             socklen_t* aAddressLength,
+                                             int& aStreamFd)
+{
+  MOZ_CRASH("|BluetoothDaemonConnector| does not support "
+            "creating stream sockets.");
+  return NS_ERROR_ABORT;
+}
+
+// Deprecated
+
+int
+BluetoothDaemonConnector::Create()
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  int fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+  if (fd < 0) {
+    BT_WARNING("Could not open socket!");
+    return -1;
+  }
+  return fd;
+}
+
+bool
+BluetoothDaemonConnector::CreateAddr(bool aIsServer,
+                                     socklen_t& aAddrSize,
+                                     mozilla::ipc::sockaddr_any& aAddr,
+                                     const char* aAddress)
+{
+  static const size_t sNameOffset = 1;
+
+  size_t namesiz = mSocketName.Length() + 1; /* include trailing '\0' */
+
+  if ((sNameOffset + namesiz) > sizeof(aAddr.un.sun_path)) {
+    BT_WARNING("Address too long for socket struct!");
+    return false;
+  }
+
+  memset(aAddr.un.sun_path, '\0', sNameOffset); // abstract socket
+  memcpy(aAddr.un.sun_path + sNameOffset, mSocketName.get(), namesiz);
+  aAddr.un.sun_family = AF_UNIX;
+
+  aAddrSize = offsetof(struct sockaddr_un, sun_path) + sNameOffset + namesiz;
+
+  return true;
+}
+
+bool
+BluetoothDaemonConnector::SetUp(int aFd)
+{
+  if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) {
+    BT_WARNING("Failed to set non-blocking I/O.");
+    return false;
+  }
+  return true;
+}
+
+bool
+BluetoothDaemonConnector::SetUpListenSocket(int aFd)
+{
+  return true;
+}
+
+void
+BluetoothDaemonConnector::GetSocketAddr(
+  const mozilla::ipc::sockaddr_any& aAddr, nsAString& aAddrStr)
+{
+  // Unused.
+  MOZ_CRASH("This should never be called!");
+}
+
+END_BLUETOOTH_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonConnector.h
@@ -0,0 +1,66 @@
+/* -*- 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_dom_bluetooth_bluedroid_bluetoothdaemonconnector_h
+#define mozilla_dom_bluetooth_bluedroid_bluetoothdaemonconnector_h
+
+#include "mozilla/dom/bluetooth/BluetoothCommon.h"
+#include "mozilla/ipc/UnixSocketConnector.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothDaemonConnector final
+  : public mozilla::ipc::UnixSocketConnector
+{
+public:
+  BluetoothDaemonConnector(const nsACString& aSocketName);
+  ~BluetoothDaemonConnector();
+
+  // Methods for |UnixSocketConnector|
+  //
+
+  nsresult ConvertAddressToString(const struct sockaddr& aAddress,
+                                  socklen_t aAddressLength,
+                                  nsACString& aAddressString) override;
+
+  nsresult CreateListenSocket(struct sockaddr* aAddress,
+                              socklen_t* aAddressLength,
+                              int& aListenFd) override;
+
+  nsresult AcceptStreamSocket(int aListenFd,
+                              struct sockaddr* aAddress,
+                              socklen_t* aAddressLen,
+                              int& aStreamFd) override;
+
+  nsresult CreateStreamSocket(struct sockaddr* aAddress,
+                              socklen_t* aAddressLength,
+                              int& aStreamFd) override;
+
+  // Deprecated
+
+  int Create() override;
+  bool CreateAddr(bool aIsServer,
+             socklen_t& aAddrSize,
+             mozilla::ipc::sockaddr_any& aAddr,
+             const char* aAddress) override;
+  bool SetUp(int aFd) override;
+  bool SetUpListenSocket(int aFd) override;
+  void GetSocketAddr(const mozilla::ipc::sockaddr_any& aAddr,
+                     nsAString& aAddrStr) override;
+
+private:
+  nsresult CreateSocket(int& aFd) const;
+  nsresult SetSocketFlags(int aFd) const;
+  nsresult CreateAddress(struct sockaddr& aAddress,
+                         socklen_t& aAddressLength) const;
+
+  nsCString mSocketName;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
--- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
@@ -5,23 +5,23 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BluetoothDaemonInterface.h"
 #include <cutils/properties.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include "BluetoothDaemonA2dpInterface.h"
 #include "BluetoothDaemonAvrcpInterface.h"
+#include "BluetoothDaemonConnector.h"
 #include "BluetoothDaemonHandsfreeInterface.h"
 #include "BluetoothDaemonHelpers.h"
 #include "BluetoothDaemonSetupInterface.h"
 #include "BluetoothDaemonSocketInterface.h"
 #include "BluetoothInterfaceHelpers.h"
 #include "mozilla/ipc/ListenSocket.h"
-#include "mozilla/ipc/UnixSocketConnector.h"
 #include "mozilla/unused.h"
 #include "prrng.h"
 
 using namespace mozilla::ipc;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 static const int sRetryInterval = 100; // ms
@@ -2013,88 +2013,16 @@ BluetoothDaemonInterface::OnDisconnect(e
       // Assume daemon crashed during regular service; notify
       // BluetoothServiceBluedroid to prepare restart-daemon procedure
       sNotificationHandler->BackendErrorNotification(true);
       sNotificationHandler = nullptr;
     }
   }
 }
 
-class BluetoothDaemonSocketConnector final
-  : public mozilla::ipc::UnixSocketConnector
-{
-public:
-  BluetoothDaemonSocketConnector(const nsACString& aSocketName)
-    : mSocketName(aSocketName)
-  { }
-
-  int
-  Create() override
-  {
-    MOZ_ASSERT(!NS_IsMainThread());
-
-    int fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
-    if (fd < 0) {
-      BT_WARNING("Could not open socket!");
-      return -1;
-    }
-    return fd;
-  }
-
-  bool
-  CreateAddr(bool aIsServer,
-             socklen_t& aAddrSize,
-             sockaddr_any& aAddr,
-             const char* aAddress) override
-  {
-    static const size_t sNameOffset = 1;
-
-    size_t namesiz = mSocketName.Length() + 1; /* include trailing '\0' */
-
-    if ((sNameOffset + namesiz) > sizeof(aAddr.un.sun_path)) {
-      BT_WARNING("Address too long for socket struct!");
-      return false;
-    }
-
-    memset(aAddr.un.sun_path, '\0', sNameOffset); // abstract socket
-    memcpy(aAddr.un.sun_path + sNameOffset, mSocketName.get(), namesiz);
-    aAddr.un.sun_family = AF_UNIX;
-
-    aAddrSize = offsetof(struct sockaddr_un, sun_path) + sNameOffset + namesiz;
-
-    return true;
-  }
-
-  bool
-  SetUp(int aFd) override
-  {
-    if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) {
-      BT_WARNING("Failed to set non-blocking I/O.");
-      return false;
-    }
-    return true;
-  }
-
-  bool
-  SetUpListenSocket(int aFd) override
-  {
-    return true;
-  }
-
-  void
-  GetSocketAddr(const sockaddr_any& aAddr, nsAString& aAddrStr) override
-  {
-    // Unused.
-    MOZ_CRASH("This should never be called!");
-  }
-
-private:
-  nsCString mSocketName;
-};
-
 nsresult
 BluetoothDaemonInterface::CreateRandomAddressString(
   const nsACString& aPrefix, unsigned long aPostfixLength,
   nsACString& aAddress)
 {
   static const char sHexChar[16] = {
     [0x0] = '0', [0x1] = '1', [0x2] = '2', [0x3] = '3',
     [0x4] = '4', [0x5] = '5', [0x6] = '6', [0x7] = '7',
@@ -2204,17 +2132,17 @@ BluetoothDaemonInterface::Init(
   nsresult rv = CreateRandomAddressString(NS_LITERAL_CSTRING(BASE_SOCKET_NAME),
                                           POSTFIX_LENGTH,
                                           mListenSocketName);
   if (NS_FAILED(rv)) {
     mListenSocketName.AssignLiteral(BASE_SOCKET_NAME);
   }
 
   bool success = mListenSocket->Listen(
-    new BluetoothDaemonSocketConnector(mListenSocketName), mCmdChannel);
+    new BluetoothDaemonConnector(mListenSocketName), mCmdChannel);
   if (!success) {
     OnConnectError(CMD_CHANNEL);
     return;
   }
 
   // The protocol implementation needs a command channel for
   // sending commands to the daemon. We set it here, because
   // this is the earliest time when it's available.
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -89,16 +89,17 @@ if CONFIG['MOZ_B2G_BT']:
             DEFINES['MOZ_B2G_BT_BLUEZ'] = True
         elif CONFIG['MOZ_B2G_BT_BLUEDROID']:
             SOURCES += [
                 'bluedroid/BluetoothA2dpHALInterface.cpp',
                 'bluedroid/BluetoothA2dpManager.cpp',
                 'bluedroid/BluetoothAvrcpHALInterface.cpp',
                 'bluedroid/BluetoothDaemonA2dpInterface.cpp',
                 'bluedroid/BluetoothDaemonAvrcpInterface.cpp',
+                'bluedroid/BluetoothDaemonConnector.cpp',
                 'bluedroid/BluetoothDaemonHandsfreeInterface.cpp',
                 'bluedroid/BluetoothDaemonHelpers.cpp',
                 'bluedroid/BluetoothDaemonInterface.cpp',
                 'bluedroid/BluetoothDaemonSetupInterface.cpp',
                 'bluedroid/BluetoothDaemonSocketInterface.cpp',
                 'bluedroid/BluetoothGattHALInterface.cpp',
                 'bluedroid/BluetoothHALHelpers.cpp',
                 'bluedroid/BluetoothHALInterface.cpp',