diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp index 2ce93da8404a..d58701bd7b41 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp @@ -1510,7 +1510,9 @@ BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData) aPDU->SetConsumer(this); aPDU->SetUserData(aUserData); aPDU->UpdateHeader(); - return mConnection->Send(aPDU); // Forward PDU to command channel + mConnection->SendSocketData(aPDU); // Forward PDU to command channel + + return NS_OK; } void diff --git a/ipc/bluetooth/BluetoothDaemonConnection.cpp b/ipc/bluetooth/BluetoothDaemonConnection.cpp index e474fd48a1d2..6e751248175d 100644 --- a/ipc/bluetooth/BluetoothDaemonConnection.cpp +++ b/ipc/bluetooth/BluetoothDaemonConnection.cpp @@ -200,7 +200,7 @@ BluetoothDaemonPDUConsumer::~BluetoothDaemonPDUConsumer() // class BluetoothDaemonConnectionIO final : public UnixSocketWatcher - , public SocketIOBase + , public DataSocketIO , public ConnectionOrientedSocketIO { public: @@ -209,33 +209,12 @@ public: BluetoothDaemonConnection* aConnection, BluetoothDaemonPDUConsumer* aConsumer); - SocketBase* GetSocketBase(); - - // StreamSocketIOBase - // - - nsresult Accept(int aFd, - const union sockaddr_any* aAddr, socklen_t aAddrLen); - - // Shutdown state - // - - bool IsShutdownOnMainThread() const; - void ShutdownOnMainThread(); - - bool IsShutdownOnIOThread() const; - void ShutdownOnIOThread(); - // Task callback methods // void Connect(const char* aSocketName); - void Send(BluetoothDaemonPDU* aPDU); - void EnqueueData(BluetoothDaemonPDU* aPDU); - bool HasPendingData() const; - - nsresult Receive(struct msghdr& msg); + void Send(UnixSocketIOBuffer* aBuffer); void OnSocketCanReceiveWithoutBlocking() override; void OnSocketCanSendWithoutBlocking() override; @@ -243,14 +222,35 @@ public: void OnConnected() override; void OnError(const char* aFunction, int aErrno) override; -private: - ssize_t ReceiveData(int aFd); - nsresult SendPendingData(int aFd); + // Methods for |ConnectionOrientedSocketIO| + // + nsresult Accept(int aFd, + const union sockaddr_any* aAddr, + socklen_t aAddrLen) override; + + // Methods for |DataSocketIO| + // + + nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override; + void ConsumeBuffer() override; + void DiscardBuffer() override; + + // Methods for |SocketIOBase| + // + + SocketBase* GetSocketBase() override; + + bool IsShutdownOnMainThread() const override; + bool IsShutdownOnIOThread() const override; + + void ShutdownOnMainThread() override; + void ShutdownOnIOThread() override; + +private: BluetoothDaemonConnection* mConnection; BluetoothDaemonPDUConsumer* mConsumer; nsAutoPtr mPDU; - nsTArray mOutgoingQ; bool mShuttingDownOnIOThread; }; @@ -266,72 +266,6 @@ BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO( { MOZ_ASSERT(mConnection); MOZ_ASSERT(mConsumer); - - /* There's only one PDU for receiving, which we reuse everytime */ - mPDU = new BluetoothDaemonPDU(BluetoothDaemonPDU::MAX_PAYLOAD_LENGTH); -} - -SocketBase* -BluetoothDaemonConnectionIO::GetSocketBase() -{ - return mConnection; -} - -bool -BluetoothDaemonConnectionIO::IsShutdownOnMainThread() const -{ - MOZ_ASSERT(NS_IsMainThread()); - - return mConnection == nullptr; -} - -void -BluetoothDaemonConnectionIO::ShutdownOnMainThread() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!IsShutdownOnMainThread()); - - mConnection = nullptr; -} - -bool -BluetoothDaemonConnectionIO::IsShutdownOnIOThread() const -{ - return mShuttingDownOnIOThread; -} - -void -BluetoothDaemonConnectionIO::ShutdownOnIOThread() -{ - MOZ_ASSERT(!NS_IsMainThread()); - MOZ_ASSERT(!mShuttingDownOnIOThread); - - Close(); // will also remove fd from I/O loop - mShuttingDownOnIOThread = true; -} - -nsresult -BluetoothDaemonConnectionIO::Accept(int aFd, - const union sockaddr_any* aAddr, - socklen_t aAddrLen) -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING); - - // File-descriptor setup - - if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) { - OnError("fcntl", errno); - ScopedClose cleanupFd(aFd); - return NS_ERROR_FAILURE; - } - - SetSocket(aFd, SOCKET_IS_CONNECTED); - - // Signal success - OnConnected(); - - return NS_OK; } void @@ -379,57 +313,17 @@ BluetoothDaemonConnectionIO::Connect(const char* aSocketName) } void -BluetoothDaemonConnectionIO::Send(BluetoothDaemonPDU* aPDU) +BluetoothDaemonConnectionIO::Send(UnixSocketIOBuffer* aBuffer) { - MOZ_ASSERT(mConsumer); - MOZ_ASSERT(aPDU); + MOZ_ASSERT(aBuffer); - EnqueueData(aPDU); + EnqueueData(aBuffer); AddWatchers(WRITE_WATCHER, false); } -void -BluetoothDaemonConnectionIO::EnqueueData(BluetoothDaemonPDU* aPDU) -{ - MOZ_ASSERT(aPDU); - - mOutgoingQ.AppendElement(aPDU); -} - -bool -BluetoothDaemonConnectionIO::HasPendingData() const -{ - return !mOutgoingQ.IsEmpty(); -} - -ssize_t -BluetoothDaemonConnectionIO::ReceiveData(int aFd) -{ - MOZ_ASSERT(aFd >= 0); - - ssize_t res = mPDU->Receive(aFd); - if (res < 0) { - /* an I/O error occured */ - NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this)); - return -1; - } else if (!res) { - /* EOF or peer shut down sending */ - NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this)); - return 0; - } - - mConsumer->Handle(*mPDU); - - return res; -} - void BluetoothDaemonConnectionIO::OnSocketCanReceiveWithoutBlocking() { - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); - MOZ_ASSERT(!IsShutdownOnIOThread()); - ssize_t res = ReceiveData(GetFd()); if (res < 0) { /* I/O error */ @@ -440,30 +334,6 @@ BluetoothDaemonConnectionIO::OnSocketCanReceiveWithoutBlocking() } } -nsresult -BluetoothDaemonConnectionIO::SendPendingData(int aFd) -{ - while (HasPendingData()) { - BluetoothDaemonPDU* outgoing = mOutgoingQ.ElementAt(0); - MOZ_ASSERT(outgoing); - - ssize_t res = outgoing->Send(aFd); - if (res < 0) { - /* an I/O error occured */ - return NS_ERROR_FAILURE; - } else if (!res) { - /* I/O is currently blocked; try again later */ - return NS_OK; - } - - MOZ_ASSERT(!outgoing->GetSize()); - mOutgoingQ.RemoveElementAt(0); - delete outgoing; - } - - return NS_OK; -} - void BluetoothDaemonConnectionIO::OnSocketCanSendWithoutBlocking() { @@ -506,6 +376,103 @@ BluetoothDaemonConnectionIO::OnError(const char* aFunction, int aErrno) new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR)); } +// |ConnectionOrientedSocketIO| + +nsresult +BluetoothDaemonConnectionIO::Accept(int aFd, + const union sockaddr_any* aAddr, + socklen_t aAddrLen) +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING); + + // File-descriptor setup + + if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) { + OnError("fcntl", errno); + ScopedClose cleanupFd(aFd); + return NS_ERROR_FAILURE; + } + + SetSocket(aFd, SOCKET_IS_CONNECTED); + + // Signal success + OnConnected(); + + return NS_OK; +} + +// |DataSocketIO| + +nsresult +BluetoothDaemonConnectionIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) +{ + MOZ_ASSERT(aBuffer); + + if (!mPDU) { + /* There's only one PDU for receiving. We reuse it every time. */ + mPDU = new BluetoothDaemonPDU(BluetoothDaemonPDU::MAX_PAYLOAD_LENGTH); + } + *aBuffer = mPDU.get(); + + return NS_OK; +} + +void +BluetoothDaemonConnectionIO::ConsumeBuffer() +{ + MOZ_ASSERT(mConsumer); + + mConsumer->Handle(*mPDU); +} + +void +BluetoothDaemonConnectionIO::DiscardBuffer() +{ + // Nothing to do. +} + +// |SocketIOBase| + +SocketBase* +BluetoothDaemonConnectionIO::GetSocketBase() +{ + return mConnection; +} + +bool +BluetoothDaemonConnectionIO::IsShutdownOnMainThread() const +{ + MOZ_ASSERT(NS_IsMainThread()); + + return mConnection == nullptr; +} + +bool +BluetoothDaemonConnectionIO::IsShutdownOnIOThread() const +{ + return mShuttingDownOnIOThread; +} + +void +BluetoothDaemonConnectionIO::ShutdownOnMainThread() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!IsShutdownOnMainThread()); + + mConnection = nullptr; +} + +void +BluetoothDaemonConnectionIO::ShutdownOnIOThread() +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!mShuttingDownOnIOThread); + + Close(); // will also remove fd from I/O loop + mShuttingDownOnIOThread = true; +} + // // I/O helper tasks // @@ -532,7 +499,7 @@ public: // BluetoothDaemonConnection::BluetoothDaemonConnection() -: mIO(nullptr) + : mIO(nullptr) { } BluetoothDaemonConnection::~BluetoothDaemonConnection() @@ -558,6 +525,49 @@ BluetoothDaemonConnection::ConnectSocket(BluetoothDaemonPDUConsumer* aConsumer) return NS_OK; } +ConnectionOrientedSocketIO* +BluetoothDaemonConnection::PrepareAccept(BluetoothDaemonPDUConsumer* aConsumer) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mIO); + MOZ_ASSERT(aConsumer); + + SetConnectionStatus(SOCKET_CONNECTING); + + mIO = new BluetoothDaemonConnectionIO( + XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, + this, aConsumer); + + return mIO; +} + +// |ConnectionOrientedSocket| + +ConnectionOrientedSocketIO* +BluetoothDaemonConnection::GetIO() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mIO); // Call |PrepareAccept| before listening for connections + + return mIO; +} + +// |DataSocket| + +void +BluetoothDaemonConnection::SendSocketData(UnixSocketIOBuffer* aBuffer) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mIO); + + XRE_GetIOMessageLoop()->PostTask( + FROM_HERE, + new SocketIOSendTask(mIO, aBuffer)); +} + +// |SocketBase| + void BluetoothDaemonConnection::CloseSocket() { @@ -575,47 +585,5 @@ BluetoothDaemonConnection::CloseSocket() NotifyDisconnect(); } -nsresult -BluetoothDaemonConnection::Send(BluetoothDaemonPDU* aPDU) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!mIO) { - CHROMIUM_LOG("Bluetooth daemon already connecting/connected!"); - return NS_ERROR_FAILURE; - } - - XRE_GetIOMessageLoop()->PostTask( - FROM_HERE, - new SocketIOSendTask(mIO, aPDU)); - return NS_OK; -} - -ConnectionOrientedSocketIO* -BluetoothDaemonConnection::GetIO() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mIO); // Call |PrepareAccept| before listening for connections - - return mIO; -} - -ConnectionOrientedSocketIO* -BluetoothDaemonConnection::PrepareAccept(BluetoothDaemonPDUConsumer* aConsumer) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mIO); - MOZ_ASSERT(aConsumer); - - SetConnectionStatus(SOCKET_CONNECTING); - - mIO = new BluetoothDaemonConnectionIO( - XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, - this, aConsumer); - - return mIO; -} - } } diff --git a/ipc/bluetooth/BluetoothDaemonConnection.h b/ipc/bluetooth/BluetoothDaemonConnection.h index 285e3234cb35..38b03fafe650 100644 --- a/ipc/bluetooth/BluetoothDaemonConnection.h +++ b/ipc/bluetooth/BluetoothDaemonConnection.h @@ -10,7 +10,7 @@ #include "mozilla/Attributes.h" #include "mozilla/FileUtils.h" #include "mozilla/ipc/ConnectionOrientedSocket.h" -#include "mozilla/ipc/SocketBase.h" +#include "mozilla/ipc/DataSocket.h" #include "nsError.h" #include "nsAutoPtr.h" @@ -112,26 +112,30 @@ protected: * Bluetooth daemon. It offers connection establishment and sending * PDUs. PDU receiving is performed by |BluetoothDaemonPDUConsumer|. */ -class BluetoothDaemonConnection : public SocketBase +class BluetoothDaemonConnection : public DataSocket , public ConnectionOrientedSocket { public: BluetoothDaemonConnection(); virtual ~BluetoothDaemonConnection(); - // SocketBase - // - nsresult ConnectSocket(BluetoothDaemonPDUConsumer* aConsumer); - void CloseSocket(); - nsresult Send(BluetoothDaemonPDU* aPDU); - - // ConnectionOrientedSocket + // Methods for |ConnectionOrientedSocket| // virtual ConnectionOrientedSocketIO* GetIO() override; + // Methods for |DataSocket| + // + + void SendSocketData(UnixSocketIOBuffer* aBuffer) override; + + // Methods for |SocketBase| + // + + void CloseSocket() override; + protected: // Prepares an instance of |BluetoothDaemonConnection| in DISCONNECTED