11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/proximity_auth/bluetooth_connection.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/message_loop/message_loop.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/numerics/safe_conversions.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/proximity_auth/bluetooth_util.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/proximity_auth/remote_device.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/proximity_auth/wire_message.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/bluetooth/bluetooth_adapter_factory.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/bluetooth/bluetooth_device.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/io_buffer.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace proximity_auth { 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kReceiveBufferSizeBytes = 1024; 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBluetoothConnection::BluetoothConnection(const RemoteDevice& remote_device, 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const device::BluetoothUUID& uuid) 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : Connection(remote_device), uuid_(uuid), weak_ptr_factory_(this) { 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBluetoothConnection::~BluetoothConnection() { 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Disconnect(); 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::Connect() { 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (status() != DISCONNECTED) { 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "[BC] Ignoring attempt to connect a non-disconnected connection."; 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) { 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "[BC] Connection failed: Bluetooth is unsupported on this platform."; 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetStatus(IN_PROGRESS); 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device::BluetoothAdapterFactory::GetAdapter( 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::OnAdapterInitialized, 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr())); 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::Disconnect() { 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (status() == DISCONNECTED) { 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "[BC] Ignoring attempt to disconnect a non-connected connection."; 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Set status as disconnected now, rather than after the socket closes, so 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // this connection is not reused. 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetStatus(DISCONNECTED); 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (socket_.get()) { 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket_->Disconnect(base::Bind(&base::DoNothing)); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket_ = NULL; 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (adapter_.get()) { 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter_->RemoveObserver(this); 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter_ = NULL; 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::SendMessageImpl(scoped_ptr<WireMessage> message) { 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(status(), CONNECTED); 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Serialize the message. 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string serialized_message = message->Serialize(); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int message_length = base::checked_cast<int>(serialized_message.size()); 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(message_length); 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci memcpy(buffer->data(), serialized_message.c_str(), message_length); 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Send it. 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_message_ = message.Pass(); 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr(); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket_->Send(buffer, 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_length, 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::OnSend, weak_this), 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::OnSendError, weak_this)); 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::DeviceRemoved(device::BluetoothAdapter* adapter, 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device::BluetoothDevice* device) { 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(adapter, adapter_.get()); 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (device->GetAddress() != remote_device().bluetooth_address) 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_NE(status(), DISCONNECTED); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Device disconnected..."; 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Disconnect(); 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::ConnectToService( 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device::BluetoothDevice* device, 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const device::BluetoothUUID& uuid, 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const device::BluetoothDevice::ConnectToServiceCallback& callback, 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const device::BluetoothDevice::ConnectToServiceErrorCallback& 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci error_callback) { 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bluetooth_util::ConnectToServiceInsecurely( 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device, uuid, callback, error_callback); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::StartReceive() { 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr(); 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket_->Receive(kReceiveBufferSizeBytes, 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::OnReceive, weak_this), 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::OnReceiveError, weak_this)); 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::OnAdapterInitialized( 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<device::BluetoothAdapter> adapter) { 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string address = remote_device().bluetooth_address; 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device::BluetoothDevice* bluetooth_device = adapter->GetDevice(address); 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!bluetooth_device) { 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Device with address " << address 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << " is not known to the system Bluetooth daemon."; 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Disconnect(); 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter_ = adapter; 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter_->AddObserver(this); 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr(); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ConnectToService( 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bluetooth_device, 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uuid_, 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::OnConnected, weak_this), 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::OnConnectionError, weak_this)); 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::OnConnected( 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<device::BluetoothSocket> socket) { 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (status() != IN_PROGRESS) { 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This case is reachable if the client of |this| connection called 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |Disconnect()| while the backing Bluetooth connection was pending. 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(status(), DISCONNECTED); 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Ignoring successful backend Bluetooth connection to an " 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "already disconnected logical connection."; 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Connection established with " 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << remote_device().bluetooth_address; 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket_ = socket; 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetStatus(CONNECTED); 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci StartReceive(); 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::OnConnectionError(const std::string& error_message) { 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Connection failed: " << error_message; 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Disconnect(); 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::OnSend(int bytes_sent) { 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Successfully sent " << bytes_sent << " bytes."; 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnDidSendMessage(*pending_message_, true); 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_message_.reset(); 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::OnSendError(const std::string& error_message) { 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Error when sending bytes: " << error_message; 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnDidSendMessage(*pending_message_, false); 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_message_.reset(); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Disconnect(); 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::OnReceive(int bytes_received, 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<net::IOBuffer> buffer) { 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Received " << bytes_received << " bytes."; 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnBytesReceived(std::string(buffer->data(), bytes_received)); 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Post a task to delay the read until the socket is available, as 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // calling StartReceive at this point would error with ERR_IO_PENDING. 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::MessageLoop::current()->PostTask( 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::StartReceive, 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr())); 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BluetoothConnection::OnReceiveError( 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device::BluetoothSocket::ErrorReason error_reason, 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& error_message) { 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "[BC] Error receiving bytes: " << error_message; 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Post a task to delay the read until the socket is available, as 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // calling StartReceive at this point would error with ERR_IO_PENDING. 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::MessageLoop::current()->PostTask( 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BluetoothConnection::StartReceive, 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr())); 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace proximity_auth 202