Bug 843868: Change sockaddr* to be a union of all possible sockaddr types; r=tzimmermann
authorKyle Machulis <kyle@nonpolynomial.com>
Tue, 19 Mar 2013 10:23:47 -0700
changeset 136669 d9aa9a732b06887a1e6c007db47bf3c4e4a98069
parent 136668 e518b1e21757ae1b55b284de6745c951ea1e31a1
child 136670 7ea4ad83da53c40c4f7cb89834f6dee064c26402
push id336
push userakeybl@mozilla.com
push dateMon, 17 Jun 2013 22:53:19 +0000
treeherdermozilla-release@574a39cdf657 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstzimmermann
bugs843868
milestone22.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 843868: Change sockaddr* to be a union of all possible sockaddr types; r=tzimmermann
dom/bluetooth/BluetoothUnixSocketConnector.cpp
dom/bluetooth/BluetoothUnixSocketConnector.h
ipc/ril/Ril.cpp
ipc/unixsocket/UnixSocket.cpp
ipc/unixsocket/UnixSocket.h
--- a/dom/bluetooth/BluetoothUnixSocketConnector.cpp
+++ b/dom/bluetooth/BluetoothUnixSocketConnector.cpp
@@ -30,16 +30,17 @@
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/sco.h>
 #include <bluetooth/rfcomm.h>
 #include <bluetooth/l2cap.h>
 
 #include "BluetoothUnixSocketConnector.h"
 #include "nsThreadUtils.h"
 
+using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 static const int RFCOMM_SO_SNDBUF = 70 * 1024; // 70 KB send buffer
 
 static
 int get_bdaddr(const char *str, bdaddr_t *ba)
 {
   char *d = ((char*)ba) + 5, *endp;
@@ -134,56 +135,62 @@ BluetoothUnixSocketConnector::Create()
   }
 
   if (!SetUp(fd)) {
     NS_WARNING("Could not set up socket!");
   }
   return fd;
 }
 
-void
+bool
 BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
                                          socklen_t& aAddrSize,
-                                         struct sockaddr* aAddr,
+                                         sockaddr_any& aAddr,
                                          const char* aAddress)
 {
   // Set to BDADDR_ANY, if it's not a server, we'll reset.
   bdaddr_t bd_address_obj = {{0, 0, 0, 0, 0, 0}};
 
   if (!aIsServer && aAddress && strlen(aAddress) > 0) {
     if (get_bdaddr(aAddress, &bd_address_obj)) {
       NS_WARNING("Can't get bluetooth address!");
-      return;
+      return false;
     }
   }
 
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     struct sockaddr_rc addr_rc;
     aAddrSize = sizeof(addr_rc);
-    memset(aAddr, 0, aAddrSize);
-    addr_rc.rc_family = AF_BLUETOOTH;
-    addr_rc.rc_channel = mChannel;
-    memcpy(&addr_rc.rc_bdaddr, &bd_address_obj, sizeof(bdaddr_t));
-    memcpy(aAddr, &addr_rc, sizeof(addr_rc));
+    aAddr.rc.rc_family = AF_BLUETOOTH;
+    aAddr.rc.rc_channel = mChannel;
+    memcpy(&aAddr.rc.rc_bdaddr, &bd_address_obj, sizeof(bd_address_obj));
     break;
   case BluetoothSocketType::SCO:
     struct sockaddr_sco addr_sco;
     aAddrSize = sizeof(addr_sco);
-
-    memset(aAddr, 0, aAddrSize);
-    addr_sco.sco_family = AF_BLUETOOTH;
-    memcpy(&addr_sco.sco_bdaddr, &bd_address_obj, sizeof(bdaddr_t));
-    memcpy(aAddr, &addr_sco, sizeof(addr_sco));
+    aAddr.sco.sco_family = AF_BLUETOOTH;
+    memcpy(&aAddr.sco.sco_bdaddr, &bd_address_obj, sizeof(bd_address_obj));
     break;
   default:
     NS_WARNING("Socket type unknown!");
+    return false;
   }
+  return true;
 }
 
 void
-BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr& aAddr,
+BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr,
                                             nsAString& aAddrStr)
 {
   char addr[18];
-  get_bdaddr_as_string((bdaddr_t*)aAddr.sa_data, addr);
+  switch (mType) {
+  case BluetoothSocketType::RFCOMM:
+    get_bdaddr_as_string((bdaddr_t*)(&aAddr.rc.rc_bdaddr), addr);
+    break;
+  case BluetoothSocketType::SCO:
+    get_bdaddr_as_string((bdaddr_t*)(&aAddr.sco.sco_bdaddr), addr);
+    break;
+  default:
+    MOZ_NOT_REACHED("Socket should be either RFCOMM or SCO!");
+  }
   aAddrStr.AssignASCII(addr);
 }
