From 474fc0a81e5027338d612b573703ddf3e120f7e2 Mon Sep 17 00:00:00 2001 From: Kyle Machulis Date: Tue, 19 Mar 2013 10:23:47 -0700 Subject: [PATCH] Bug 843868: Change sockaddr* to be a union of all possible sockaddr types; r=tzimmermann --HG-- extra : rebase_source : 455aeb8c49bec2477a5ffea839a0ac3fe09434f7 --- .../BluetoothUnixSocketConnector.cpp | 37 ++++++---- dom/bluetooth/BluetoothUnixSocketConnector.h | 6 +- ipc/ril/Ril.cpp | 68 +++++++++---------- ipc/unixsocket/UnixSocket.cpp | 20 ++++-- ipc/unixsocket/UnixSocket.h | 28 +++++++- 5 files changed, 95 insertions(+), 64 deletions(-) diff --git a/dom/bluetooth/BluetoothUnixSocketConnector.cpp b/dom/bluetooth/BluetoothUnixSocketConnector.cpp index 27b003593596..327870d6fbea 100644 --- a/dom/bluetooth/BluetoothUnixSocketConnector.cpp +++ b/dom/bluetooth/BluetoothUnixSocketConnector.cpp @@ -35,6 +35,7 @@ #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 @@ -139,10 +140,10 @@ BluetoothUnixSocketConnector::Create() 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. @@ -151,7 +152,7 @@ BluetoothUnixSocketConnector::CreateAddr(bool aIsServer, if (!aIsServer && aAddress && strlen(aAddress) > 0) { if (get_bdaddr(aAddress, &bd_address_obj)) { NS_WARNING("Can't get bluetooth address!"); - return; + return false; } } @@ -159,31 +160,37 @@ BluetoothUnixSocketConnector::CreateAddr(bool aIsServer, 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); } diff --git a/dom/bluetooth/BluetoothUnixSocketConnector.h b/dom/bluetooth/BluetoothUnixSocketConnector.h index 89252b80dd7e..e46a9bd78f55 100644 --- a/dom/bluetooth/BluetoothUnixSocketConnector.h +++ b/dom/bluetooth/BluetoothUnixSocketConnector.h @@ -21,12 +21,12 @@ public: 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: diff --git a/ipc/ril/Ril.cpp b/ipc/ril/Ril.cpp index bdcde63c7ccb..bb44a2b052af 100644 --- a/ipc/ril/Ril.cpp +++ b/ipc/ril/Ril.cpp @@ -71,12 +71,12 @@ public: {} 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: @@ -93,12 +93,8 @@ RilConnector::Create() #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) { @@ -112,41 +108,41 @@ RilConnector::Create() 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; - } - - 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); + 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; + } + return true; } bool @@ -157,7 +153,7 @@ RilConnector::SetUp(int aFd) } void -RilConnector::GetSocketAddr(const sockaddr& aAddr, +RilConnector::GetSocketAddr(const sockaddr_any& aAddr, nsAString& aAddrStr) { // Unused. diff --git a/ipc/unixsocket/UnixSocket.cpp b/ipc/unixsocket/UnixSocket.cpp index 57c0ad15d0af..0054143e8386 100644 --- a/ipc/unixsocket/UnixSocket.cpp +++ b/ipc/unixsocket/UnixSocket.cpp @@ -218,7 +218,7 @@ private: /** * Address struct of the socket currently in use */ - sockaddr mAddr; + sockaddr_any mAddr; }; template @@ -441,9 +441,12 @@ UnixSocketImpl::Accept() // 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) { @@ -454,7 +457,7 @@ UnixSocketImpl::Accept() 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 @@ -493,9 +496,12 @@ UnixSocketImpl::Connect() 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 @@ -660,7 +666,7 @@ UnixSocketImpl::OnFileCanReadWithoutBlocking(int aFd) } 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; diff --git a/ipc/unixsocket/UnixSocket.h b/ipc/unixsocket/UnixSocket.h index 6fecbae51075..058159807920 100644 --- a/ipc/unixsocket/UnixSocket.h +++ b/ipc/unixsocket/UnixSocket.h @@ -7,7 +7,15 @@ #ifndef mozilla_ipc_UnixSocket_h #define mozilla_ipc_UnixSocket_h + #include +#include +#include +#ifdef MOZ_B2G_BT +#include +#include +#include +#endif #include #include "nsString.h" #include "nsAutoPtr.h" @@ -16,6 +24,18 @@ 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: @@ -78,10 +98,12 @@ public: * @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; /** @@ -100,7 +122,7 @@ public: * @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; };