diff --git a/ipc/bluetooth/BluetoothDaemonConnection.cpp b/ipc/bluetooth/BluetoothDaemonConnection.cpp index 2f9adc7aaff4..ac1c146b6d08 100644 --- a/ipc/bluetooth/BluetoothDaemonConnection.cpp +++ b/ipc/bluetooth/BluetoothDaemonConnection.cpp @@ -212,6 +212,8 @@ public: // Task callback methods // + void Connect(const char* aSocketName); + void Send(UnixSocketIOBuffer* aBuffer); void OnSocketCanReceiveWithoutBlocking() override; @@ -266,6 +268,50 @@ BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO( MOZ_ASSERT(mConsumer); } +void +BluetoothDaemonConnectionIO::Connect(const char* aSocketName) +{ + static const size_t sNameOffset = 1; + + MOZ_ASSERT(aSocketName); + + // Create socket address + + struct sockaddr_un addr; + size_t namesiz = strlen(aSocketName) + 1; + + if((sNameOffset + namesiz) > sizeof(addr.sun_path)) { + CHROMIUM_LOG("Address too long for socket struct!"); + return; + } + memset(addr.sun_path, '\0', sNameOffset); // abstract socket + memcpy(addr.sun_path + sNameOffset, aSocketName, namesiz); + addr.sun_family = AF_UNIX; + + socklen_t socklen = offsetof(struct sockaddr_un, sun_path) + 1 + namesiz; + + // Create socket + + int fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) { + OnError("socket", errno); + return; + } + if (TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, O_NONBLOCK)) < 0) { + OnError("fcntl", errno); + ScopedClose cleanupFd(fd); + return; + } + + SetFd(fd); + + // Connect socket to address; calls OnConnected() + // on success, or OnError() otherwise + nsresult rv = UnixSocketWatcher::Connect( + reinterpret_cast(&addr), socklen); + NS_WARN_IF(NS_FAILED(rv)); +} + void BluetoothDaemonConnectionIO::Send(UnixSocketIOBuffer* aBuffer) { @@ -427,6 +473,27 @@ BluetoothDaemonConnectionIO::ShutdownOnIOThread() mShuttingDownOnIOThread = true; } +// +// I/O helper tasks +// + +class BluetoothDaemonConnectTask final + : public SocketIOTask +{ +public: + BluetoothDaemonConnectTask(BluetoothDaemonConnectionIO* aIO) + : SocketIOTask(aIO) + { } + + void Run() override + { + if (IsCanceled()) { + return; + } + GetIO()->Connect(sBluetoothdSocketName); + } +}; + // // BluetoothDaemonConnection // @@ -438,6 +505,26 @@ BluetoothDaemonConnection::BluetoothDaemonConnection() BluetoothDaemonConnection::~BluetoothDaemonConnection() { } +nsresult +BluetoothDaemonConnection::ConnectSocket(BluetoothDaemonPDUConsumer* aConsumer) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (mIO) { + CHROMIUM_LOG("Bluetooth daemon already connecting/connected!"); + return NS_ERROR_FAILURE; + } + + SetConnectionStatus(SOCKET_CONNECTING); + + MessageLoop* ioLoop = XRE_GetIOMessageLoop(); + mIO = new BluetoothDaemonConnectionIO( + ioLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, this, aConsumer); + ioLoop->PostTask(FROM_HERE, new BluetoothDaemonConnectTask(mIO)); + + return NS_OK; +} + ConnectionOrientedSocketIO* BluetoothDaemonConnection::PrepareAccept(BluetoothDaemonPDUConsumer* aConsumer) { diff --git a/ipc/bluetooth/BluetoothDaemonConnection.h b/ipc/bluetooth/BluetoothDaemonConnection.h index a110b5beecfa..ea26b68be169 100644 --- a/ipc/bluetooth/BluetoothDaemonConnection.h +++ b/ipc/bluetooth/BluetoothDaemonConnection.h @@ -116,6 +116,8 @@ public: BluetoothDaemonConnection(); virtual ~BluetoothDaemonConnection(); + nsresult ConnectSocket(BluetoothDaemonPDUConsumer* aConsumer); + // Methods for |ConnectionOrientedSocket| //