/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hci/cert/cert.h" #include #include #include #include #include "common/blocking_queue.h" #include "grpc/grpc_event_stream.h" #include "hci/cert/api.grpc.pb.h" #include "hci/classic_security_manager.h" #include "hci/controller.h" #include "hci/hci_layer.h" #include "hci/hci_packets.h" #include "os/queue.h" #include "packet/raw_builder.h" using ::grpc::ServerAsyncResponseWriter; using ::grpc::ServerAsyncWriter; using ::grpc::ServerContext; using ::bluetooth::common::Bind; using ::bluetooth::common::BindOnce; using ::bluetooth::facade::EventStreamRequest; using ::bluetooth::packet::RawBuilder; namespace bluetooth { namespace hci { namespace cert { class AclManagerCertService : public AclManagerCert::Service { public: AclManagerCertService(Controller* controller, HciLayer* hci_layer, ::bluetooth::os::Handler* facade_handler) : controller_(controller), hci_layer_(hci_layer), handler_(facade_handler), acl_queue_end_(hci_layer_->GetAclQueueEnd()) { hci_layer_->RegisterEventHandler(EventCode::CONNECTION_COMPLETE, Bind(&AclManagerCertService::on_connection_complete, common::Unretained(this)), handler_); hci_layer_->RegisterEventHandler(EventCode::DISCONNECTION_COMPLETE, Bind(&AclManagerCertService::on_disconnection_complete, common::Unretained(this)), handler_); hci_layer_->RegisterEventHandler(EventCode::CONNECTION_REQUEST, Bind(&AclManagerCertService::on_incoming_connection, common::Unretained(this)), handler_); controller_->RegisterCompletedAclPacketsCallback(common::Bind([](uint16_t, uint16_t) { /* TODO check */ }), handler_); acl_queue_end_->RegisterDequeue(handler_, Bind(&AclManagerCertService::on_incoming_packet, common::Unretained(this))); } void on_incoming_packet() { auto packet = acl_queue_end_->TryDequeue(); ASSERT(packet->IsValid()); AclData acl_data; if (connected_devices_.find(packet->GetHandle()) == connected_devices_.end()) { LOG_ERROR("Can't find remote device"); return; } auto address = connected_devices_[packet->GetHandle()]; acl_data.mutable_remote()->set_address(address.ToString()); std::string data = std::string(packet->begin(), packet->end()); acl_data.set_payload(data); acl_stream_.OnIncomingEvent(acl_data); } ~AclManagerCertService() { acl_queue_end_->UnregisterDequeue(); hci_layer_->UnregisterEventHandler(EventCode::CONNECTION_REQUEST); hci_layer_->UnregisterEventHandler(EventCode::DISCONNECTION_COMPLETE); hci_layer_->UnregisterEventHandler(EventCode::CONNECTION_COMPLETE); } void on_connection_complete(EventPacketView packet) { ConnectionCompleteView connection_complete = ConnectionCompleteView::Create(std::move(packet)); ASSERT(connection_complete.IsValid()); auto status = connection_complete.GetStatus(); auto address = connection_complete.GetBdAddr(); auto handle = connection_complete.GetConnectionHandle(); if (status == ErrorCode::SUCCESS) { connected_devices_.emplace(handle, address); ConnectionEvent event; event.mutable_remote()->set_address(address.ToString()); connection_complete_stream_.OnIncomingEvent(event); } else { ConnectionFailedEvent event; event.mutable_remote()->set_address(address.ToString()); event.set_reason(static_cast(connection_complete.GetStatus())); connection_failed_stream_.OnIncomingEvent(event); } } void on_disconnection_complete(EventPacketView packet) { DisconnectionCompleteView disconnection_complete = DisconnectionCompleteView::Create(std::move(packet)); ASSERT(disconnection_complete.IsValid()); auto status = disconnection_complete.GetStatus(); auto handle = disconnection_complete.GetConnectionHandle(); auto device = connected_devices_.find(handle); ASSERT(device != connected_devices_.end()); auto address = device->second; if (status == ErrorCode::SUCCESS) { connected_devices_.erase(handle); DisconnectionEvent event; event.mutable_remote()->set_address(address.ToString()); event.set_reason(static_cast(disconnection_complete.GetReason())); disconnection_stream_.OnIncomingEvent(event); } } void on_incoming_connection(EventPacketView packet) { ConnectionRequestView request = ConnectionRequestView::Create(packet); ASSERT(request.IsValid()); Address address = request.GetBdAddr(); if (accepted_devices_.find(address) != accepted_devices_.end()) { auto role = AcceptConnectionRequestRole::BECOME_MASTER; // We prefer to be master hci_layer_->EnqueueCommand(AcceptConnectionRequestBuilder::Create(address, role), common::BindOnce([](CommandStatusView status) { /* TODO: check? */ }), handler_); } else { auto reason = RejectConnectionReason::LIMITED_RESOURCES; auto builder = RejectConnectionRequestBuilder::Create(address, reason); hci_layer_->EnqueueCommand(std::move(builder), BindOnce([](CommandStatusView status) { /* TODO: check? */ }), handler_); } } using EventStream = ::bluetooth::grpc::GrpcEventStream; ::grpc::Status ReadLocalAddress(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::bluetooth::facade::BluetoothAddress* response) override { auto address = controller_->GetControllerMacAddress().ToString(); response->set_address(address); return ::grpc::Status::OK; } ::grpc::Status SetPageScanMode(::grpc::ServerContext* context, const ::bluetooth::hci::cert::PageScanMode* request, ::google::protobuf::Empty* response) override { ScanEnable scan_enable = request->enabled() ? ScanEnable::PAGE_SCAN_ONLY : ScanEnable::NO_SCANS; std::promise promise; auto future = promise.get_future(); hci_layer_->EnqueueCommand( WriteScanEnableBuilder::Create(scan_enable), common::BindOnce([](std::promise promise, CommandCompleteView) { promise.set_value(); }, std::move(promise)), handler_); future.wait(); return ::grpc::Status::OK; } ::grpc::Status SetIncomingConnectionPolicy(::grpc::ServerContext* context, const ::bluetooth::hci::cert::IncomingConnectionPolicy* request, ::google::protobuf::Empty* response) override { std::unique_lock lock(mutex_); Address peer; ASSERT(Address::FromString(request->remote().address(), peer)); if (request->accepted()) { accepted_devices_.insert(peer); } else { accepted_devices_.erase(peer); } return ::grpc::Status::OK; } ::grpc::Status Connect(::grpc::ServerContext* context, const facade::BluetoothAddress* remote, ::google::protobuf::Empty* response) override { std::unique_lock lock(mutex_); uint16_t packet_type = 0x4408 /* DM 1,3,5 */ | 0x8810 /*DH 1,3,5 */; PageScanRepetitionMode page_scan_repetition_mode = PageScanRepetitionMode::R1; uint16_t clock_offset = 0; ClockOffsetValid clock_offset_valid = ClockOffsetValid::INVALID; CreateConnectionRoleSwitch allow_role_switch = CreateConnectionRoleSwitch::ALLOW_ROLE_SWITCH; Address peer; ASSERT(Address::FromString(remote->address(), peer)); std::unique_ptr packet = CreateConnectionBuilder::Create( peer, packet_type, page_scan_repetition_mode, clock_offset, clock_offset_valid, allow_role_switch); hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandStatusView status) { ASSERT(status.IsValid()); ASSERT(status.GetCommandOpCode() == OpCode::CREATE_CONNECTION); }), handler_); return ::grpc::Status::OK; } ::grpc::Status Disconnect(::grpc::ServerContext* context, const facade::BluetoothAddress* request, ::google::protobuf::Empty* response) override { std::unique_lock lock(mutex_); Address peer; Address::FromString(request->address(), peer); uint16_t handle = find_connected_device_handle_by_address(peer); if (handle == kInvalidHandle) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid address"); } DisconnectReason reason = DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION; std::unique_ptr packet = DisconnectBuilder::Create(handle, reason); hci_layer_->EnqueueCommand(std::move(packet), BindOnce([](CommandStatusView status) { /* TODO: check? */ }), handler_); return ::grpc::Status::OK; } ::grpc::Status SendAclData(::grpc::ServerContext* context, const AclData* request, ::google::protobuf::Empty* response) override { Address peer; Address::FromString(request->remote().address(), peer); auto handle = find_connected_device_handle_by_address(peer); if (handle == kInvalidHandle) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid address"); } constexpr PacketBoundaryFlag packet_boundary_flag = PacketBoundaryFlag::COMPLETE_PDU; constexpr BroadcastFlag broadcast_flag = BroadcastFlag::POINT_TO_POINT; std::unique_ptr packet = std::make_unique(); auto req_string = request->payload(); packet->AddOctets(std::vector(req_string.begin(), req_string.end())); auto acl_packet = AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(packet)); acl_enqueue_buffer_.Enqueue(std::move(acl_packet), handler_); return ::grpc::Status::OK; } ::grpc::Status FetchAclData(::grpc::ServerContext* context, const facade::EventStreamRequest* request, ::grpc::ServerWriter* writer) override { return acl_stream_.HandleRequest(context, request, writer); } ::grpc::Status FetchConnectionComplete(::grpc::ServerContext* context, const EventStreamRequest* request, ::grpc::ServerWriter* writer) override { return connection_complete_stream_.HandleRequest(context, request, writer); }; ::grpc::Status FetchConnectionFailed(::grpc::ServerContext* context, const EventStreamRequest* request, ::grpc::ServerWriter* writer) override { return connection_failed_stream_.HandleRequest(context, request, writer); }; ::grpc::Status FetchDisconnection(::grpc::ServerContext* context, const ::bluetooth::facade::EventStreamRequest* request, ::grpc::ServerWriter* writer) override { return disconnection_stream_.HandleRequest(context, request, writer); } private: Controller* controller_; HciLayer* hci_layer_; ::bluetooth::os::Handler* handler_; common::BidiQueueEnd* acl_queue_end_; os::EnqueueBuffer acl_enqueue_buffer_{acl_queue_end_}; mutable std::mutex mutex_; std::set
accepted_devices_; std::map connected_devices_; constexpr static uint16_t kInvalidHandle = 0xffff; uint16_t find_connected_device_handle_by_address(Address address) { for (auto device : connected_devices_) { if (device.second == address) { return device.first; } } return kInvalidHandle; // Can't find } class ConnectionCompleteStreamCallback : public ::bluetooth::grpc::GrpcEventStreamCallback { public: void OnWriteResponse(ConnectionEvent* response, const ConnectionEvent& connection) override { response->CopyFrom(connection); } } connection_complete_stream_callback_; ::bluetooth::grpc::GrpcEventStream connection_complete_stream_{ &connection_complete_stream_callback_}; class ConnectionFailedStreamCallback : public ::bluetooth::grpc::GrpcEventStreamCallback { public: void OnWriteResponse(ConnectionFailedEvent* response, const ConnectionFailedEvent& event) override { response->CopyFrom(event); } } connection_failed_stream_callback_; ::bluetooth::grpc::GrpcEventStream connection_failed_stream_{ &connection_failed_stream_callback_}; class DisconnectionStreamCallback : public ::bluetooth::grpc::GrpcEventStreamCallback { public: void OnWriteResponse(DisconnectionEvent* response, const DisconnectionEvent& event) override { response->CopyFrom(event); } } disconnection_stream_callback_; ::bluetooth::grpc::GrpcEventStream disconnection_stream_{ &disconnection_stream_callback_}; class AclStreamCallback : public ::bluetooth::grpc::GrpcEventStreamCallback { public: void OnWriteResponse(AclData* response, const AclData& event) override { response->CopyFrom(event); } } acl_stream_callback_; ::bluetooth::grpc::GrpcEventStream acl_stream_{&acl_stream_callback_}; }; void AclManagerCertModule::ListDependencies(ModuleList* list) { ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list); list->add(); list->add(); list->add(); } void AclManagerCertModule::Start() { ::bluetooth::grpc::GrpcFacadeModule::Start(); service_ = new AclManagerCertService(GetDependency(), GetDependency(), GetHandler()); } void AclManagerCertModule::Stop() { delete service_; ::bluetooth::grpc::GrpcFacadeModule::Stop(); } ::grpc::Service* AclManagerCertModule::GetService() const { return service_; } const ModuleFactory AclManagerCertModule::Factory = ::bluetooth::ModuleFactory([]() { return new AclManagerCertModule(); }); } // namespace cert } // namespace hci } // namespace bluetooth