diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index f4725639949..528e121b45e 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,15 +15,15 @@ - + - + - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 218c4d5fd5f..c6b682a2e91 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,15 +15,15 @@ - + - + - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 0a0a3c36ea8..734631a7c94 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,8 +19,8 @@ - - + + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 508f0bb9107..2070ced2909 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,10 +17,10 @@ - - + + - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 39f45586c70..73c497efdba 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,15 +15,15 @@ - + - + - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 2bd4ee19062..b7ad9ace7bb 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,15 +15,15 @@ - + - + - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 0a0a3c36ea8..734631a7c94 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,8 +19,8 @@ - - + + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index f3cd317a8d4..1b9e7974971 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,15 +15,15 @@ - + - + - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 871f6ede654..79c7e328a48 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "97dc139f1a690224e98533a86526c4165eed1db5", + "git_revision": "600fd8249960b8256af9de67d9171025bb9a3ff3", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "8fa0242e0aa7c8e126dec5fb6811f6137616c87e", + "revision": "c2b9d5ec23830d9e360ca665ffe4d60195f60c91", "repo_path": "integration/gaia-central" } diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 096d920cf79..c4c1cbe75ce 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,10 +17,10 @@ - - + + - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 048db8d119e..8dbab3baccf 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,15 +15,15 @@ - + - + - + diff --git a/dom/bluetooth/BluetoothUtils.cpp b/dom/bluetooth/BluetoothUtils.cpp index b52356e5ec5..a3f1a834e23 100644 --- a/dom/bluetooth/BluetoothUtils.cpp +++ b/dom/bluetooth/BluetoothUtils.cpp @@ -270,7 +270,6 @@ BroadcastSystemMessage(const nsAString& aType, return true; } -#ifdef MOZ_B2G_BT_API_V2 void DispatchReplySuccess(BluetoothReplyRunnable* aRunnable) { @@ -297,8 +296,14 @@ DispatchReplyError(BluetoothReplyRunnable* aRunnable, MOZ_ASSERT(aRunnable); MOZ_ASSERT(!aErrorStr.IsEmpty()); + // Reply will be deleted by the runnable after running on main thread +#if MOZ_B2G_BT_API_V2 BluetoothReply* reply = new BluetoothReply(BluetoothReplyError(STATUS_FAIL, nsString(aErrorStr))); +#else + BluetoothReply* reply = + new BluetoothReply(BluetoothReplyError(nsString(aErrorStr))); +#endif aRunnable->SetReply(reply); // runnable will delete reply after Run() NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(aRunnable))); @@ -311,8 +316,15 @@ DispatchReplyError(BluetoothReplyRunnable* aRunnable, MOZ_ASSERT(aRunnable); MOZ_ASSERT(aStatus != STATUS_SUCCESS); + // Reply will be deleted by the runnable after running on main thread +#if MOZ_B2G_BT_API_V2 BluetoothReply* reply = new BluetoothReply(BluetoothReplyError(aStatus, EmptyString())); +#else + BluetoothReply* reply = + new BluetoothReply( + BluetoothReplyError(NS_LITERAL_STRING("Internal error"))); +#endif aRunnable->SetReply(reply); // runnable will delete reply after Run() NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(aRunnable))); @@ -331,50 +343,14 @@ DispatchStatusChangedEvent(const nsAString& aType, BluetoothService* bs = BluetoothService::Get(); NS_ENSURE_TRUE_VOID(bs); + +#ifdef MOZ_B2G_BT_API_V2 bs->DistributeSignal(aType, NS_LITERAL_STRING(KEY_ADAPTER), data); -} #else -// TODO: remove with bluetooth1 -void -DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, - const BluetoothValue& aValue, - const nsAString& aErrorStr) -{ - // Reply will be deleted by the runnable after running on main thread - BluetoothReply* reply; - if (!aErrorStr.IsEmpty()) { - nsString err(aErrorStr); - reply = new BluetoothReply(BluetoothReplyError(err)); - } else { - MOZ_ASSERT(aValue.type() != BluetoothValue::T__None); - reply = new BluetoothReply(BluetoothReplySuccess(aValue)); - } - - aRunnable->SetReply(reply); - if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } -} - -// TODO: remove with bluetooth1 -void -DispatchStatusChangedEvent(const nsAString& aType, - const nsAString& aAddress, - bool aStatus) -{ - MOZ_ASSERT(NS_IsMainThread()); - - InfallibleTArray data; - BT_APPEND_NAMED_VALUE(data, "address", nsString(aAddress)); - BT_APPEND_NAMED_VALUE(data, "status", aStatus); - BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data); - - BluetoothService* bs = BluetoothService::Get(); - NS_ENSURE_TRUE_VOID(bs); bs->DistributeSignal(signal); -} #endif +} bool IsMainProcess() diff --git a/dom/bluetooth/BluetoothUtils.h b/dom/bluetooth/BluetoothUtils.h index 1b231376d49..666a94094c3 100644 --- a/dom/bluetooth/BluetoothUtils.h +++ b/dom/bluetooth/BluetoothUtils.h @@ -127,7 +127,6 @@ BroadcastSystemMessage(const nsAString& aType, // Dispatch bluetooth reply to main thread // -#ifdef MOZ_B2G_BT_API_V2 /** * Dispatch successful bluetooth reply with NO value to reply request. * @@ -177,19 +176,6 @@ DispatchReplyError(BluetoothReplyRunnable* aRunnable, void DispatchReplyError(BluetoothReplyRunnable* aRunnable, const enum BluetoothStatus aStatus); -#else -// TODO: remove with bluetooth1 -void -DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, - const BluetoothValue& aValue, - const nsAString& aErrorStr); - -// TODO: remove with bluetooth1 -void -DispatchStatusChangedEvent(const nsAString& aType, - const nsAString& aDeviceAddress, - bool aStatus); -#endif void DispatchStatusChangedEvent(const nsAString& aType, diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp new file mode 100644 index 00000000000..a526fca396e --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp @@ -0,0 +1,174 @@ +/* -*- 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 +#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(&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(&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; +} + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonConnector.h b/dom/bluetooth/bluedroid/BluetoothDaemonConnector.h new file mode 100644 index 00000000000..c3f014294f4 --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothDaemonConnector.h @@ -0,0 +1,54 @@ +/* -*- 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; + +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 diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp index 91046bd744c..5b20efd8117 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp @@ -10,13 +10,13 @@ #include #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" @@ -2018,78 +2018,6 @@ BluetoothDaemonInterface::OnDisconnect(enum Channel aChannel) } } -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, @@ -2209,7 +2137,7 @@ BluetoothDaemonInterface::Init( } bool success = mListenSocket->Listen( - new BluetoothDaemonSocketConnector(mListenSocketName), mCmdChannel); + new BluetoothDaemonConnector(mListenSocketName), mCmdChannel); if (!success) { OnConnectError(CMD_CHANNEL); return; diff --git a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp index c3f2eb41e3c..cd1f74b2ba9 100644 --- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp +++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp @@ -45,8 +45,6 @@ #include "nsDataHashtable.h" #endif -#ifdef MOZ_B2G_BT_API_V2 - #define ENSURE_BLUETOOTH_IS_READY(runnable, result) \ do { \ if (!sBtInterface || !IsEnabled()) { \ @@ -65,6 +63,8 @@ } \ } while(0) +#ifdef MOZ_B2G_BT_API_V2 + #define ENSURE_GATT_MGR_IS_READY_VOID(gatt, runnable) \ do { \ if (!gatt) { \ @@ -594,24 +594,6 @@ BluetoothServiceBluedroid::GattClientWriteDescriptorValueInternal( } #else -#define ENSURE_BLUETOOTH_IS_READY(runnable, result) \ - do { \ - if (!sBtInterface || !IsEnabled()) { \ - NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth is not ready"); \ - DispatchBluetoothReply(runnable, BluetoothValue(), errorStr); \ - return result; \ - } \ - } while(0) - -#define ENSURE_BLUETOOTH_IS_READY_VOID(runnable) \ - do { \ - if (!sBtInterface || !IsEnabled()) { \ - NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth is not ready"); \ - DispatchBluetoothReply(runnable, BluetoothValue(), errorStr); \ - return; \ - } \ - } while(0) - // Audio: Major service class = 0x100 (Bit 21 is set) #define SET_AUDIO_BIT(cod) (cod |= 0x200000) // Rendering: Major service class = 0x20 (Bit 18 is set) @@ -936,8 +918,7 @@ ReplyStatusError(BluetoothReplyRunnable* aBluetoothReplyRunnable, replyError.AppendLiteral(":BT_STATUS_FAIL"); } - DispatchBluetoothReply(aBluetoothReplyRunnable, BluetoothValue(true), - replyError); + DispatchReplyError(aBluetoothReplyRunnable, replyError); } /** @@ -1057,7 +1038,7 @@ BluetoothServiceBluedroid::GetDefaultAdapterPathInternal( BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(), "Devices", sAdapterBondedAddressArray); - DispatchBluetoothReply(aRunnable, v, EmptyString()); + DispatchReplySuccess(aRunnable, v); return NS_OK; } @@ -1098,8 +1079,7 @@ public: /* dispatch result after final pending operation */ if (--sRequestedDeviceCountArray[0] == 0) { if (!sGetDeviceRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sGetDeviceRunnableArray[0], - sRemoteDevicesPack, EmptyString()); + DispatchReplySuccess(sGetDeviceRunnableArray[0], sRemoteDevicesPack); sGetDeviceRunnableArray.RemoveElementAt(0); } @@ -1147,8 +1127,7 @@ BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal( BluetoothUuidHelper::GetBluetoothProfileManager(aServiceUuid); if (!profile) { InfallibleTArray emptyArr; - DispatchBluetoothReply(aRunnable, emptyArr, - NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE)); + DispatchReplyError(aRunnable, NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE)); return NS_OK; } @@ -1162,7 +1141,7 @@ BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal( int requestedDeviceCount = deviceAddresses.Length(); if (requestedDeviceCount == 0) { InfallibleTArray emptyArr; - DispatchBluetoothReply(aRunnable, emptyArr, EmptyString()); + DispatchReplySuccess(aRunnable, emptyArr); return NS_OK; } #endif @@ -1196,8 +1175,7 @@ BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal( #else int requestedDeviceCount = aDeviceAddress.Length(); if (requestedDeviceCount == 0) { - InfallibleTArray emptyArr; - DispatchBluetoothReply(aRunnable, BluetoothValue(emptyArr), EmptyString()); + DispatchReplySuccess(aRunnable, InfallibleTArray()); return NS_OK; } @@ -1233,7 +1211,7 @@ public: void StartDiscovery() override { MOZ_ASSERT(NS_IsMainThread()); - DispatchBluetoothReply(mRunnable, true, EmptyString()); + DispatchReplySuccess(mRunnable); } void OnError(BluetoothStatus aStatus) override @@ -1282,7 +1260,7 @@ public: void CancelDiscovery() override { MOZ_ASSERT(NS_IsMainThread()); - DispatchBluetoothReply(mRunnable, true, EmptyString()); + DispatchReplySuccess(mRunnable); } void OnError(BluetoothStatus aStatus) override @@ -1552,7 +1530,7 @@ public: void PinReply() override { - DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString()); + DispatchReplySuccess(mRunnable); } void OnError(BluetoothStatus aStatus) override @@ -1652,7 +1630,7 @@ public: void SspReply() override { - DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString()); + DispatchReplySuccess(mRunnable); } void OnError(BluetoothStatus aStatus) override @@ -1785,10 +1763,10 @@ BluetoothServiceBluedroid::IsConnected(const uint16_t aServiceUuid, BluetoothProfileManagerBase* profile = BluetoothUuidHelper::GetBluetoothProfileManager(aServiceUuid); if (profile) { - DispatchBluetoothReply(aRunnable, profile->IsConnected(), EmptyString()); + DispatchReplySuccess(aRunnable, profile->IsConnected()); } else { BT_WARNING("Can't find profile manager with uuid: %x", aServiceUuid); - DispatchBluetoothReply(aRunnable, false, EmptyString()); + DispatchReplySuccess(aRunnable, false); } } #endif @@ -1806,7 +1784,6 @@ BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress, // has been determined when calling 'Connect()'. Nevertheless, keep // it for future use. -#ifdef MOZ_B2G_BT_API_V2 BluetoothOppManager* opp = BluetoothOppManager::Get(); if (!opp || !opp->SendFile(aDeviceAddress, aBlobParent)) { DispatchReplyError(aRunnable, NS_LITERAL_STRING("SendFile failed")); @@ -1814,15 +1791,6 @@ BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress, } DispatchReplySuccess(aRunnable); -#else - BluetoothOppManager* opp = BluetoothOppManager::Get(); - nsAutoString errorStr; - if (!opp || !opp->SendFile(aDeviceAddress, aBlobParent)) { - errorStr.AssignLiteral("Calling SendFile() failed"); - } - - DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr); -#endif } void @@ -1837,7 +1805,6 @@ BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress, // has been determined when calling 'Connect()'. Nevertheless, keep // it for future use. -#ifdef MOZ_B2G_BT_API_V2 BluetoothOppManager* opp = BluetoothOppManager::Get(); if (!opp || !opp->SendFile(aDeviceAddress, aBlob)) { DispatchReplyError(aRunnable, NS_LITERAL_STRING("SendFile failed")); @@ -1845,15 +1812,6 @@ BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress, } DispatchReplySuccess(aRunnable); -#else - BluetoothOppManager* opp = BluetoothOppManager::Get(); - nsAutoString errorStr; - if (!opp || !opp->SendFile(aDeviceAddress, aBlob)) { - errorStr.AssignLiteral("Calling SendFile() failed"); - } - - DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr); -#endif } void @@ -1867,7 +1825,6 @@ BluetoothServiceBluedroid::StopSendingFile(const nsAString& aDeviceAddress, // has been determined when calling 'Connect()'. Nevertheless, keep // it for future use. -#ifdef MOZ_B2G_BT_API_V2 BluetoothOppManager* opp = BluetoothOppManager::Get(); nsAutoString errorStr; if (!opp || !opp->StopSendingFile()) { @@ -1876,15 +1833,6 @@ BluetoothServiceBluedroid::StopSendingFile(const nsAString& aDeviceAddress, } DispatchReplySuccess(aRunnable); -#else - BluetoothOppManager* opp = BluetoothOppManager::Get(); - nsAutoString errorStr; - if (!opp || !opp->StopSendingFile()) { - errorStr.AssignLiteral("Calling StopSendingFile() failed"); - } - - DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr); -#endif } void @@ -1899,7 +1847,6 @@ BluetoothServiceBluedroid::ConfirmReceivingFile( // has been determined when calling 'Connect()'. Nevertheless, keep // it for future use. -#ifdef MOZ_B2G_BT_API_V2 BluetoothOppManager* opp = BluetoothOppManager::Get(); nsAutoString errorStr; if (!opp || !opp->ConfirmReceivingFile(aConfirm)) { @@ -1909,15 +1856,6 @@ BluetoothServiceBluedroid::ConfirmReceivingFile( } DispatchReplySuccess(aRunnable); -#else - BluetoothOppManager* opp = BluetoothOppManager::Get(); - nsAutoString errorStr; - if (!opp || !opp->ConfirmReceivingFile(aConfirm)) { - errorStr.AssignLiteral("Calling ConfirmReceivingFile() failed"); - } - - DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr); -#endif } void @@ -1925,7 +1863,6 @@ BluetoothServiceBluedroid::ConnectSco(BluetoothReplyRunnable* aRunnable) { MOZ_ASSERT(NS_IsMainThread()); -#ifdef MOZ_B2G_BT_API_V2 BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); if (!hfp || !hfp->ConnectSco()) { DispatchReplyError(aRunnable, NS_LITERAL_STRING("ConnectSco failed")); @@ -1933,16 +1870,6 @@ BluetoothServiceBluedroid::ConnectSco(BluetoothReplyRunnable* aRunnable) } DispatchReplySuccess(aRunnable); -#else - BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); - if (!hfp || !hfp->ConnectSco()) { - NS_NAMED_LITERAL_STRING(replyError, "Calling ConnectSco() failed"); - DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError); - return; - } - - DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString()); -#endif } void @@ -1950,7 +1877,6 @@ BluetoothServiceBluedroid::DisconnectSco(BluetoothReplyRunnable* aRunnable) { MOZ_ASSERT(NS_IsMainThread()); -#ifdef MOZ_B2G_BT_API_V2 BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); if (!hfp || !hfp->DisconnectSco()) { DispatchReplyError(aRunnable, NS_LITERAL_STRING("DisconnectSco failed")); @@ -1958,16 +1884,6 @@ BluetoothServiceBluedroid::DisconnectSco(BluetoothReplyRunnable* aRunnable) } DispatchReplySuccess(aRunnable); -#else - BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); - if (!hfp || !hfp->DisconnectSco()) { - NS_NAMED_LITERAL_STRING(replyError, "Calling DisconnectSco() failed"); - DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError); - return; - } - - DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString()); -#endif } void @@ -1975,7 +1891,6 @@ BluetoothServiceBluedroid::IsScoConnected(BluetoothReplyRunnable* aRunnable) { MOZ_ASSERT(NS_IsMainThread()); -#ifdef MOZ_B2G_BT_API_V2 BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); if (!hfp) { DispatchReplyError(aRunnable, NS_LITERAL_STRING("IsScoConnected failed")); @@ -1983,16 +1898,6 @@ BluetoothServiceBluedroid::IsScoConnected(BluetoothReplyRunnable* aRunnable) } DispatchReplySuccess(aRunnable, BluetoothValue(hfp->IsScoConnected())); -#else - BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); - if (!hfp) { - NS_NAMED_LITERAL_STRING(replyError, "Fail to get BluetoothHfpManager"); - DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError); - return; - } - - DispatchBluetoothReply(aRunnable, hfp->IsScoConnected(), EmptyString()); -#endif } void @@ -2009,11 +1914,7 @@ BluetoothServiceBluedroid::SendMetaData(const nsAString& aTitle, a2dp->UpdateMetaData(aTitle, aArtist, aAlbum, aMediaNumber, aTotalMediaCount, aDuration); } -#ifdef MOZ_B2G_BT_API_V2 DispatchReplySuccess(aRunnable); -#else - DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString()); -#endif } void @@ -2028,11 +1929,7 @@ BluetoothServiceBluedroid::SendPlayStatus( PlayStatusStringToControlPlayStatus(aPlayStatus); a2dp->UpdatePlayStatus(aDuration, aPosition, playStatus); } -#ifdef MOZ_B2G_BT_API_V2 DispatchReplySuccess(aRunnable); -#else - DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString()); -#endif } void @@ -2491,8 +2388,7 @@ BluetoothServiceBluedroid::AdapterPropertiesNotification( // Send reply for SetProperty if (!sSetPropertyRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sSetPropertyRunnableArray[0], - BluetoothValue(true), EmptyString()); + DispatchReplySuccess(sSetPropertyRunnableArray[0]); sSetPropertyRunnableArray.RemoveElementAt(0); } #endif @@ -2699,8 +2595,7 @@ BluetoothServiceBluedroid::RemoteDevicePropertiesNotification( if (--sRequestedDeviceCountArray[0] == 0) { if (!sGetDeviceRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sGetDeviceRunnableArray[0], - sRemoteDevicesPack, EmptyString()); + DispatchReplySuccess(sGetDeviceRunnableArray[0], sRemoteDevicesPack); sGetDeviceRunnableArray.RemoveElementAt(0); } @@ -3066,13 +2961,11 @@ BluetoothServiceBluedroid::BondStateChangedNotification( BluetoothValue(propertiesChangeArray))); if (bonded && !sBondingRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sBondingRunnableArray[0], - BluetoothValue(true), EmptyString()); + DispatchReplySuccess(sBondingRunnableArray[0]); sBondingRunnableArray.RemoveElementAt(0); } else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sUnbondingRunnableArray[0], - BluetoothValue(true), EmptyString()); + DispatchReplySuccess(sUnbondingRunnableArray[0]); sUnbondingRunnableArray.RemoveElementAt(0); } @@ -3098,9 +2991,8 @@ BluetoothServiceBluedroid::BondStateChangedNotification( BluetoothValue(propertiesArray))); if (!sBondingRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sBondingRunnableArray[0], - BluetoothValue(true), - NS_LITERAL_STRING("Authentication failure")); + DispatchReplyError(sBondingRunnableArray[0], + NS_LITERAL_STRING("Authentication failure")); sBondingRunnableArray.RemoveElementAt(0); } break; @@ -3109,9 +3001,8 @@ BluetoothServiceBluedroid::BondStateChangedNotification( BT_WARNING("Got an unhandled status of BondStateChangedCallback!"); // Dispatch a reply to unblock the waiting status of pairing. if (!sBondingRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sBondingRunnableArray[0], - BluetoothValue(true), - NS_LITERAL_STRING("Internal failure")); + DispatchReplyError(sBondingRunnableArray[0], + NS_LITERAL_STRING("Internal failure")); sBondingRunnableArray.RemoveElementAt(0); } break; diff --git a/dom/bluetooth/bluetooth1/BluetoothProfileController.cpp b/dom/bluetooth/bluetooth1/BluetoothProfileController.cpp index b63b2ccd53c..bdf017a5b72 100644 --- a/dom/bluetooth/bluetooth1/BluetoothProfileController.cpp +++ b/dom/bluetooth/bluetooth1/BluetoothProfileController.cpp @@ -116,8 +116,7 @@ BluetoothProfileController::AddProfileWithServiceClass( profile = BluetoothHidManager::Get(); break; default: - DispatchBluetoothReply(mRunnable, BluetoothValue(), - NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE)); + DispatchReplyError(mRunnable, NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE)); mCallback(); return; } @@ -130,8 +129,8 @@ BluetoothProfileController::AddProfile(BluetoothProfileManagerBase* aProfile, bool aCheckConnected) { if (!aProfile) { - DispatchBluetoothReply(mRunnable, BluetoothValue(), - NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE)); + DispatchReplyError(mRunnable, + NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE)); mCallback(); return; } @@ -266,13 +265,11 @@ BluetoothProfileController::EndSession() // The action has completed, so the DOM request should be replied then invoke // the callback. if (mSuccess) { - DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString()); + DispatchReplySuccess(mRunnable); } else if (mConnect) { - DispatchBluetoothReply(mRunnable, BluetoothValue(true), - NS_LITERAL_STRING(ERR_CONNECTION_FAILED)); + DispatchReplyError(mRunnable, NS_LITERAL_STRING(ERR_CONNECTION_FAILED)); } else { - DispatchBluetoothReply(mRunnable, BluetoothValue(true), - NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED)); + DispatchReplyError(mRunnable, NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED)); } mCallback(); diff --git a/dom/bluetooth/bluez/BluetoothDBusService.cpp b/dom/bluetooth/bluez/BluetoothDBusService.cpp index a43887267f4..7136d9f461b 100644 --- a/dom/bluetooth/bluez/BluetoothDBusService.cpp +++ b/dom/bluetooth/bluez/BluetoothDBusService.cpp @@ -420,7 +420,6 @@ DispatchToBtThread(nsIRunnable* aRunnable) return sBluetoothThread->Dispatch(aRunnable, NS_DISPATCH_NORMAL); } -#ifdef MOZ_B2G_BT_API_V2 static void DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, const BluetoothValue& aValue, @@ -432,9 +431,6 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, DispatchReplySuccess(aRunnable, aValue); } } -#else -// Missing in bluetooth1 -#endif BluetoothDBusService::BluetoothDBusService() { @@ -4698,14 +4694,14 @@ BluetoothDBusService::UpdateNotification(ControlEventId aEventId, void BluetoothDBusService::StartLeScanInternal( const nsTArray& aServiceUuids, - BluetoothReplyRunnable* aRunnable); + BluetoothReplyRunnable* aRunnable) { } void BluetoothDBusService::StopLeScanInternal( const nsAString& aAppUuid, - BluetoothReplyRunnable* aRunnable); + BluetoothReplyRunnable* aRunnable) { } diff --git a/dom/bluetooth/bluez/BluetoothHfpManager.cpp b/dom/bluetooth/bluez/BluetoothHfpManager.cpp index b6982807f7d..283a864ca99 100644 --- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp +++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp @@ -1916,12 +1916,7 @@ BluetoothHfpManager::OnScoConnectSuccess() { // For active connection request, we need to reply the DOMRequest if (mScoRunnable) { -#ifdef MOZ_B2G_BT_API_V2 DispatchReplySuccess(mScoRunnable); -#else - DispatchBluetoothReply(mScoRunnable, - BluetoothValue(true), EmptyString()); -#endif mScoRunnable = nullptr; } @@ -1935,13 +1930,8 @@ void BluetoothHfpManager::OnScoConnectError() { if (mScoRunnable) { -#ifdef MOZ_B2G_BT_API_V2 DispatchReplyError(mScoRunnable, NS_LITERAL_STRING("Failed to create SCO socket!")); -#else - NS_NAMED_LITERAL_STRING(replyError, "Failed to create SCO socket!"); - DispatchBluetoothReply(mScoRunnable, BluetoothValue(), replyError); -#endif mScoRunnable = nullptr; } diff --git a/dom/bluetooth/bluez/BluetoothSocket.cpp b/dom/bluetooth/bluez/BluetoothSocket.cpp index 27b5d50d32f..02f573de6d9 100644 --- a/dom/bluetooth/bluez/BluetoothSocket.cpp +++ b/dom/bluetooth/bluez/BluetoothSocket.cpp @@ -30,11 +30,10 @@ class BluetoothSocket::BluetoothSocketIO final public: BluetoothSocketIO(MessageLoop* mIOLoop, BluetoothSocket* aConsumer, - UnixSocketConnector* aConnector, - const nsACString& aAddress); + UnixSocketConnector* aConnector); ~BluetoothSocketIO(); - void GetSocketAddr(nsAString& aAddrStr) const; + void GetSocketAddr(nsAString& aAddrStr) const; BluetoothSocket* GetBluetoothSocket(); DataSocket* GetDataSocket(); @@ -94,9 +93,6 @@ private: void FireSocketError(); - // Set up flags on file descriptor. - static bool SetSocketFlags(int aFd); - /** * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated * directly from main thread. All non-main-thread accesses should happen with @@ -115,19 +111,14 @@ private: bool mShuttingDownOnIOThread; /** - * Address we are connecting to, assuming we are creating a client connection. + * Number of valid bytes in |mAddress| */ - nsCString mAddress; + socklen_t mAddressLength; /** - * Size of the socket address struct + * Address structure of the socket currently in use */ - socklen_t mAddrSize; - - /** - * Address struct of the socket currently in use - */ - sockaddr_any mAddr; + struct sockaddr_storage mAddress; /** * Task member for delayed connect task. Should only be access on main thread. @@ -143,13 +134,12 @@ private: BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO( MessageLoop* mIOLoop, BluetoothSocket* aConsumer, - UnixSocketConnector* aConnector, - const nsACString& aAddress) + UnixSocketConnector* aConnector) : UnixSocketWatcher(mIOLoop) , mConsumer(aConsumer) , mConnector(aConnector) , mShuttingDownOnIOThread(false) - , mAddress(aAddress) + , mAddressLength(0) , mDelayedConnectTask(nullptr) { MOZ_ASSERT(mConsumer); @@ -170,7 +160,17 @@ BluetoothSocket::BluetoothSocketIO::GetSocketAddr(nsAString& aAddrStr) const aAddrStr.Truncate(); return; } - mConnector->GetSocketAddr(mAddr, aAddrStr); + + nsCString addressString; + nsresult rv = mConnector->ConvertAddressToString( + *reinterpret_cast(&mAddress), mAddressLength, + addressString); + if (NS_FAILED(rv)) { + aAddrStr.Truncate(); + return; + } + + aAddrStr.Assign(NS_ConvertUTF8toUTF16(addressString)); } BluetoothSocket* @@ -221,34 +221,20 @@ BluetoothSocket::BluetoothSocketIO::Listen() MOZ_ASSERT(mConnector); if (!IsOpen()) { - int fd = mConnector->Create(); - if (fd < 0) { - NS_WARNING("Cannot create socket fd!"); - FireSocketError(); - return; - } - if (!SetSocketFlags(fd)) { - NS_WARNING("Cannot set socket flags!"); - FireSocketError(); - return; - } - if (!mConnector->SetUpListenSocket(fd)) { - NS_WARNING("Could not set up listen socket!"); - FireSocketError(); - 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. - if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) { - NS_WARNING("Cannot create socket address!"); + mAddressLength = sizeof(mAddress); + + int fd; + nsresult rv = mConnector->CreateListenSocket( + reinterpret_cast(&mAddress), &mAddressLength, fd); + if (NS_WARN_IF(NS_FAILED(rv))) { FireSocketError(); return; } SetFd(fd); // calls OnListening on success, or OnError otherwise - nsresult rv = UnixSocketWatcher::Listen( - reinterpret_cast(&mAddr), mAddrSize); + rv = UnixSocketWatcher::Listen( + reinterpret_cast(&mAddress), mAddressLength); NS_WARN_IF(NS_FAILED(rv)); } } @@ -260,24 +246,12 @@ BluetoothSocket::BluetoothSocketIO::Connect() MOZ_ASSERT(mConnector); if (!IsOpen()) { - int fd = mConnector->Create(); - if (fd < 0) { - NS_WARNING("Cannot create socket fd!"); - FireSocketError(); - return; - } - if (!SetSocketFlags(fd)) { - NS_WARNING("Cannot set socket flags!"); - FireSocketError(); - return; - } - if (!mConnector->SetUp(fd)) { - NS_WARNING("Could not set up socket!"); - FireSocketError(); - return; - } - if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) { - NS_WARNING("Cannot create socket address!"); + mAddressLength = sizeof(mAddress); + + int fd; + nsresult rv = mConnector->CreateStreamSocket( + reinterpret_cast(&mAddress), &mAddressLength, fd); + if (NS_WARN_IF(NS_FAILED(rv))) { FireSocketError(); return; } @@ -286,7 +260,7 @@ BluetoothSocket::BluetoothSocketIO::Connect() // calls OnConnected() on success, or OnError() otherwise nsresult rv = UnixSocketWatcher::Connect( - reinterpret_cast(&mAddr), mAddrSize); + reinterpret_cast(&mAddress), mAddressLength); NS_WARN_IF(NS_FAILED(rv)); } @@ -338,18 +312,14 @@ BluetoothSocket::BluetoothSocketIO::OnSocketCanAcceptWithoutBlocking() RemoveWatchers(READ_WATCHER|WRITE_WATCHER); - socklen_t mAddrSize = sizeof(mAddr); - int fd = TEMP_FAILURE_RETRY(accept(GetFd(), - reinterpret_cast(&mAddr), &mAddrSize)); - if (fd < 0) { - OnError("accept", errno); - return; - } - if (!SetSocketFlags(fd)) { - return; - } - if (!mConnector->SetUp(fd)) { - NS_WARNING("Could not set up socket!"); + mAddressLength = sizeof(mAddress); + + int fd; + nsresult rv = mConnector->AcceptStreamSocket( + GetFd(), + reinterpret_cast(&mAddress), &mAddressLength, fd); + if (NS_WARN_IF(NS_FAILED(rv))) { + FireSocketError(); return; } @@ -411,38 +381,6 @@ BluetoothSocket::BluetoothSocketIO::FireSocketError() } -bool -BluetoothSocket::BluetoothSocketIO::SetSocketFlags(int aFd) -{ - // Set socket addr to be reused even if kernel is still waiting to close - int n = 1; - if (setsockopt(aFd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) < 0) { - return false; - } - - // Set close-on-exec bit. - int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFD)); - if (-1 == flags) { - return false; - } - flags |= FD_CLOEXEC; - if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFD, flags))) { - return false; - } - - // Set non-blocking status flag. - flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL)); - if (-1 == flags) { - return false; - } - flags |= O_NONBLOCK; - if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, flags))) { - return false; - } - - return true; -} - // |DataSocketIO| nsresult @@ -646,7 +584,8 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress, MOZ_ASSERT(!aDeviceAddress.IsEmpty()); nsAutoPtr c( - new BluetoothUnixSocketConnector(mType, aChannel, mAuth, mEncrypt)); + new BluetoothUnixSocketConnector(NS_ConvertUTF16toUTF8(aDeviceAddress), + mType, aChannel, mAuth, mEncrypt)); if (!ConnectSocket(c.forget(), NS_ConvertUTF16toUTF8(aDeviceAddress).BeginReading())) { @@ -668,7 +607,8 @@ BluetoothSocket::Listen(const nsAString& aServiceName, MOZ_ASSERT(NS_IsMainThread()); nsAutoPtr c( - new BluetoothUnixSocketConnector(mType, aChannel, mAuth, mEncrypt)); + new BluetoothUnixSocketConnector(NS_LITERAL_CSTRING(BLUETOOTH_ADDRESS_NONE), + mType, aChannel, mAuth, mEncrypt)); if (!ListenSocket(c.forget())) { nsAutoString addr; @@ -728,9 +668,8 @@ BluetoothSocket::ConnectSocket(BluetoothUnixSocketConnector* aConnector, return false; } - nsCString addr(aAddress); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); - mIO = new BluetoothSocketIO(ioLoop, this, connector.forget(), addr); + mIO = new BluetoothSocketIO(ioLoop, this, connector.forget()); SetConnectionStatus(SOCKET_CONNECTING); if (aDelayMs > 0) { DelayedConnectTask* connectTask = new DelayedConnectTask(mIO); @@ -755,10 +694,12 @@ BluetoothSocket::ListenSocket(BluetoothUnixSocketConnector* aConnector) return false; } - mIO = new BluetoothSocketIO( - XRE_GetIOMessageLoop(), this, connector.forget(), EmptyCString()); + MessageLoop* ioLoop = XRE_GetIOMessageLoop(); + + mIO = new BluetoothSocketIO(ioLoop, this, connector.forget()); SetConnectionStatus(SOCKET_LISTENING); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ListenTask(mIO)); + ioLoop->PostTask(FROM_HERE, new ListenTask(mIO)); + return true; } diff --git a/dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp b/dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp index bb980dec314..f9fbfbdf8de 100644 --- a/dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp +++ b/dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp @@ -1,5 +1,6 @@ /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ + /* * Copyright 2009, The Android Open Source Project * @@ -15,123 +16,175 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * NOTE: Due to being based on the dbus compatibility layer for - * android's bluetooth implementation, this file is licensed under the - * apache license instead of MPL. - * + * NOTE: Due to being based on the D-Bus compatibility layer for + * Android's Bluetooth implementation, this file is licensed under the + * Apache License instead of MPL. */ -#include -#include -#include -#include - -#include -#ifdef MOZ_B2G_BT_BLUEZ +#include "BluetoothUnixSocketConnector.h" #include #include #include #include -#endif -#include "BluetoothUnixSocketConnector.h" -#include "nsThreadUtils.h" +#include +#include +#include +#include +#include +#include "nsThreadUtils.h" // For NS_IsMainThread. using namespace mozilla::ipc; -USING_BLUETOOTH_NAMESPACE + +BEGIN_BLUETOOTH_NAMESPACE static const int RFCOMM_SO_SNDBUF = 70 * 1024; // 70 KB send buffer static const int L2CAP_SO_SNDBUF = 400 * 1024; // 400 KB send buffer static const int L2CAP_SO_RCVBUF = 400 * 1024; // 400 KB receive buffer static const int L2CAP_MAX_MTU = 65000; -#ifdef MOZ_B2G_BT_BLUEZ -static -int get_bdaddr(const char *str, bdaddr_t *ba) -{ - char *d = ((char*)ba) + 5, *endp; - for (int i = 0; i < 6; i++) { - *d-- = strtol(str, &endp, 16); - MOZ_ASSERT(!(*endp != ':' && i != 5)); - str = endp + 1; - } - return 0; -} - -static -void get_bdaddr_as_string(const bdaddr_t *ba, char *str) { - const uint8_t *b = (const uint8_t *)ba; - sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - b[5], b[4], b[3], b[2], b[1], b[0]); -} - -#endif - BluetoothUnixSocketConnector::BluetoothUnixSocketConnector( + const nsACString& aAddressString, BluetoothSocketType aType, int aChannel, bool aAuth, - bool aEncrypt) : mType(aType) - , mChannel(aChannel) - , mAuth(aAuth) - , mEncrypt(aEncrypt) + bool aEncrypt) + : mAddressString(aAddressString) + , mType(aType) + , mChannel(aChannel) + , mAuth(aAuth) + , mEncrypt(aEncrypt) +{ } + +BluetoothUnixSocketConnector::~BluetoothUnixSocketConnector() +{ } + +nsresult +BluetoothUnixSocketConnector::CreateSocket(int& aFd) const { + static const int sType[] = { + [0] = 0, + [BluetoothSocketType::RFCOMM] = SOCK_STREAM, + [BluetoothSocketType::SCO] = SOCK_SEQPACKET, + [BluetoothSocketType::L2CAP] = SOCK_SEQPACKET, + [BluetoothSocketType::EL2CAP] = SOCK_STREAM + }; + static const int sProtocol[] = { + [0] = 0, + [BluetoothSocketType::RFCOMM] = BTPROTO_RFCOMM, + [BluetoothSocketType::SCO] = BTPROTO_SCO, + [BluetoothSocketType::L2CAP] = BTPROTO_L2CAP, + [BluetoothSocketType::EL2CAP] = BTPROTO_L2CAP + }; + + MOZ_ASSERT(mType < MOZ_ARRAY_LENGTH(sType)); + MOZ_ASSERT(mType < MOZ_ARRAY_LENGTH(sProtocol)); + + aFd = socket(AF_BLUETOOTH, sType[mType], sProtocol[mType]); + if (aFd < 0) { + BT_LOGR("Could not open Bluetooth socket!"); + return NS_ERROR_FAILURE; + } + + return NS_OK; } -bool -BluetoothUnixSocketConnector::SetUp(int aFd) +nsresult +BluetoothUnixSocketConnector::SetSocketFlags(int aFd) const { -#ifdef MOZ_B2G_BT_BLUEZ - int lm = 0; - int sndbuf, rcvbuf; + 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; + } + + int lm; - /* kernel does not yet support LM for SCO */ switch (mType) { - case BluetoothSocketType::RFCOMM: - lm |= mAuth ? RFCOMM_LM_AUTH : 0; - lm |= mEncrypt ? RFCOMM_LM_ENCRYPT : 0; - break; - case BluetoothSocketType::L2CAP: - case BluetoothSocketType::EL2CAP: - lm |= mAuth ? L2CAP_LM_AUTH : 0; - lm |= mEncrypt ? L2CAP_LM_ENCRYPT : 0; - break; - case BluetoothSocketType::SCO: - break; - default: - MOZ_CRASH("Unknown socket type!"); + case BluetoothSocketType::RFCOMM: + lm |= mAuth ? RFCOMM_LM_AUTH : 0; + lm |= mEncrypt ? RFCOMM_LM_ENCRYPT : 0; + break; + case BluetoothSocketType::L2CAP: + case BluetoothSocketType::EL2CAP: + lm |= mAuth ? L2CAP_LM_AUTH : 0; + lm |= mEncrypt ? L2CAP_LM_ENCRYPT : 0; + break; + default: + // kernel does not yet support LM for SCO + lm = 0; + break; } if (lm) { - if (mType == BluetoothSocketType::RFCOMM) { - if (setsockopt(aFd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) { - BT_WARNING("setsockopt(RFCOMM_LM) failed, throwing"); - return false; - } - } else if (mType == BluetoothSocketType::L2CAP || - mType == BluetoothSocketType::EL2CAP) { - if (setsockopt(aFd, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm))) { - BT_WARNING("setsockopt(L2CAP_LM) failed, throwing"); - return false; - } + static const int sLevel[] = { + [0] = 0, + [BluetoothSocketType::RFCOMM] = SOL_RFCOMM, + [BluetoothSocketType::SCO] = 0, + [BluetoothSocketType::L2CAP] = SOL_L2CAP, + [BluetoothSocketType::EL2CAP] = SOL_L2CAP + }; + static const int sOptname[] = { + [0] = 0, + [BluetoothSocketType::RFCOMM] = RFCOMM_LM, + [BluetoothSocketType::SCO] = 0, + [BluetoothSocketType::L2CAP] = L2CAP_LM, + [BluetoothSocketType::EL2CAP] = L2CAP_LM + }; + + MOZ_ASSERT(mType < MOZ_ARRAY_LENGTH(sLevel)); + MOZ_ASSERT(mType < MOZ_ARRAY_LENGTH(sOptname)); + + if (setsockopt(aFd, sLevel[mType], sOptname[mType], &lm, sizeof(lm)) < 0) { + BT_LOGR("setsockopt(RFCOMM_LM) failed, throwing"); + return NS_ERROR_FAILURE; } } if (mType == BluetoothSocketType::RFCOMM) { - sndbuf = RFCOMM_SO_SNDBUF; + + /* Setting RFCOMM socket options */ + + int sndbuf = RFCOMM_SO_SNDBUF; if (setsockopt(aFd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) { BT_WARNING("setsockopt(SO_SNDBUF) failed, throwing"); - return false; + return NS_ERROR_FAILURE; } } - /* Setting L2CAP socket options */ if (mType == BluetoothSocketType::L2CAP || mType == BluetoothSocketType::EL2CAP) { + + /* Setting L2CAP/EL2CAP socket options */ + struct l2cap_options opts; socklen_t optlen = sizeof(opts); - int err; - err = getsockopt(aFd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen); - if (!err) { + int res = getsockopt(aFd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen); + if (!res) { /* setting MTU for [E]L2CAP */ opts.omtu = opts.imtu = L2CAP_MAX_MTU; @@ -144,142 +197,215 @@ BluetoothUnixSocketConnector::SetUp(int aFd) opts.max_tx = 10; } - err = setsockopt(aFd, SOL_L2CAP, L2CAP_OPTIONS, &opts, optlen); + setsockopt(aFd, SOL_L2CAP, L2CAP_OPTIONS, &opts, optlen); } - /* Set larger SNDBUF & RCVBUF for EL2CAP connections */ if (mType == BluetoothSocketType::EL2CAP) { - sndbuf = L2CAP_SO_SNDBUF; - if (setsockopt(aFd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) { - BT_WARNING("setsockopt(SO_SNDBUF) failed, throwing"); - return false; + + /* Set larger SNDBUF and RCVBUF for EL2CAP connections */ + + int sndbuf = L2CAP_SO_SNDBUF; + if (setsockopt(aFd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) { + BT_LOGR("setsockopt(SO_SNDBUF) failed, throwing"); + return NS_ERROR_FAILURE; } - rcvbuf = L2CAP_SO_RCVBUF; - if (setsockopt(aFd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) { - BT_WARNING("setsockopt(SO_RCVBUF) failed, throwing"); - return false; + int rcvbuf = L2CAP_SO_RCVBUF; + if (setsockopt(aFd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0) { + BT_LOGR("setsockopt(SO_RCVBUF) failed, throwing"); + return NS_ERROR_FAILURE; } } } -#endif - return true; + + return NS_OK; } -bool -BluetoothUnixSocketConnector::SetUpListenSocket(int aFd) +nsresult +BluetoothUnixSocketConnector::CreateAddress(struct sockaddr& aAddress, + socklen_t& aAddressLength) const { - // Nothing to do here. - return true; -} - -int -BluetoothUnixSocketConnector::Create() -{ - MOZ_ASSERT(!NS_IsMainThread()); - int fd = -1; - -#ifdef MOZ_B2G_BT_BLUEZ switch (mType) { - case BluetoothSocketType::RFCOMM: - fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - break; - case BluetoothSocketType::SCO: - fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); - break; - case BluetoothSocketType::L2CAP: - fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); - break; - case BluetoothSocketType::EL2CAP: - fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP); - break; - default: - MOZ_CRASH(); + case BluetoothSocketType::RFCOMM: { + struct sockaddr_rc* rc = + reinterpret_cast(&aAddress); + rc->rc_family = AF_BLUETOOTH; + nsresult rv = ConvertAddressString(mAddressString.get(), + rc->rc_bdaddr); + if (NS_FAILED(rv)) { + return rv; + } + rc->rc_channel = mChannel; + aAddressLength = sizeof(*rc); + } + break; + case BluetoothSocketType::L2CAP: + case BluetoothSocketType::EL2CAP: { + struct sockaddr_l2* l2 = + reinterpret_cast(&aAddress); + l2->l2_family = AF_BLUETOOTH; + l2->l2_psm = mChannel; + nsresult rv = ConvertAddressString(mAddressString.get(), + l2->l2_bdaddr); + if (NS_FAILED(rv)) { + return rv; + } + l2->l2_cid = 0; + aAddressLength = sizeof(*l2); + } + break; + case BluetoothSocketType::SCO: { + struct sockaddr_sco* sco = + reinterpret_cast(&aAddress); + sco->sco_family = AF_BLUETOOTH; + nsresult rv = ConvertAddressString(mAddressString.get(), + sco->sco_bdaddr); + if (NS_FAILED(rv)) { + return rv; + } + sco->sco_pkt_type = 0; + aAddressLength = sizeof(*sco); + } + break; + default: + MOZ_CRASH("Socket type unknown!"); + return NS_ERROR_ABORT; } + return NS_OK; +} + +nsresult +BluetoothUnixSocketConnector::ConvertAddressString(const char* aAddressString, + bdaddr_t& aAddress) +{ + char* d = reinterpret_cast(aAddress.b) + 5; + + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aAddress.b); ++i) { + char* endp; + *d-- = strtoul(aAddressString, &endp, 16); + MOZ_ASSERT(!(*endp != ':' && i != 5)); + aAddressString = endp + 1; + } + return NS_OK; +} + +// |UnixSocketConnector| + +nsresult +BluetoothUnixSocketConnector::ConvertAddressToString( + const struct sockaddr& aAddress, socklen_t aAddressLength, + nsACString& aAddressString) +{ + MOZ_ASSERT(aAddress.sa_family == AF_BLUETOOTH); + + const uint8_t* b; + + switch (mType) { + case BluetoothSocketType::RFCOMM: { + const struct sockaddr_rc* rc = + reinterpret_cast(&aAddress); + b = rc->rc_bdaddr.b; + } + break; + case BluetoothSocketType::SCO: { + const struct sockaddr_sco* sco = + reinterpret_cast(&aAddress); + b = sco->sco_bdaddr.b; + } + break; + case BluetoothSocketType::L2CAP: + case BluetoothSocketType::EL2CAP: { + const struct sockaddr_l2* l2 = + reinterpret_cast(&aAddress); + b = l2->l2_bdaddr.b; + } + break; + } + + char str[32]; + snprintf(str, sizeof(str), "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + b[5], b[4], b[3], b[2], b[1], b[0]); + + aAddressString.Assign(str); + + return NS_OK; +} + +nsresult +BluetoothUnixSocketConnector::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 +BluetoothUnixSocketConnector::AcceptStreamSocket(int aListenFd, + struct sockaddr* aAddress, + socklen_t* aAddressLength, + int& aStreamFd) +{ + ScopedClose fd( + TEMP_FAILURE_RETRY(accept(aListenFd, aAddress, aAddressLength))); if (fd < 0) { - BT_WARNING("Could not open bluetooth socket!"); - return -1; + NS_WARNING("Cannot accept file descriptor!"); + return NS_ERROR_FAILURE; + } + nsresult rv = SetSocketFlags(fd); + if (NS_FAILED(rv)) { + return rv; } - if (!SetUp(fd)) { - BT_WARNING("Could not set up socket!"); - return -1; - } -#endif - return fd; + aStreamFd = fd.forget(); + + return NS_OK; } -bool -BluetoothUnixSocketConnector::CreateAddr(bool aIsServer, - socklen_t& aAddrSize, - sockaddr_any& aAddr, - const char* aAddress) +nsresult +BluetoothUnixSocketConnector::CreateStreamSocket(struct sockaddr* aAddress, + socklen_t* aAddressLength, + int& aStreamFd) { -#ifdef MOZ_B2G_BT_BLUEZ - // Set to BDADDR_ANY, if it's not a server, we'll reset. - bdaddr_t bd_address_obj = {{0, 0, 0, 0, 0, 0}}; + ScopedClose fd; - if (!aIsServer && aAddress && strlen(aAddress) > 0) { - if (get_bdaddr(aAddress, &bd_address_obj)) { - BT_WARNING("Can't get bluetooth address!"); - return false; + 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; } } - // Initialize - memset(&aAddr, 0, sizeof(aAddr)); + aStreamFd = fd.forget(); - switch (mType) { - case BluetoothSocketType::RFCOMM: - struct sockaddr_rc addr_rc; - aAddrSize = 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::L2CAP: - case BluetoothSocketType::EL2CAP: - struct sockaddr_l2 addr_l2; - aAddrSize = sizeof(addr_l2); - aAddr.l2.l2_family = AF_BLUETOOTH; - aAddr.l2.l2_psm = mChannel; - memcpy(&aAddr.l2.l2_bdaddr, &bd_address_obj, sizeof(bdaddr_t)); - break; - case BluetoothSocketType::SCO: - struct sockaddr_sco addr_sco; - aAddrSize = sizeof(addr_sco); - aAddr.sco.sco_family = AF_BLUETOOTH; - memcpy(&aAddr.sco.sco_bdaddr, &bd_address_obj, sizeof(bd_address_obj)); - break; - default: - BT_WARNING("Socket type unknown!"); - return false; - } -#endif - return true; + return NS_OK; } -void -BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr, - nsAString& aAddrStr) -{ -#ifdef MOZ_B2G_BT_BLUEZ - char addr[18]; - 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; - case BluetoothSocketType::L2CAP: - case BluetoothSocketType::EL2CAP: - get_bdaddr_as_string((bdaddr_t*)(&aAddr.l2.l2_bdaddr), addr); - break; - default: - MOZ_CRASH("Socket should be either RFCOMM or SCO!"); - } - aAddrStr.AssignASCII(addr); -#endif -} +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluez/BluetoothUnixSocketConnector.h b/dom/bluetooth/bluez/BluetoothUnixSocketConnector.h index d793f470651..852a5e69389 100644 --- a/dom/bluetooth/bluez/BluetoothUnixSocketConnector.h +++ b/dom/bluetooth/bluez/BluetoothUnixSocketConnector.h @@ -8,29 +8,48 @@ #define mozilla_dom_bluetooth_BluetoothUnixSocketConnector_h #include "BluetoothCommon.h" -#include -#include +#include "mozilla/ipc/UnixSocketConnector.h" BEGIN_BLUETOOTH_NAMESPACE -class BluetoothUnixSocketConnector : public mozilla::ipc::UnixSocketConnector +class BluetoothUnixSocketConnector final + : public mozilla::ipc::UnixSocketConnector { public: - BluetoothUnixSocketConnector(BluetoothSocketType aType, int aChannel, - bool aAuth, bool aEncrypt); - virtual ~BluetoothUnixSocketConnector() - {} - virtual int Create() override; - virtual bool CreateAddr(bool aIsServer, - socklen_t& aAddrSize, - mozilla::ipc::sockaddr_any& aAddr, - const char* aAddress) override; - virtual bool SetUp(int aFd) override; - virtual bool SetUpListenSocket(int aFd) override; - virtual void GetSocketAddr(const mozilla::ipc::sockaddr_any& aAddr, - nsAString& aAddrStr) override; + BluetoothUnixSocketConnector(const nsACString& aAddressString, + BluetoothSocketType aType, + int aChannel, bool aAuth, bool aEncrypt); + ~BluetoothUnixSocketConnector(); + + // 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; private: + nsresult CreateSocket(int& aFd) const; + nsresult SetSocketFlags(int aFd) const; + nsresult CreateAddress(struct sockaddr& aAddress, + socklen_t& aAddressLength) const; + static nsresult ConvertAddressString(const char* aAddressString, + bdaddr_t& aAddress); + + nsCString mAddressString; BluetoothSocketType mType; int mChannel; bool mAuth; diff --git a/dom/bluetooth/moz.build b/dom/bluetooth/moz.build index 78a84e766aa..538077133f0 100644 --- a/dom/bluetooth/moz.build +++ b/dom/bluetooth/moz.build @@ -94,6 +94,7 @@ if CONFIG['MOZ_B2G_BT']: 'bluedroid/BluetoothAvrcpHALInterface.cpp', 'bluedroid/BluetoothDaemonA2dpInterface.cpp', 'bluedroid/BluetoothDaemonAvrcpInterface.cpp', + 'bluedroid/BluetoothDaemonConnector.cpp', 'bluedroid/BluetoothDaemonHandsfreeInterface.cpp', 'bluedroid/BluetoothDaemonHelpers.cpp', 'bluedroid/BluetoothDaemonInterface.cpp', diff --git a/dom/nfc/gonk/NfcService.cpp b/dom/nfc/gonk/NfcService.cpp index f0923b5331d..de1d6951181 100644 --- a/dom/nfc/gonk/NfcService.cpp +++ b/dom/nfc/gonk/NfcService.cpp @@ -12,6 +12,7 @@ #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" @@ -312,7 +313,8 @@ NfcService::Start(nsINfcGonkEventListener* aListener) 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; diff --git a/dom/system/gonk/tests/marionette/test_ril_code_quality.py b/dom/system/gonk/tests/marionette/test_ril_code_quality.py index e31ba407f68..2fe4cf2ddfd 100644 --- a/dom/system/gonk/tests/marionette/test_ril_code_quality.py +++ b/dom/system/gonk/tests/marionette/test_ril_code_quality.py @@ -31,7 +31,7 @@ The above merge way ensures the correct scope of 'strict mode.' """ -from marionette_test import MarionetteTestCase +from marionette.marionette_test import MarionetteTestCase import bisect import inspect import os diff --git a/ipc/keystore/KeyStore.cpp b/ipc/keystore/KeyStore.cpp index 1bf568b8521..0a878e221d2 100644 --- a/ipc/keystore/KeyStore.cpp +++ b/ipc/keystore/KeyStore.cpp @@ -19,6 +19,7 @@ #include "KeyStore.h" #include "jsfriendapi.h" +#include "KeyStoreConnector.h" #include "MainThreadUtils.h" // For NS_IsMainThread. #include "nsICryptoHash.h" @@ -304,7 +305,6 @@ static const char *CA_BEGIN = "-----BEGIN ", namespace mozilla { namespace ipc { -static const char* KEYSTORE_SOCKET_PATH = "/dev/socket/keystore"; static const char* KEYSTORE_ALLOWED_USERS[] = { "root", "wifi", @@ -672,76 +672,6 @@ checkPermission(uid_t uid) return false; } -int -KeyStoreConnector::Create() -{ - MOZ_ASSERT(!NS_IsMainThread()); - - int fd; - - unlink(KEYSTORE_SOCKET_PATH); - - fd = socket(AF_LOCAL, SOCK_STREAM, 0); - - if (fd < 0) { - NS_WARNING("Could not open keystore socket!"); - return -1; - } - - return fd; -} - -bool -KeyStoreConnector::CreateAddr(bool aIsServer, - socklen_t& aAddrSize, - sockaddr_any& aAddr, - const char* aAddress) -{ - // Keystore socket must be server - MOZ_ASSERT(aIsServer); - - aAddr.un.sun_family = AF_LOCAL; - if(strlen(KEYSTORE_SOCKET_PATH) > sizeof(aAddr.un.sun_path)) { - NS_WARNING("Address too long for socket struct!"); - return false; - } - strcpy((char*)&aAddr.un.sun_path, KEYSTORE_SOCKET_PATH); - aAddrSize = strlen(KEYSTORE_SOCKET_PATH) + offsetof(struct sockaddr_un, sun_path) + 1; - - return true; -} - -bool -KeyStoreConnector::SetUp(int aFd) -{ - // Socket permission check. - struct ucred userCred; - socklen_t len = sizeof(struct ucred); - - if (getsockopt(aFd, SOL_SOCKET, SO_PEERCRED, &userCred, &len)) { - return false; - } - - return ::checkPermission(userCred.uid); -} - -bool -KeyStoreConnector::SetUpListenSocket(int aFd) -{ - // Allow access of wpa_supplicant(different user, differnt group) - chmod(KEYSTORE_SOCKET_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); - - return true; -} - -void -KeyStoreConnector::GetSocketAddr(const sockaddr_any& aAddr, - nsAString& aAddrStr) -{ - // Unused. - MOZ_CRASH("This should never be called!"); -} - // // KeyStore::ListenSocket // @@ -818,7 +748,7 @@ KeyStore::StreamSocket::ReceiveSocketData(nsAutoPtr& aBuffer) ConnectionOrientedSocketIO* KeyStore::StreamSocket::GetIO() { - return PrepareAccept(new KeyStoreConnector()); + return PrepareAccept(new KeyStoreConnector(KEYSTORE_ALLOWED_USERS)); } // @@ -877,7 +807,8 @@ KeyStore::Listen() if (!mListenSocket) { // We only ever allocate one |ListenSocket|... mListenSocket = new ListenSocket(this); - mListenSocket->Listen(new KeyStoreConnector(), mStreamSocket); + mListenSocket->Listen(new KeyStoreConnector(KEYSTORE_ALLOWED_USERS), + mStreamSocket); } else { // ... but keep it open. mListenSocket->Listen(mStreamSocket); diff --git a/ipc/keystore/KeyStore.h b/ipc/keystore/KeyStore.h index 797cd536937..18dcf3b56ea 100644 --- a/ipc/keystore/KeyStore.h +++ b/ipc/keystore/KeyStore.h @@ -12,7 +12,6 @@ #include "cert.h" #include "mozilla/ipc/ListenSocket.h" #include "mozilla/ipc/StreamSocket.h" -#include "mozilla/ipc/UnixSocketConnector.h" #include "nsNSSShutDown.h" namespace mozilla { @@ -79,26 +78,6 @@ typedef enum { STATE_PROCESSING } ProtocolHandlerState; -class KeyStoreConnector : public mozilla::ipc::UnixSocketConnector -{ -public: - KeyStoreConnector() - {} - - virtual ~KeyStoreConnector() - {} - - virtual int Create(); - virtual bool CreateAddr(bool aIsServer, - socklen_t& aAddrSize, - sockaddr_any& aAddr, - const char* aAddress); - virtual bool SetUp(int aFd); - virtual bool SetUpListenSocket(int aFd); - virtual void GetSocketAddr(const sockaddr_any& aAddr, - nsAString& aAddrStr); -}; - class KeyStore final : public nsNSSShutDownObject { public: diff --git a/ipc/keystore/KeyStoreConnector.cpp b/ipc/keystore/KeyStoreConnector.cpp new file mode 100644 index 00000000000..a40fef8665b --- /dev/null +++ b/ipc/keystore/KeyStoreConnector.cpp @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=2 et ft=cpp: 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 "KeyStoreConnector.h" +#include +#include +#include +#include +#include "nsThreadUtils.h" // For NS_IsMainThread. + +#ifdef MOZ_WIDGET_GONK +#include +#define KEYSTORE_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args) +#else +#define KEYSTORE_LOG(args...) printf(args); +#endif + +namespace mozilla { +namespace ipc { + +static const char KEYSTORE_SOCKET_PATH[] = "/dev/socket/keystore"; + +KeyStoreConnector::KeyStoreConnector(const char** const aAllowedUsers) + : mAllowedUsers(aAllowedUsers) +{ } + +KeyStoreConnector::~KeyStoreConnector() +{ } + +nsresult +KeyStoreConnector::CreateSocket(int& aFd) const +{ + unlink(KEYSTORE_SOCKET_PATH); + + aFd = socket(AF_LOCAL, SOCK_STREAM, 0); + if (aFd < 0) { + KEYSTORE_LOG("Could not open KeyStore socket!"); + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +nsresult +KeyStoreConnector::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 +KeyStoreConnector::CheckPermission(int aFd) const +{ + struct ucred userCred; + socklen_t len = sizeof(userCred); + + if (getsockopt(aFd, SOL_SOCKET, SO_PEERCRED, &userCred, &len)) { + return NS_ERROR_FAILURE; + } + + const struct passwd* userInfo = getpwuid(userCred.uid); + if (!userInfo) { + return NS_ERROR_FAILURE; + } + + if (!mAllowedUsers) { + return NS_ERROR_FAILURE; + } + + for (const char** user = mAllowedUsers; *user; ++user) { + if (!strcmp(*user, userInfo->pw_name)) { + return NS_OK; + } + } + + return NS_ERROR_FAILURE; +} + +nsresult +KeyStoreConnector::CreateAddress(struct sockaddr& aAddress, + socklen_t& aAddressLength) const +{ + struct sockaddr_un* address = + reinterpret_cast(&aAddress); + + size_t namesiz = strlen(KEYSTORE_SOCKET_PATH) + 1; // include trailing '\0' + + if (namesiz > sizeof(address->sun_path)) { + KEYSTORE_LOG("Address too long for socket struct!"); + return NS_ERROR_FAILURE; + } + + address->sun_family = AF_UNIX; + memcpy(address->sun_path, KEYSTORE_SOCKET_PATH, namesiz); + + aAddressLength = offsetof(struct sockaddr_un, sun_path) + namesiz; + + return NS_OK; +} + +// |UnixSocketConnector| + +nsresult +KeyStoreConnector::ConvertAddressToString(const struct sockaddr& aAddress, + socklen_t aAddressLength, + nsACString& aAddressString) +{ + MOZ_ASSERT(aAddress.sa_family == AF_UNIX); + + const struct sockaddr_un* un = + reinterpret_cast(&aAddress); + + size_t len = aAddressLength - offsetof(struct sockaddr_un, sun_path); + + aAddressString.Assign(un->sun_path, len); + + return NS_OK; +} + +nsresult +KeyStoreConnector::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; + } + } + + // Allow access for wpa_supplicant (different user, different group) + // + // TODO: Improve this by setting specific user/group for + // wpa_supplicant by calling |fchmod| and |fchown|. + // + chmod(KEYSTORE_SOCKET_PATH, S_IRUSR|S_IWUSR| + S_IRGRP|S_IWGRP| + S_IROTH|S_IWOTH); + + aListenFd = fd.forget(); + + return NS_OK; +} + +nsresult +KeyStoreConnector::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; + } + rv = CheckPermission(fd); + if (NS_FAILED(rv)) { + return rv; + } + + aStreamFd = fd.forget(); + + return NS_OK; +} + +nsresult +KeyStoreConnector::CreateStreamSocket(struct sockaddr* aAddress, + socklen_t* aAddressLength, + int& aStreamFd) +{ + MOZ_CRASH("|KeyStoreConnector| does not support creating stream sockets."); + return NS_ERROR_FAILURE; +} + +} +} diff --git a/ipc/keystore/KeyStoreConnector.h b/ipc/keystore/KeyStoreConnector.h new file mode 100644 index 00000000000..5387b5290ff --- /dev/null +++ b/ipc/keystore/KeyStoreConnector.h @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=2 et ft=cpp: 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_KeyStoreConnector_h +#define mozilla_ipc_KeyStoreConnector_h + +#include "mozilla/ipc/UnixSocketConnector.h" + +namespace mozilla { +namespace ipc { + +class KeyStoreConnector final : public UnixSocketConnector +{ +public: + KeyStoreConnector(const char** const aAllowedUsers); + ~KeyStoreConnector(); + + // 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* aAddressLength, + int& aStreamFd) override; + + nsresult CreateStreamSocket(struct sockaddr* aAddress, + socklen_t* aAddressLength, + int& aStreamFd) override; + +private: + nsresult CreateSocket(int& aFd) const; + nsresult SetSocketFlags(int aFd) const; + nsresult CheckPermission(int aFd) const; + nsresult CreateAddress(struct sockaddr& aAddress, + socklen_t& aAddressLength) const; + + const char** const mAllowedUsers; +}; + +} +} + +#endif diff --git a/ipc/keystore/moz.build b/ipc/keystore/moz.build index 78af00cb211..62005f33aa8 100644 --- a/ipc/keystore/moz.build +++ b/ipc/keystore/moz.build @@ -9,7 +9,8 @@ EXPORTS.mozilla.ipc += [ ] SOURCES += [ - 'KeyStore.cpp' + 'KeyStore.cpp', + 'KeyStoreConnector.cpp' ] FAIL_ON_WARNINGS = True diff --git a/ipc/nfc/Nfc.cpp b/ipc/nfc/Nfc.cpp index 9ff5e49d600..15162149242 100644 --- a/ipc/nfc/Nfc.cpp +++ b/ipc/nfc/Nfc.cpp @@ -22,6 +22,7 @@ #include "jsfriendapi.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/ipc/NfcConnector.h" #include "nsThreadUtils.h" // For NS_IsMainThread. using namespace mozilla::ipc; @@ -60,74 +61,6 @@ private: 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 // @@ -231,7 +164,7 @@ NfcConsumer::OnDisconnect() ConnectionOrientedSocketIO* NfcConsumer::GetIO() { - return PrepareAccept(new NfcConnector()); + return PrepareAccept(new NfcConnector(NS_LITERAL_CSTRING("nfcd"))); } } // namespace ipc diff --git a/ipc/nfc/Nfc.h b/ipc/nfc/Nfc.h index 583c4174df5..198f7d666fe 100644 --- a/ipc/nfc/Nfc.h +++ b/ipc/nfc/Nfc.h @@ -11,7 +11,6 @@ #include #include -#include namespace mozilla { namespace ipc { @@ -44,23 +43,6 @@ 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: diff --git a/ipc/nfc/NfcConnector.cpp b/ipc/nfc/NfcConnector.cpp new file mode 100644 index 00000000000..5c36d7450aa --- /dev/null +++ b/ipc/nfc/NfcConnector.cpp @@ -0,0 +1,194 @@ +/* -*- 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 +#include +#include "nsThreadUtils.h" // For NS_IsMainThread. + +namespace mozilla { +namespace ipc { + +NfcConnector::NfcConnector(const nsACString& aAddressString) + : mAddressString(aAddressString) +{ } + +NfcConnector::~NfcConnector() +{ } + +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(&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(&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; +} + +} +} diff --git a/ipc/nfc/NfcConnector.h b/ipc/nfc/NfcConnector.h new file mode 100644 index 00000000000..b4ef85ef60f --- /dev/null +++ b/ipc/nfc/NfcConnector.h @@ -0,0 +1,58 @@ +/* -*- 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; + +private: + nsresult CreateSocket(int& aFd) const; + nsresult SetSocketFlags(int aFd) const; + nsresult CreateAddress(struct sockaddr& aAddress, + socklen_t& aAddressLength) const; + + nsCString mAddressString; +}; + +} +} + +#endif diff --git a/ipc/nfc/moz.build b/ipc/nfc/moz.build index 8443be5bedb..b824ae1c8ed 100644 --- a/ipc/nfc/moz.build +++ b/ipc/nfc/moz.build @@ -6,9 +6,11 @@ if CONFIG['MOZ_NFC']: EXPORTS.mozilla.ipc += [ 'Nfc.h', + 'NfcConnector.h', ] SOURCES += [ 'Nfc.cpp', + 'NfcConnector.cpp', ] include('/ipc/chromium/chromium-config.mozbuild') diff --git a/ipc/ril/Ril.cpp b/ipc/ril/Ril.cpp index c7848bb9519..48264e1a91d 100644 --- a/ipc/ril/Ril.cpp +++ b/ipc/ril/Ril.cpp @@ -21,9 +21,9 @@ #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; @@ -32,10 +32,6 @@ 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 > sRilConsumers; class ConnectWorkerToRIL final : public WorkerTask @@ -199,109 +195,6 @@ DispatchRILEvent::RunTask(JSContext* 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 { @@ -324,7 +217,7 @@ RilConsumer::RilConsumer(unsigned long aClientId, mAddress = addr_un.sun_path; } - Connect(new RilConnector(mClientId), mAddress.get()); + Connect(new RilConnector(mAddress, mClientId), mAddress.get()); } nsresult @@ -396,7 +289,7 @@ 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()); } } @@ -404,7 +297,7 @@ RilConsumer::OnDisconnect() ConnectionOrientedSocketIO* RilConsumer::GetIO() { - return PrepareAccept(new RilConnector(mClientId)); + return PrepareAccept(new RilConnector(mAddress, mClientId)); } } // namespace ipc diff --git a/ipc/ril/RilConnector.cpp b/ipc/ril/RilConnector.cpp new file mode 100644 index 00000000000..35bcd48b68d --- /dev/null +++ b/ipc/ril/RilConnector.cpp @@ -0,0 +1,208 @@ +/* -*- 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 +#include +#include "nsThreadUtils.h" // For NS_IsMainThread. + +#ifdef AF_INET +#include +#include +#endif +#ifdef AF_UNIX +#include +#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(&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(&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(&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(&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; +} + +} +} diff --git a/ipc/ril/RilConnector.h b/ipc/ril/RilConnector.h new file mode 100644 index 00000000000..49c1cf051cb --- /dev/null +++ b/ipc/ril/RilConnector.h @@ -0,0 +1,60 @@ +/* -*- 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; + +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 diff --git a/ipc/ril/moz.build b/ipc/ril/moz.build index 2ab5da59e8d..4e7018bcb6a 100644 --- a/ipc/ril/moz.build +++ b/ipc/ril/moz.build @@ -10,6 +10,7 @@ EXPORTS.mozilla.ipc += [ SOURCES += [ 'Ril.cpp', + 'RilConnector.cpp' ] include('/ipc/chromium/chromium-config.mozbuild') diff --git a/ipc/unixsocket/ListenSocket.cpp b/ipc/unixsocket/ListenSocket.cpp index fca2f896b2d..62cb76fba54 100644 --- a/ipc/unixsocket/ListenSocket.cpp +++ b/ipc/unixsocket/ListenSocket.cpp @@ -28,8 +28,7 @@ public: ListenSocketIO(MessageLoop* mIOLoop, ListenSocket* aListenSocket, - UnixSocketConnector* aConnector, - const nsACString& aAddress); + UnixSocketConnector* aConnector); ~ListenSocketIO(); void GetSocketAddr(nsAString& aAddrStr) const; @@ -64,9 +63,6 @@ public: private: void FireSocketError(); - // Set up flags on file descriptor. - static bool SetSocketFlags(int aFd); - /** * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated * directly from main thread. All non-main-thread accesses should happen with @@ -85,33 +81,27 @@ private: bool mShuttingDownOnIOThread; /** - * Address we are connecting to, assuming we are creating a client connection. + * Number of valid bytes in |mAddress| */ - nsCString mAddress; + socklen_t mAddressLength; /** - * Size of the socket address struct + * Address structure of the socket currently in use */ - socklen_t mAddrSize; - - /** - * Address struct of the socket currently in use - */ - sockaddr_any mAddr; + struct sockaddr_storage mAddress; ConnectionOrientedSocketIO* mCOSocketIO; }; ListenSocketIO::ListenSocketIO(MessageLoop* mIOLoop, ListenSocket* aListenSocket, - UnixSocketConnector* aConnector, - const nsACString& aAddress) + UnixSocketConnector* aConnector) : UnixSocketWatcher(mIOLoop) , SocketIOBase() , mListenSocket(aListenSocket) , mConnector(aConnector) , mShuttingDownOnIOThread(false) - , mAddress(aAddress) + , mAddressLength(0) , mCOSocketIO(nullptr) { MOZ_ASSERT(mListenSocket); @@ -132,7 +122,16 @@ ListenSocketIO::GetSocketAddr(nsAString& aAddrStr) const aAddrStr.Truncate(); return; } - mConnector->GetSocketAddr(mAddr, aAddrStr); + + nsCString addressString; + nsresult rv = mConnector->ConvertAddressToString( + *reinterpret_cast(&mAddress), mAddressLength, + addressString); + if (NS_FAILED(rv)) { + return; + } + + aAddrStr.Assign(NS_ConvertUTF8toUTF16(addressString)); } void @@ -142,28 +141,14 @@ ListenSocketIO::Listen(ConnectionOrientedSocketIO* aCOSocketIO) MOZ_ASSERT(mConnector); MOZ_ASSERT(aCOSocketIO); + struct sockaddr* address = reinterpret_cast(&mAddress); + mAddressLength = sizeof(mAddress); + if (!IsOpen()) { - int fd = mConnector->Create(); - if (fd < 0) { - NS_WARNING("Cannot create socket fd!"); - FireSocketError(); - return; - } - if (!SetSocketFlags(fd)) { - NS_WARNING("Cannot set socket flags!"); - FireSocketError(); - return; - } - if (!mConnector->SetUpListenSocket(GetFd())) { - NS_WARNING("Could not set up listen socket!"); - FireSocketError(); - 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. - if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) { - NS_WARNING("Cannot create socket address!"); + int fd; + nsresult rv = mConnector->CreateListenSocket(address, &mAddressLength, + fd); + if (NS_FAILED(rv)) { FireSocketError(); return; } @@ -173,8 +158,7 @@ ListenSocketIO::Listen(ConnectionOrientedSocketIO* aCOSocketIO) mCOSocketIO = aCOSocketIO; // calls OnListening on success, or OnError otherwise - nsresult rv = UnixSocketWatcher::Listen( - reinterpret_cast(&mAddr), mAddrSize); + nsresult rv = UnixSocketWatcher::Listen(address, mAddressLength); NS_WARN_IF(NS_FAILED(rv)); } @@ -221,41 +205,6 @@ ListenSocketIO::FireSocketError() new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR)); } -bool -ListenSocketIO::SetSocketFlags(int aFd) -{ - static const int reuseaddr = 1; - - // Set socket addr to be reused even if kernel is still waiting to close - int res = setsockopt(aFd, SOL_SOCKET, SO_REUSEADDR, - &reuseaddr, sizeof(reuseaddr)); - if (res < 0) { - return false; - } - - // Set close-on-exec bit. - int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFD)); - if (-1 == flags) { - return false; - } - flags |= FD_CLOEXEC; - if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFD, flags))) { - return false; - } - - // Set non-blocking status flag. - flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL)); - if (-1 == flags) { - return false; - } - flags |= O_NONBLOCK; - if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, flags))) { - return false; - } - - return true; -} - void ListenSocketIO::OnSocketCanAcceptWithoutBlocking() { @@ -263,20 +212,24 @@ ListenSocketIO::OnSocketCanAcceptWithoutBlocking() MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_LISTENING); MOZ_ASSERT(mCOSocketIO); - struct sockaddr_storage addr; - socklen_t addrLen = sizeof(addr); - int fd = TEMP_FAILURE_RETRY(accept(GetFd(), - reinterpret_cast(&addr), &addrLen)); - if (fd < 0) { - OnError("accept", errno); + RemoveWatchers(READ_WATCHER|WRITE_WATCHER); + + struct sockaddr_storage storage; + socklen_t addressLength = sizeof(storage); + + int fd; + nsresult rv = mConnector->AcceptStreamSocket( + GetFd(), + reinterpret_cast(&storage), &addressLength, + fd); + if (NS_FAILED(rv)) { + FireSocketError(); return; } - RemoveWatchers(READ_WATCHER|WRITE_WATCHER); - mCOSocketIO->Accept(fd, - reinterpret_cast(&addr), - addrLen); + reinterpret_cast(&storage), + addressLength); } // |SocketIOBase| @@ -397,8 +350,7 @@ ListenSocket::Listen(UnixSocketConnector* aConnector, return false; } - mIO = new ListenSocketIO( - XRE_GetIOMessageLoop(), this, connector.forget(), EmptyCString()); + mIO = new ListenSocketIO(XRE_GetIOMessageLoop(), this, connector.forget()); // Prepared I/O object, now start listening. return Listen(aCOSocket); diff --git a/ipc/unixsocket/StreamSocket.cpp b/ipc/unixsocket/StreamSocket.cpp index d6e423ba593..79b8471efc6 100644 --- a/ipc/unixsocket/StreamSocket.cpp +++ b/ipc/unixsocket/StreamSocket.cpp @@ -30,13 +30,11 @@ public: StreamSocketIO(MessageLoop* mIOLoop, StreamSocket* aStreamSocket, - UnixSocketConnector* aConnector, - const nsACString& aAddress); + UnixSocketConnector* aConnector); StreamSocketIO(MessageLoop* mIOLoop, int aFd, ConnectionStatus aConnectionStatus, StreamSocket* aStreamSocket, - UnixSocketConnector* aConnector, - const nsACString& aAddress); + UnixSocketConnector* aConnector); ~StreamSocketIO(); void GetSocketAddr(nsAString& aAddrStr) const; @@ -98,9 +96,6 @@ public: private: void FireSocketError(); - // Set up flags on file descriptor. - static bool SetSocketFlags(int aFd); - /** * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated * directly from main thread. All non-main-thread accesses should happen with @@ -119,19 +114,14 @@ private: bool mShuttingDownOnIOThread; /** - * Address we are connecting to, assuming we are creating a client connection. + * Number of valid bytes in |mAddress| */ - nsCString mAddress; + socklen_t mAddressLength; /** - * Size of the socket address struct + * Address structure of the socket currently in use */ - socklen_t mAddrSize; - - /** - * Address struct of the socket currently in use - */ - sockaddr_any mAddr; + struct sockaddr_storage mAddress; /** * Task member for delayed connect task. Should only be access on main thread. @@ -146,13 +136,12 @@ private: StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, StreamSocket* aStreamSocket, - UnixSocketConnector* aConnector, - const nsACString& aAddress) + UnixSocketConnector* aConnector) : UnixSocketWatcher(mIOLoop) , mStreamSocket(aStreamSocket) , mConnector(aConnector) , mShuttingDownOnIOThread(false) - , mAddress(aAddress) + , mAddressLength(0) , mDelayedConnectTask(nullptr) { MOZ_ASSERT(mStreamSocket); @@ -162,13 +151,12 @@ StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, int aFd, ConnectionStatus aConnectionStatus, StreamSocket* aStreamSocket, - UnixSocketConnector* aConnector, - const nsACString& aAddress) + UnixSocketConnector* aConnector) : UnixSocketWatcher(mIOLoop, aFd, aConnectionStatus) , mStreamSocket(aStreamSocket) , mConnector(aConnector) , mShuttingDownOnIOThread(false) - , mAddress(aAddress) + , mAddressLength(0) , mDelayedConnectTask(nullptr) { MOZ_ASSERT(mStreamSocket); @@ -189,7 +177,16 @@ StreamSocketIO::GetSocketAddr(nsAString& aAddrStr) const aAddrStr.Truncate(); return; } - mConnector->GetSocketAddr(mAddr, aAddrStr); + + nsCString addressString; + nsresult rv = mConnector->ConvertAddressToString( + *reinterpret_cast(&mAddress), mAddressLength, + addressString); + if (NS_FAILED(rv)) { + return; + } + + aAddrStr.Assign(NS_ConvertUTF8toUTF16(addressString)); } StreamSocket* @@ -239,34 +236,21 @@ StreamSocketIO::Connect() MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); MOZ_ASSERT(mConnector); - if (!IsOpen()) { - int fd = mConnector->Create(); - if (fd < 0) { - NS_WARNING("Cannot create socket fd!"); - FireSocketError(); - return; - } - if (!SetSocketFlags(fd)) { - NS_WARNING("Cannot set socket flags!"); - FireSocketError(); - return; - } - if (!mConnector->SetUp(GetFd())) { - NS_WARNING("Could not set up socket!"); - FireSocketError(); - return; - } - if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) { - NS_WARNING("Cannot create socket address!"); - FireSocketError(); - return; - } - SetFd(fd); + MOZ_ASSERT(!IsOpen()); + + struct sockaddr* address = reinterpret_cast(&mAddress); + mAddressLength = sizeof(mAddress); + + int fd; + nsresult rv = mConnector->CreateStreamSocket(address, &mAddressLength, fd); + if (NS_FAILED(rv)) { + FireSocketError(); + return; } + SetFd(fd); // calls OnConnected() on success, or OnError() otherwise - nsresult rv = UnixSocketWatcher::Connect( - reinterpret_cast(&mAddr), mAddrSize); + rv = UnixSocketWatcher::Connect(address, mAddressLength); NS_WARN_IF(NS_FAILED(rv)); } @@ -354,41 +338,6 @@ StreamSocketIO::FireSocketError() new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR)); } -bool -StreamSocketIO::SetSocketFlags(int aFd) -{ - static const int reuseaddr = 1; - - // Set socket addr to be reused even if kernel is still waiting to close - int res = setsockopt(aFd, SOL_SOCKET, SO_REUSEADDR, - &reuseaddr, sizeof(reuseaddr)); - if (res < 0) { - return false; - } - - // Set close-on-exec bit. - int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFD)); - if (-1 == flags) { - return false; - } - flags |= FD_CLOEXEC; - if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFD, flags))) { - return false; - } - - // Set non-blocking status flag. - flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL)); - if (-1 == flags) { - return false; - } - flags |= O_NONBLOCK; - if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, flags))) { - return false; - } - - return true; -} - // |ConnectionOrientedSocketIO| nsresult @@ -398,21 +347,11 @@ StreamSocketIO::Accept(int aFd, MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING); - // File-descriptor setup - - if (!SetSocketFlags(aFd)) { - return NS_ERROR_FAILURE; - } - if (!mConnector->SetUp(aFd)) { - NS_WARNING("Could not set up socket!"); - return NS_ERROR_FAILURE; - } - SetSocket(aFd, SOCKET_IS_CONNECTED); // Address setup - memcpy(&mAddr, aAddr, aAddrLen); - mAddrSize = aAddrLen; + mAddressLength = aAddrLen; + memcpy(&mAddress, aAddr, mAddressLength); // Signal success NS_DispatchToMainThread( @@ -652,9 +591,8 @@ StreamSocket::Connect(UnixSocketConnector* aConnector, return false; } - nsCString addr(aAddress); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); - mIO = new StreamSocketIO(ioLoop, this, connector.forget(), addr); + mIO = new StreamSocketIO(ioLoop, this, connector.forget()); SetConnectionStatus(SOCKET_CONNECTING); if (aDelayMs > 0) { StreamSocketIO::DelayedConnectTask* connectTask = @@ -681,7 +619,7 @@ StreamSocket::PrepareAccept(UnixSocketConnector* aConnector) mIO = new StreamSocketIO(XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, - this, connector.forget(), EmptyCString()); + this, connector.forget()); return mIO; } diff --git a/ipc/unixsocket/UnixSocketConnector.cpp b/ipc/unixsocket/UnixSocketConnector.cpp index ef958f062f8..37ddd0fb1b0 100644 --- a/ipc/unixsocket/UnixSocketConnector.cpp +++ b/ipc/unixsocket/UnixSocketConnector.cpp @@ -9,6 +9,9 @@ namespace mozilla { namespace ipc { +UnixSocketConnector::UnixSocketConnector() +{ } + UnixSocketConnector::~UnixSocketConnector() { } diff --git a/ipc/unixsocket/UnixSocketConnector.h b/ipc/unixsocket/UnixSocketConnector.h index dcfb1b83149..39f76501c70 100644 --- a/ipc/unixsocket/UnixSocketConnector.h +++ b/ipc/unixsocket/UnixSocketConnector.h @@ -7,6 +7,7 @@ #ifndef mozilla_ipc_unixsocketconnector_h #define mozilla_ipc_unixsocketconnector_h +#include #include "mozilla/ipc/UnixSocketWatcher.h" #include "nsString.h" @@ -16,7 +17,7 @@ namespace ipc { /** * |UnixSocketConnector| defines the socket creation and connection/listening * functions for |UnixSocketConsumer|, et al. Due to the fact that socket setup - * can vary between protocols (unix sockets, tcp sockets, bluetooth sockets, etc), + * can vary between protocols (Unix sockets, TCP sockets, Bluetooth sockets, etc), * this allows the user to create whatever connection mechanism they need while * still depending on libevent for non-blocking communication handling. */ @@ -26,57 +27,57 @@ public: virtual ~UnixSocketConnector(); /** - * Establishs a file descriptor for a socket. + * Converts an address to a human-readable string. * - * @return File descriptor for socket + * @param aAddress A socket address + * @param aAddressLength The number of valid bytes in |aAddress| + * @param[out] aAddressString The resulting string + * @return NS_OK on success, or an XPCOM error code otherwise. */ - virtual int Create() = 0; + virtual nsresult ConvertAddressToString(const struct sockaddr& aAddress, + socklen_t aAddressLength, + nsACString& aAddressString) = 0; /** - * 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 + * Creates a listening socket. I/O thread only. * - * @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 + * @param[out] aAddress The listening socket's address + * @param[out] aAddressLength The number of valid bytes in |aAddress| + * @param[out] aListenFd The socket's file descriptor + * @return NS_OK on success, or an XPCOM error code otherwise. */ - virtual bool CreateAddr(bool aIsServer, - socklen_t& aAddrSize, - sockaddr_any& aAddr, - const char* aAddress) = 0; + virtual nsresult CreateListenSocket(struct sockaddr* aAddress, + socklen_t* aAddressLength, + int& aListenFd) = 0; /** - * Does any socket type specific setup that may be needed, only for socket - * created by ConnectSocket() + * Accepts a stream socket from a listening socket. I/O thread only. * - * @param aFd File descriptor for opened socket - * - * @return true is successful, false otherwise + * @param aListenFd The listening socket + * @param[out] aAddress Returns the stream socket's address + * @param[out] aAddressLength Returns the number of valid bytes in |aAddress| + * @param[out] aStreamFd The stream socket's file descriptor + * @return NS_OK on success, or an XPCOM error code otherwise. */ - virtual bool SetUp(int aFd) = 0; + virtual nsresult AcceptStreamSocket(int aListenFd, + struct sockaddr* aAddress, + socklen_t* aAddressLen, + int& aStreamFd) = 0; /** - * Perform socket setup for socket created by ListenSocket(), after listen(). + * Creates a stream socket. I/O thread only. * - * @param aFd File descriptor for opened socket - * - * @return true is successful, false otherwise + * @param[in|out] aAddress The stream socket's address + * @param[in|out] aAddressLength The number of valid bytes in |aAddress| + * @param[out] aStreamFd The socket's file descriptor + * @return NS_OK on success, or an XPCOM error code otherwise. */ - virtual bool SetUpListenSocket(int aFd) = 0; + virtual nsresult CreateStreamSocket(struct sockaddr* aAddress, + socklen_t* aAddressLength, + int& aStreamFd) = 0; - /** - * 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_any& aAddr, - nsAString& aAddrStr) = 0; +protected: + UnixSocketConnector(); }; }