Bug 1161020: Implement new socket-connector interface for RIL, r=htsai
authorThomas Zimmermann <tdz@users.sourceforge.net>
Tue, 19 May 2015 13:28:46 +0200
changeset 244512 0ba5a258797d88aa903092d008a03a3e8fd32cee
parent 244511 1acea1f3dfe552dbc0764986b1ab37689407c128
child 244513 85939a63419fe98cf95a23cfb1272f469d7914f6
push id28782
push userkwierso@gmail.com
push dateTue, 19 May 2015 23:42:58 +0000
treeherdermozilla-central@ac277e615f8f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershtsai
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 RIL, r=htsai This patch moves |RilConnector| into its own file and implements the new socket-connector interface.
ipc/ril/Ril.cpp
ipc/ril/RilConnector.cpp
ipc/ril/RilConnector.h
ipc/ril/moz.build
--- a/ipc/ril/Ril.cpp
+++ b/ipc/ril/Ril.cpp
@@ -16,31 +16,27 @@
 #include <android/log.h>
 #define CHROMIUM_LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
 #else
 #define CHROMIUM_LOG(args...)  printf(args);
 #endif
 
 #include "jsfriendapi.h"
 #include "mozilla/ArrayUtils.h"
-#include "mozilla/ipc/UnixSocketConnector.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h" // For NS_IsMainThread.
+#include "RilConnector.h"
 
 USING_WORKERS_NAMESPACE
 using namespace mozilla::ipc;
 
 namespace {
 
 static const char RIL_SOCKET_NAME[] = "/dev/socket/rilproxy";
 
-// Network port to connect to for adb forwarded sockets when doing
-// desktop development.
-static const uint32_t RIL_TEST_PORT = 6200;
-
 static nsTArray<nsRefPtr<mozilla::ipc::RilConsumer> > sRilConsumers;
 
 class ConnectWorkerToRIL final : public WorkerTask
 {
 public:
   bool RunTask(JSContext* aCx) override;
 };
 
@@ -194,119 +190,16 @@ DispatchRILEvent::RunTask(JSContext* aCx
   JS::AutoValueArray<2> args(aCx);
   args[0].setNumber((uint32_t)mClientId);
   args[1].setObject(*array);
 
   JS::Rooted<JS::Value> rval(aCx);
   return JS_CallFunctionName(aCx, obj, "onRILMessage", args, &rval);
 }
 
-class RilConnector final : public mozilla::ipc::UnixSocketConnector
-{
-public:
-  RilConnector(unsigned long aClientId)
-    : mClientId(aClientId)
-  { }
-
-  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:
-  unsigned long mClientId;
-};
-
-int
-RilConnector::Create()
-{
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  int fd = -1;
-
-#if defined(MOZ_WIDGET_GONK)
-  fd = socket(AF_LOCAL, SOCK_STREAM, 0);
-#else
-  // If we can't hit a local loopback, fail later in connect.
-  fd = socket(AF_INET, SOCK_STREAM, 0);
-#endif
-
-  if (fd < 0) {
-    NS_WARNING("Could not open ril socket!");
-    return -1;
-  }
-
-  if (!SetUp(fd)) {
-    NS_WARNING("Could not set up socket!");
-  }
-  return fd;
-}
-
-bool
-RilConnector::CreateAddr(bool aIsServer,
-                         socklen_t& aAddrSize,
-                         sockaddr_any& aAddr,
-                         const char* aAddress)
-{
-  // We never open ril socket as server.
-  MOZ_ASSERT(!aIsServer);
-  uint32_t af;
-#if defined(MOZ_WIDGET_GONK)
-  af = AF_LOCAL;
-#else
-  af = AF_INET;
-#endif
-  switch (af) {
-  case AF_LOCAL:
-    aAddr.un.sun_family = af;
-    if(strlen(aAddress) > sizeof(aAddr.un.sun_path)) {
-      NS_WARNING("Address too long for socket struct!");
-      return false;
-    }
-    strcpy((char*)&aAddr.un.sun_path, aAddress);
-    aAddrSize = strlen(aAddress) + offsetof(struct sockaddr_un, sun_path) + 1;
-    break;
-  case AF_INET:
-    aAddr.in.sin_family = af;
-    aAddr.in.sin_port = htons(RIL_TEST_PORT + mClientId);
-    aAddr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-    aAddrSize = sizeof(sockaddr_in);
-    break;
-  default:
-    NS_WARNING("Socket type not handled by connector!");
-    return false;
-  }
-  return true;
-}
-
-bool
-RilConnector::SetUp(int aFd)
-{
-  // Nothing to do here.
-  return true;
-}
-
-bool
-RilConnector::SetUpListenSocket(int aFd)
-{
-  // Nothing to do here.
-  return true;
-}
-
-void
-RilConnector::GetSocketAddr(const sockaddr_any& aAddr, nsAString& aAddrStr)
-{
-  MOZ_CRASH("This should never be called!");
-}
-
 } // anonymous namespace
 
 namespace mozilla {
 namespace ipc {
 
 RilConsumer::RilConsumer(unsigned long aClientId,
                          WorkerCrossThreadDispatcher* aDispatcher)
   : mDispatcher(aDispatcher)
@@ -319,17 +212,17 @@ RilConsumer::RilConsumer(unsigned long a
     mAddress = RIL_SOCKET_NAME;
   } else {
     struct sockaddr_un addr_un;
     snprintf(addr_un.sun_path, sizeof addr_un.sun_path, "%s%lu",
              RIL_SOCKET_NAME, aClientId);
     mAddress = addr_un.sun_path;
   }
 
-  Connect(new RilConnector(mClientId), mAddress.get());
+  Connect(new RilConnector(mAddress, mClientId), mAddress.get());
 }
 
 nsresult
 RilConsumer::Register(unsigned int aClientId,
                       WorkerCrossThreadDispatcher* aDispatcher)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -391,21 +284,21 @@ RilConsumer::OnConnectError()
   Close();
 }
 
 void
 RilConsumer::OnDisconnect()
 {
   CHROMIUM_LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__);
   if (!mShutdown) {
-    Connect(new RilConnector(mClientId), mAddress.get(),
+    Connect(new RilConnector(mAddress, mClientId), mAddress.get(),
             GetSuggestedConnectDelayMs());
   }
 }
 
 ConnectionOrientedSocketIO*
 RilConsumer::GetIO()
 {
-  return PrepareAccept(new RilConnector(mClientId));
+  return PrepareAccept(new RilConnector(mAddress, mClientId));
 }
 
 } // namespace ipc
 } // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/ril/RilConnector.cpp
