Bug 1161020: Implement new socket-connector interface for NFC, r=allstars.chh
☠☠ backed out by b0784c6cf439 ☠ ☠
authorThomas Zimmermann <tdz@users.sourceforge.net>
Mon, 18 May 2015 11:28:30 +0200
changeset 244341 13753f9043f72975ad483ae1564dc955c19f95e7
parent 244340 f90b8d3d6b709896b1a8b106ba84743610876ad3
child 244342 34a20b05af6c5b6f5d0426a9602d19ed1db36c4a
push id28774
push userryanvm@gmail.com
push dateMon, 18 May 2015 20:24:02 +0000
treeherdermozilla-central@3c292fab543d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersallstars.chh
bugs1161020
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 1161020: Implement new socket-connector interface for NFC, r=allstars.chh This patch moves |NfcConnector| into its own file and implements the new socket-connector interface.
dom/nfc/gonk/NfcService.cpp
ipc/nfc/Nfc.cpp
ipc/nfc/Nfc.h
ipc/nfc/NfcConnector.cpp
ipc/nfc/NfcConnector.h
ipc/nfc/moz.build
--- a/dom/nfc/gonk/NfcService.cpp
+++ b/dom/nfc/gonk/NfcService.cpp
@@ -7,16 +7,17 @@
 #include "NfcService.h"
 #include <binder/Parcel.h>
 #include <cutils/properties.h>
 #include "mozilla/ModuleUtils.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/NfcOptionsBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/RootedDictionary.h"
+#include "mozilla/ipc/NfcConnector.h"
 #include "mozilla/unused.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsXULAppAPI.h"
 #include "NfcOptions.h"
 
 #define NS_NFCSERVICE_CID \
   { 0x584c9a21, 0x4e17, 0x43b7, {0xb1, 0x6a, 0x87, 0xa0, 0x42, 0xef, 0xd4, 0x64} }
