blob: c13fd3358ca23f0830d0001eae3e19f67232f7cd [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/copresence_endpoints/public/copresence_endpoint.h"
#include <stdint.h>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/format_macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "components/copresence_endpoints/transports/bluetooth/copresence_socket_bluetooth.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/bluetooth_uuid.h"
namespace {
const char kAdapterError[] = "NOADAPTER";
const char kSocketServiceUuid[] = "2491fb14-0077-4d4d-bd41-b18e9a570f56";
// This class will confirm pairing for a device that is expecting a pairing
// confirmation.
class DefaultApprovalDelegate
: public device::BluetoothDevice::PairingDelegate {
public:
DefaultApprovalDelegate() {}
~DefaultApprovalDelegate() override {}
// device::BluetoothDevice::PairingDelegate overrides:
void RequestPinCode(device::BluetoothDevice* device) override {}
void RequestPasskey(device::BluetoothDevice* device) override {}
void DisplayPinCode(device::BluetoothDevice* device,
const std::string& pincode) override {}
void DisplayPasskey(device::BluetoothDevice* device,
uint32 passkey) override {}
void KeysEntered(device::BluetoothDevice* device, uint32 entered) override {}
void ConfirmPasskey(device::BluetoothDevice* device,
uint32 passkey) override {}
void AuthorizePairing(device::BluetoothDevice* device) override {
if (device->ExpectingConfirmation())
device->ConfirmPairing();
}
};
} // namespace
namespace copresence_endpoints {
CopresenceEndpoint::CopresenceEndpoint(
int endpoint_id,
const CreateEndpointCallback& create_callback,
const base::Closure& accept_callback,
const CopresenceSocket::ReceiveCallback& receive_callback)
: endpoint_id_(endpoint_id),
create_callback_(create_callback),
accept_callback_(accept_callback),
receive_callback_(receive_callback),
delegate_(nullptr),
weak_ptr_factory_(this) {
CHECK(!create_callback.is_null());
CHECK(!accept_callback.is_null());
CHECK(!receive_callback.is_null());
if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
create_callback_.Run(std::string());
return;
}
device::BluetoothAdapterFactory::GetAdapter(base::Bind(
&CopresenceEndpoint::OnGetAdapter, weak_ptr_factory_.GetWeakPtr()));
}
CopresenceEndpoint::~CopresenceEndpoint() {
server_socket_->Disconnect(base::Bind(&base::DoNothing));
server_socket_->Close();
if (delegate_)
adapter_->RemovePairingDelegate(delegate_.get());
}
std::string CopresenceEndpoint::GetLocator() {
if (!adapter_.get())
return kAdapterError;
return base::IntToString(endpoint_id_) + "." + adapter_->GetAddress() + "." +
kSocketServiceUuid;
}
bool CopresenceEndpoint::Send(const scoped_refptr<net::IOBuffer>& buffer,
int buffer_size) {
if (!client_socket_)
return false;
return client_socket_->Send(buffer, buffer_size);
}
// Private methods.
void CopresenceEndpoint::OnGetAdapter(
scoped_refptr<device::BluetoothAdapter> adapter) {
if (!adapter.get() || !adapter->IsPresent() || !adapter->IsPowered()) {
LOG(WARNING) << "Unable to use BT adapter";
create_callback_.Run(std::string());
return;
}
adapter_ = adapter;
delegate_ = make_scoped_ptr(new DefaultApprovalDelegate());
VLOG(2) << "Got Adapter, creating service with UUID: " << kSocketServiceUuid;
adapter_->AddPairingDelegate(
delegate_.get(),
device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
adapter_->CreateRfcommService(
device::BluetoothUUID(kSocketServiceUuid),
device::BluetoothAdapter::ServiceOptions(),
base::Bind(&CopresenceEndpoint::OnCreateService,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&CopresenceEndpoint::OnCreateServiceError,
weak_ptr_factory_.GetWeakPtr()));
}
void CopresenceEndpoint::OnCreateService(
scoped_refptr<device::BluetoothSocket> socket) {
if (!socket.get()) {
LOG(WARNING) << "Couldn't create service!";
create_callback_.Run(std::string());
return;
}
VLOG(3) << "Starting Accept Socket.";
server_socket_ = socket;
create_callback_.Run(GetLocator());
server_socket_->Accept(
base::Bind(&CopresenceEndpoint::OnAccept, weak_ptr_factory_.GetWeakPtr()),
base::Bind(&CopresenceEndpoint::OnAcceptError,
weak_ptr_factory_.GetWeakPtr()));
}
void CopresenceEndpoint::OnCreateServiceError(const std::string& message) {
LOG(WARNING) << "Couldn't create Bluetooth service: " << message;
create_callback_.Run(std::string());
}
void CopresenceEndpoint::OnAccept(
const device::BluetoothDevice* device,
scoped_refptr<device::BluetoothSocket> socket) {
if (!socket.get())
return;
VLOG(3) << "Accepted Socket.";
client_socket_.reset(new CopresenceSocketBluetooth(socket));
accept_callback_.Run();
client_socket_->Receive(receive_callback_);
}
void CopresenceEndpoint::OnAcceptError(const std::string& message) {
LOG(WARNING) << "Couldn't accept Bluetooth connection: " << message;
}
} // namespace copresence_endpoints