@@ -0,0 +1,292 @@
+/* -*- 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 "RilConnector.h"
+#include <fcntl.h>
+#include <sys/socket.h>
+#include "nsThreadUtils.h" // For NS_IsMainThread.
+
+#ifdef AF_INET
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+#ifdef AF_UNIX
+#include <sys/un.h>
+#endif
+
+namespace mozilla {
+namespace ipc {
+
+static const uint16_t RIL_TEST_PORT = 6200;
+
+RilConnector::RilConnector(const nsACString& aAddressString,
+                           unsigned long aClientId)
+  : mAddressString(aAddressString)
+  , mClientId(aClientId)
+{ }
+
+RilConnector::~RilConnector()
+{ }
+
+nsresult
+RilConnector::CreateSocket(int aDomain, int& aFd) const
+{
+  aFd = socket(aDomain, SOCK_STREAM, 0);
+  if (aFd < 0) {
+    NS_WARNING("Could not open RIL socket!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+RilConnector::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
+RilConnector::CreateAddress(int aDomain,
+                            struct sockaddr& aAddress,
+                            socklen_t& aAddressLength) const
+{
+  switch (aDomain) {
+#ifdef AF_UNIX
+    case AF_UNIX: {
+        struct sockaddr_un* address =
+          reinterpret_cast<struct sockaddr_un*>(&aAddress);
+        address->sun_family = aDomain;
+        size_t siz = mAddressString.Length() + 1;
+        if (siz > sizeof(address->sun_path)) {
+          NS_WARNING("Address too long for socket struct!");
+          return NS_ERROR_FAILURE;
+        }
+        memcpy(address->sun_path, mAddressString.get(), siz);
+        aAddressLength = offsetof(struct sockaddr_un, sun_path) + siz;
+      }
+      break;
+#endif
+#ifdef AF_INET
+    case AF_INET: {
+        struct sockaddr_in* address =
+          reinterpret_cast<struct sockaddr_in*>(&aAddress);
+        address->sin_family = aDomain;
+        address->sin_port = htons(RIL_TEST_PORT + mClientId);
+        address->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+        aAddressLength = sizeof(*address);
+      }
+      break;
+#endif
+    default:
+      NS_WARNING("Address family not handled by connector!");
+      return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+// |UnixSocketConnector|
+
+nsresult
+RilConnector::ConvertAddressToString(const struct sockaddr& aAddress,
+                                     socklen_t aAddressLength,
+                                     nsACString& aAddressString)
+{
+#ifdef AF_UNIX
+  if (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);
+  } else
+#endif
+#ifdef AF_INET
+  if (aAddress.sa_family == AF_INET) {
+    const struct sockaddr_in* in =
+      reinterpret_cast<const struct sockaddr_in*>(&aAddress);
+
+    aAddressString.Assign(nsDependentCString(inet_ntoa(in->sin_addr)));
+  } else
+#endif
+  {
+    NS_WARNING("Address family not handled by connector!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+RilConnector::CreateListenSocket(struct sockaddr* aAddress,
+                                 socklen_t* aAddressLength,
+                                 int& aListenFd)
+{
+  MOZ_CRASH("|RilConnector| does not support listening sockets.");
+}
+
+nsresult
+RilConnector::AcceptStreamSocket(int aListenFd,
+                                 struct sockaddr* aAddress,
+                                 socklen_t* aAddressLen,
+                                 int& aStreamFd)
+{
+  MOZ_CRASH("|RilConnector| does not support accepting sockets.");
+}
+
+nsresult
+RilConnector::CreateStreamSocket(struct sockaddr* aAddress,
+                                 socklen_t* aAddressLength,
+                                 int& aStreamFd)
+{
+#ifdef MOZ_WIDGET_GONK
+  static const int sDomain = AF_UNIX;
+#else
+  static const int sDomain = AF_INET;
+#endif
+
+  ScopedClose fd;
+
+  nsresult rv = CreateSocket(sDomain, fd.rwget());
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = SetSocketFlags(fd);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  if (aAddress && aAddressLength) {
+    rv = CreateAddress(sDomain, *aAddress, *aAddressLength);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  }
+
+  aStreamFd = fd.forget();
+
+  return NS_OK;
+}
+
+// Deprecated
+
+int
+RilConnector::Create()
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  int fd = -1;
+
+#if defined(MOZ_WIDGET_GONK)
+  fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+#else
+  // If we can't hit a local loopback, fail later in connect.
+  fd = socket(AF_INET, SOCK_STREAM, 0);
+#endif
+
+  if (fd < 0) {
+    NS_WARNING("Could not open ril socket!");
+    return -1;
+  }
+
+  if (!SetUp(fd)) {
+    NS_WARNING("Could not set up socket!");
+  }
+  return fd;
+}
+
+bool
+RilConnector::CreateAddr(bool aIsServer,
+                         socklen_t& aAddrSize,
+                         sockaddr_any& aAddr,
+                         const char* aAddress)
+{
+  // We never open ril socket as server.
+  MOZ_ASSERT(!aIsServer);
+  uint32_t af;
+#if defined(MOZ_WIDGET_GONK)
+  af = AF_LOCAL;
+#else
+  af = AF_INET;
+#endif
+  switch (af) {
+  case AF_LOCAL:
+    aAddr.un.sun_family = af;
+    if(strlen(aAddress) > sizeof(aAddr.un.sun_path)) {
+      NS_WARNING("Address too long for socket struct!");
+      return false;
+    }
+    strcpy((char*)&aAddr.un.sun_path, aAddress);
+    aAddrSize = strlen(aAddress) + offsetof(struct sockaddr_un, sun_path) + 1;
+    break;
+  case AF_INET:
+    aAddr.in.sin_family = af;
+    aAddr.in.sin_port = htons(RIL_TEST_PORT + mClientId);
+    aAddr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    aAddrSize = sizeof(sockaddr_in);
+    break;
+  default:
+    NS_WARNING("Socket type not handled by connector!");
+    return false;
+  }
+  return true;
+}
+
+bool
+RilConnector::SetUp(int aFd)
+{
+  // Nothing to do here.
+  return true;
+}
+
+bool
+RilConnector::SetUpListenSocket(int aFd)
+{
+  // Nothing to do here.
+  return true;
+}
+
+void
+RilConnector::GetSocketAddr(const sockaddr_any& aAddr, nsAString& aAddrStr)
+{
+  MOZ_CRASH("This should never be called!");
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/ipc/ril/RilConnector.h
@@ -0,0 +1,72 @@
+/* -*- 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_RilConnector_h
+#define mozilla_ipc_RilConnector_h
+
+#include "mozilla/ipc/UnixSocketConnector.h"
+
+namespace mozilla {
+namespace ipc {
+
+/**
+ * |RilConnector| creates sockets for connecting to rild.
+ */
+class RilConnector final : public UnixSocketConnector
+{
+public:
+  RilConnector(const nsACString& aAddressString,
+               unsigned long aClientId);
+  ~RilConnector();
+
+  // 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 aDomain, int& aFd) const;
+  nsresult SetSocketFlags(int aFd) const;
+  nsresult CreateAddress(int aDomain,
+                         struct sockaddr& aAddress,
+                         socklen_t& aAddressLength) const;
+
+  nsCString mAddressString;
+  unsigned long mClientId;
+};
+
+}
+}
+
+#endif
--- a/ipc/ril/moz.build
+++ b/ipc/ril/moz.build
@@ -5,15 +5,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS.mozilla.ipc += [
     'Ril.h',
 ]
 
 SOURCES += [
     'Ril.cpp',
+    'RilConnector.cpp'
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True