@@ -307,17 +308,18 @@ NfcService::Start(nsINfcGonkEventListene
   mListener = aListener;
   mHandler = new NfcMessageHandler();
   mConsumer = new NfcConsumer(this);
 
   mListenSocketName = BASE_SOCKET_NAME;
 
   mListenSocket = new NfcListenSocket(this);
 
-  bool success = mListenSocket->Listen(new NfcConnector(), mConsumer);
+  bool success = mListenSocket->Listen(new NfcConnector(mListenSocketName),
+                                       mConsumer);
   if (!success) {
     mConsumer = nullptr;
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv = NS_NewNamedThread("NfcThread", getter_AddRefs(mThread));
   if (NS_FAILED(rv)) {
     NS_WARNING("Can't create Nfc worker thread.");
--- a/ipc/nfc/Nfc.cpp
+++ b/ipc/nfc/Nfc.cpp
@@ -17,16 +17,17 @@
 #include <android/log.h>
 #define CHROMIUM_LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
 #else
 #define CHROMIUM_LOG(args...)
 #endif
 
 #include "jsfriendapi.h"
 #include "mozilla/ArrayUtils.h"
+#include "mozilla/ipc/NfcConnector.h"
 #include "nsThreadUtils.h" // For NS_IsMainThread.
 
 using namespace mozilla::ipc;
 
 namespace {
 
 class SendNfcSocketDataTask final : public nsRunnable
 {
@@ -56,84 +57,16 @@ private:
 };
 
 } // anonymous namespace
 
 namespace mozilla {
 namespace ipc {
 
 //
-// NfcConnector
-//
-
-int
-NfcConnector::Create()
-{
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
-  if (fd < 0) {
-    NS_WARNING("Could not open nfc socket!");
-    return -1;
-  }
-
-  if (!SetUp(fd)) {
-    NS_WARNING("Could not set up socket!");
-  }
-  return fd;
-}
-
-bool
-NfcConnector::CreateAddr(bool aIsServer,
-                         socklen_t& aAddrSize,
-                         sockaddr_any& aAddr,
-                         const char* aAddress)
-{
-  static const size_t sNameOffset = 1;
-
-  nsDependentCString socketName("nfcd");
-
-  size_t namesiz = socketName.Length() + 1; /* include trailing '\0' */
-
-  if ((sNameOffset + namesiz) > sizeof(aAddr.un.sun_path)) {
-    NS_WARNING("Address too long for socket struct!");
-    return false;
-  }
-
-  memset(aAddr.un.sun_path, '\0', sNameOffset); // abstract socket
-  memcpy(aAddr.un.sun_path + sNameOffset, socketName.get(), namesiz);
-  aAddr.un.sun_family = AF_UNIX;
-
-  aAddrSize = offsetof(struct sockaddr_un, sun_path) + sNameOffset + namesiz;
-
-  return true;
-}
-
-bool
-NfcConnector::SetUp(int aFd)
-{
-  // Nothing to do here.
-  return true;
-}
-
-bool
-NfcConnector::SetUpListenSocket(int aFd)
-{
-  // Nothing to do here.
-  return true;
-}
-
-void
-NfcConnector::GetSocketAddr(const sockaddr_any& aAddr,
-                            nsAString& aAddrStr)
-{
-  MOZ_CRASH("This should never be called!");
-}
-
-//
 // NfcListenSocket
 //
 
 NfcListenSocket::NfcListenSocket(NfcSocketListener* aListener)
   : mListener(aListener)
 { }
 
 void
@@ -226,13 +159,13 @@ NfcConsumer::OnDisconnect()
   if (mListener) {
     mListener->OnDisconnect(NfcSocketListener::STREAM_SOCKET);
   }
 }
 
 ConnectionOrientedSocketIO*
 NfcConsumer::GetIO()
 {
-  return PrepareAccept(new NfcConnector());
+  return PrepareAccept(new NfcConnector(NS_LITERAL_CSTRING("nfcd")));
 }
 
 } // namespace ipc
 } // namespace mozilla
--- a/ipc/nfc/Nfc.h
+++ b/ipc/nfc/Nfc.h
@@ -6,17 +6,16 @@
 
 /* Copyright © 2013, Deutsche Telekom, Inc. */
 
 #ifndef mozilla_ipc_Nfc_h
 #define mozilla_ipc_Nfc_h 1
 
 #include <mozilla/ipc/ListenSocket.h>
 #include <mozilla/ipc/StreamSocket.h>
-#include <mozilla/ipc/UnixSocketConnector.h>
 
 namespace mozilla {
 namespace ipc {
 
 class NfcSocketListener
 {
 public:
   enum SocketType {
@@ -39,33 +38,16 @@ public:
   void OnConnectSuccess() override;
   void OnConnectError() override;
   void OnDisconnect() override;
 
 private:
   NfcSocketListener* mListener;
 };
 
-class NfcConnector final : public mozilla::ipc::UnixSocketConnector
-{
-public:
-  NfcConnector()
-  { }
-
-  int Create() override;
-  bool CreateAddr(bool aIsServer,
-                  socklen_t& aAddrSize,
-                  sockaddr_any& aAddr,
-                  const char* aAddress) override;
-  bool SetUp(int aFd) override;
-  bool SetUpListenSocket(int aFd) override;
-  void GetSocketAddr(const sockaddr_any& aAddr,
-                     nsAString& aAddrStr) override;
-};
-
 class NfcConsumer final : public mozilla::ipc::StreamSocket
 {
 public:
   NfcConsumer(NfcSocketListener* aListener);
 
   void Shutdown();
   bool PostToNfcDaemon(const uint8_t* aData, size_t aSize);
 
new file mode 100644
--- /dev/null
+++ b/ipc/nfc/NfcConnector.cpp
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp: */
+
+/* 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 "NfcConnector.h"
+#include <fcntl.h>
+#include <sys/un.h>
+#include "nsISupportsImpl.h" // For MOZ_COUNT_CTOR, MOZ_COUNT_DTOR
+#include "nsThreadUtils.h" // For NS_IsMainThread.
+
+namespace mozilla {
+namespace ipc {
+
+NfcConnector::NfcConnector(const nsACString& aAddressString)
+  : mAddressString(aAddressString)
+{
+  MOZ_COUNT_CTOR_INHERITED(NfcConnector, UnixSocketConnector);
+}
+
+NfcConnector::~NfcConnector()
+{
+  MOZ_COUNT_DTOR_INHERITED(NfcConnector, UnixSocketConnector);
+}
+
+nsresult
+NfcConnector::CreateSocket(int& aFd) const
+{
+  aFd = socket(AF_LOCAL, SOCK_STREAM, 0);
+  if (aFd < 0) {
+    NS_WARNING("Could not open NFC socket!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+NfcConnector::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
+NfcConnector::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 = mAddressString.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, mAddressString.get(), namesiz);
+
+  aAddressLength =
+    offsetof(struct sockaddr_un, sun_path) + sNameOffset + namesiz;
+
+  return NS_OK;
+}
+
+// |UnixSocketConnector|
+//
+
+nsresult
+NfcConnector::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
+NfcConnector::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
+NfcConnector::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
+NfcConnector::CreateStreamSocket(struct sockaddr* aAddress,
+                                 socklen_t* aAddressLength,
+                                 int& aStreamFd)
+{
+  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;
+    }
+  }
+
+  aStreamFd = fd.forget();
+
+  return NS_OK;
+}
+
+// Deprecated
+
+int
+NfcConnector::Create()
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+  if (fd < 0) {
+    NS_WARNING("Could not open nfc socket!");
+    return -1;
+  }
+
+  if (!SetUp(fd)) {
+    NS_WARNING("Could not set up socket!");
+  }
+  return fd;
+}
+
+bool
+NfcConnector::CreateAddr(bool aIsServer,
+                         socklen_t& aAddrSize,
+                         sockaddr_any& aAddr,
+                         const char* aAddress)
+{
+  static const size_t sNameOffset = 1;
+
+  nsDependentCString socketName("nfcd");
+
+  size_t namesiz = socketName.Length() + 1; /* include trailing '\0' */
+
+  if ((sNameOffset + namesiz) > sizeof(aAddr.un.sun_path)) {
+    NS_WARNING("Address too long for socket struct!");
+    return false;
+  }
+
+  memset(aAddr.un.sun_path, '\0', sNameOffset); // abstract socket
+  memcpy(aAddr.un.sun_path + sNameOffset, socketName.get(), namesiz);
+  aAddr.un.sun_family = AF_UNIX;
+
+  aAddrSize = offsetof(struct sockaddr_un, sun_path) + sNameOffset + namesiz;
+
+  return true;
+}
+
+bool
+NfcConnector::SetUp(int aFd)
+{
+  // Nothing to do here.
+  return true;
+}
+
+bool
+NfcConnector::SetUpListenSocket(int aFd)
+{
+  // Nothing to do here.
+  return true;
+}
+
+void
+NfcConnector::GetSocketAddr(const sockaddr_any& aAddr,
+                            nsAString& aAddrStr)
+{
+  MOZ_CRASH("This should never be called!");
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/ipc/nfc/NfcConnector.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp: */
+
+/* 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_NfcConnector_h
+#define mozilla_ipc_NfcConnector_h
+
+#include "mozilla/ipc/UnixSocketConnector.h"
+
+namespace mozilla {
+namespace ipc {
+
+/**
+ * |NfcConnector| creates sockets for communicating with
+ * the NFC daemon.
+ */
+class NfcConnector final : public UnixSocketConnector
+{
+public:
+  NfcConnector(const nsACString& aAddressString);
+  ~NfcConnector();
+
+  // 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,
+                  sockaddr_any& aAddr,
+                  const char* aAddress) override;
+  bool SetUp(int aFd) override;
+  bool SetUpListenSocket(int aFd) override;
+  void GetSocketAddr(const 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 mAddressString;
+};
+
+}
+}
+
+#endif
--- a/ipc/nfc/moz.build
+++ b/ipc/nfc/moz.build
@@ -1,18 +1,20 @@
 # 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/.
 
 if CONFIG['MOZ_NFC']:
     EXPORTS.mozilla.ipc += [
         'Nfc.h',
+        'NfcConnector.h',
     ]
     SOURCES += [
         'Nfc.cpp',
+        'NfcConnector.cpp',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True