--- a/dom/bluetooth/BluetoothUnixSocketConnector.h
+++ b/dom/bluetooth/BluetoothUnixSocketConnector.h
@@ -16,22 +16,22 @@ BEGIN_BLUETOOTH_NAMESPACE
 class BluetoothUnixSocketConnector : public mozilla::ipc::UnixSocketConnector
 {
 public:
   BluetoothUnixSocketConnector(BluetoothSocketType aType, int aChannel,
                                bool aAuth, bool aEncrypt);
   virtual ~BluetoothUnixSocketConnector()
   {}
   virtual int Create() MOZ_OVERRIDE;
-  virtual void CreateAddr(bool aIsServer,
+  virtual bool CreateAddr(bool aIsServer,
                           socklen_t& aAddrSize,
-                          struct sockaddr* aAddr,
+                          mozilla::ipc::sockaddr_any& aAddr,
                           const char* aAddress) MOZ_OVERRIDE;
   virtual bool SetUp(int aFd) MOZ_OVERRIDE;
-  virtual void GetSocketAddr(const sockaddr& aAddr,
+  virtual void GetSocketAddr(const mozilla::ipc::sockaddr_any& aAddr,
                              nsAString& aAddrStr) MOZ_OVERRIDE;
 
 private:
   BluetoothSocketType mType;
   int mChannel;
   bool mAuth;
   bool mEncrypt;
 };
--- a/ipc/ril/Ril.cpp
+++ b/ipc/ril/Ril.cpp
@@ -66,103 +66,99 @@ class RilConnector : public mozilla::ipc
 public:
   RilConnector(unsigned long aClientId) : mClientId(aClientId)
   {}
 
   virtual ~RilConnector()
   {}
 
   virtual int Create();
-  virtual void CreateAddr(bool aIsServer,
+  virtual bool CreateAddr(bool aIsServer,
                           socklen_t& aAddrSize,
-                          struct sockaddr *aAddr,
+                          sockaddr_any& aAddr,
                           const char* aAddress);
   virtual bool SetUp(int aFd);
-  virtual void GetSocketAddr(const sockaddr& aAddr,
+  virtual void GetSocketAddr(const sockaddr_any& aAddr,
                              nsAString& aAddrStr);
 
 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
-    struct hostent *hp;
-
-    hp = gethostbyname("localhost");
-    if (hp) {
-        fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
-    }
+    // 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;
 }
 
-void
+bool
 RilConnector::CreateAddr(bool aIsServer,
                          socklen_t& aAddrSize,
-                         struct sockaddr *aAddr,
+                         sockaddr_any& aAddr,
                          const char* aAddress)
 {
     // We never open ril socket as server.
     MOZ_ASSERT(!aIsServer);
-
+    uint32_t af;
 #if defined(MOZ_WIDGET_GONK)
-    struct sockaddr_un addr_un;
-
-    memset(&addr_un, 0, sizeof(addr_un));
-    strcpy(addr_un.sun_path, aAddress);
-    addr_un.sun_family = AF_LOCAL;
-
-    aAddrSize = strlen(aAddress) + offsetof(struct sockaddr_un, sun_path) + 1;
-    memcpy(aAddr, &addr_un, aAddrSize);
+    af = AF_LOCAL;
 #else
-    struct hostent *hp;
-    struct sockaddr_in addr_in;
-
-    hp = gethostbyname("localhost");
-    if (!hp) {
-        return;
+    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 = htons(INADDR_LOOPBACK);
+        aAddrSize = sizeof(sockaddr_in);
+        break;
+    default:
+        NS_WARNING("Socket type not handled by connector!");
+        return false;
     }
-
-    memset(&addr_in, 0, sizeof(addr_in));
-    addr_in.sin_family = hp->h_addrtype;
-    addr_in.sin_port = htons(RIL_TEST_PORT + mClientId);
-    memcpy(&addr_in.sin_addr, hp->h_addr, hp->h_length);
-
-    aAddrSize = sizeof(addr_in);
-    memcpy(aAddr, &addr_in, aAddrSize);
-#endif
+    return true;
 }
 
 bool
 RilConnector::SetUp(int aFd)
 {
     // Nothing to do here.
     return true;
 }
 
 void
-RilConnector::GetSocketAddr(const sockaddr& aAddr,
+RilConnector::GetSocketAddr(const sockaddr_any& aAddr,
                             nsAString& aAddrStr)
 {
     // Unused.
     MOZ_NOT_REACHED("This should never be called!");
 }
 
 } // anonymous namespace
 
--- a/ipc/unixsocket/UnixSocket.cpp
+++ b/ipc/unixsocket/UnixSocket.cpp
@@ -213,17 +213,17 @@ private:
   /**
    * Size of the socket address struct
    */
   socklen_t mAddrSize;
 
   /**
    * Address struct of the socket currently in use
    */
-  sockaddr mAddr;
+  sockaddr_any mAddr;
 };
 
 template<class T>
 class DeleteInstanceRunnable : public nsRunnable
 {
 public:
   DeleteInstanceRunnable(T* aInstance)
   : mInstance(aInstance)
@@ -436,30 +436,33 @@ UnixSocketImpl::Accept()
 
   if (!mConnector) {
     NS_WARNING("No connector object available!");
     return;
   }
 
   // This will set things we don't particularly care about, but it will hand
   // back the correct structure size which is what we do care about.
-  mConnector->CreateAddr(true, mAddrSize, &mAddr, nullptr);
+  if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) {
+    NS_WARNING("Cannot create socket address!");
+    return;
+  }
 
-  if(mFd.get() < 0)
+  if (mFd.get() < 0)
   {
     mFd = mConnector->Create();
     if (mFd.get() < 0) {
       return;
     }
 
     if (!SetSocketFlags()) {
       return;
     }
 
-    if (bind(mFd.get(), &mAddr, mAddrSize)) {
+    if (bind(mFd.get(), (struct sockaddr*)&mAddr, mAddrSize)) {
 #ifdef DEBUG
       LOG("...bind(%d) gave errno %d", mFd.get(), errno);
 #endif
       return;
     }
 
     if (listen(mFd.get(), 1)) {
 #ifdef DEBUG
@@ -488,19 +491,22 @@ UnixSocketImpl::Connect()
     mFd = mConnector->Create();
     if (mFd.get() < 0) {
       return;
     }
   }
 
   int ret;
 
-  mConnector->CreateAddr(false, mAddrSize, &mAddr, mAddress.get());
+  if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) {
+    NS_WARNING("Cannot create socket address!");
+    return;
+  }
 
-  ret = connect(mFd.get(), &mAddr, mAddrSize);
+  ret = connect(mFd.get(), (struct sockaddr*)&mAddr, mAddrSize);
 
   if (ret) {
 #if DEBUG
     LOG("Socket connect errno=%d\n", errno);
 #endif
     mFd.reset(-1);
     nsRefPtr<OnSocketEventTask> t =
       new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
@@ -655,17 +661,17 @@ UnixSocketImpl::OnFileCanReadWithoutBloc
         return;
       }
     }
 
     MOZ_NOT_REACHED("We returned early");
   }
 
   if (status == SOCKET_LISTENING) {
-    int client_fd = accept(mFd.get(), &mAddr, &mAddrSize);
+    int client_fd = accept(mFd.get(), (struct sockaddr*)&mAddr, &mAddrSize);
 
     if (client_fd < 0) {
       return;
     }
 
     if (!mConnector->SetUp(client_fd)) {
       NS_WARNING("Could not set up socket!");
       return;
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -2,25 +2,45 @@
 /* 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 <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#ifdef MOZ_B2G_BT
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sco.h>
+#include <bluetooth/rfcomm.h>
+#endif
 #include <stdlib.h>
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "mozilla/RefPtr.h"
 
 namespace mozilla {
 namespace ipc {
 
+union sockaddr_any {
+  sockaddr_storage storage; // address-family only
+  sockaddr_un un;
+  sockaddr_in in;
+  sockaddr_in6 in6;
+#ifdef MOZ_B2G_BT
+  sockaddr_sco sco;
+  sockaddr_rc rc;
+#endif
+  // ... others
+};
+
 class UnixSocketRawData
 {
 public:
   nsAutoArrayPtr<uint8_t> mData;
 
   // Number of octets in mData.
   size_t mSize;
   size_t mCurrentWriteOffset;
@@ -73,20 +93,22 @@ public:
    * Since most socket specifics are related to address formation into a
    * sockaddr struct, this function is defined by subclasses and fills in the
    * structure as needed for whatever connection it is trying to build
    *
    * @param aIsServer True is we are acting as a server socket
    * @param aAddrSize Size of the struct 
    * @param aAddr Struct to fill
    * @param aAddress If aIsServer is false, Address to connect to. nullptr otherwise.
+   *
+   * @return True if address is filled correctly, false otherwise
    */
-  virtual void CreateAddr(bool aIsServer,
+  virtual bool CreateAddr(bool aIsServer,
                           socklen_t& aAddrSize,
-                          struct sockaddr *aAddr,
+                          sockaddr_any& aAddr,
                           const char* aAddress) = 0;
 
   /** 
    * Does any socket type specific setup that may be needed
    *
    * @param aFd File descriptor for opened socket
    *
    * @return true is successful, false otherwise
@@ -95,17 +117,17 @@ public:
 
   /** 
    * Get address of socket we're currently connected to. Return null string if
    * not connected.
    *
    * @param aAddr Address struct
    * @param aAddrStr String to store address to
    */
-  virtual void GetSocketAddr(const sockaddr& aAddr,
+  virtual void GetSocketAddr(const sockaddr_any& aAddr,
                              nsAString& aAddrStr) = 0;
 
 };
 
 enum SocketConnectionStatus {
   SOCKET_DISCONNECTED = 0,
   SOCKET_LISTENING = 1,
   SOCKET_CONNECTING = 2,