| /* |
| * 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/facade.h" |
| |
| #include <condition_variable> |
| #include <memory> |
| #include <mutex> |
| |
| #include "common/bind.h" |
| #include "common/blocking_queue.h" |
| #include "grpc/grpc_event_stream.h" |
| #include "hci/acl_manager.h" |
| #include "hci/classic_security_manager.h" |
| #include "hci/controller.h" |
| #include "hci/facade.grpc.pb.h" |
| #include "hci/hci_layer.h" |
| #include "hci/hci_packets.h" |
| #include "packet/raw_builder.h" |
| |
| using ::grpc::ServerAsyncResponseWriter; |
| using ::grpc::ServerAsyncWriter; |
| using ::grpc::ServerContext; |
| |
| using ::bluetooth::facade::EventStreamRequest; |
| using ::bluetooth::packet::RawBuilder; |
| |
| namespace bluetooth { |
| namespace hci { |
| |
| class AclManagerFacadeService : public AclManagerFacade::Service, |
| public ::bluetooth::hci::ConnectionCallbacks, |
| public ::bluetooth::hci::ConnectionManagementCallbacks, |
| public ::bluetooth::hci::AclManagerCallbacks { |
| public: |
| AclManagerFacadeService(AclManager* acl_manager, Controller* controller, HciLayer* hci_layer, |
| ::bluetooth::os::Handler* facade_handler) |
| : acl_manager_(acl_manager), controller_(controller), hci_layer_(hci_layer), facade_handler_(facade_handler) { |
| acl_manager_->RegisterCallbacks(this, facade_handler_); |
| acl_manager_->RegisterAclManagerCallbacks(this, facade_handler_); |
| } |
| |
| using EventStream = ::bluetooth::grpc::GrpcEventStream<AclData, AclPacketView>; |
| |
| ::grpc::Status SetPageScanMode(::grpc::ServerContext* context, const ::bluetooth::hci::PageScanMode* request, |
| ::google::protobuf::Empty* response) override { |
| ScanEnable scan_enable = request->enabled() ? ScanEnable::PAGE_SCAN_ONLY : ScanEnable::NO_SCANS; |
| std::promise<void> promise; |
| auto future = promise.get_future(); |
| hci_layer_->EnqueueCommand( |
| WriteScanEnableBuilder::Create(scan_enable), |
| common::BindOnce([](std::promise<void> promise, CommandCompleteView) { promise.set_value(); }, |
| std::move(promise)), |
| facade_handler_); |
| future.wait(); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status Connect(::grpc::ServerContext* context, const facade::BluetoothAddress* remote, |
| ::google::protobuf::Empty* response) override { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(remote->address(), peer)); |
| acl_manager_->CreateConnection(peer); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status Disconnect(::grpc::ServerContext* context, const facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) override { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| Address::FromString(request->address(), peer); |
| auto connection = acl_connections_.find(request->address()); |
| if (connection == acl_connections_.end()) { |
| LOG_ERROR("Invalid address"); |
| return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid address"); |
| } else { |
| connection->second->Disconnect(DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION); |
| return ::grpc::Status::OK; |
| } |
| } |
| |
| ::grpc::Status AuthenticationRequested(::grpc::ServerContext* context, const facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) override { |
| Address peer; |
| Address::FromString(request->address(), peer); |
| auto connection = acl_connections_.find(request->address()); |
| if (connection == acl_connections_.end()) { |
| LOG_ERROR("Invalid address"); |
| return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid address"); |
| } else { |
| connection->second->AuthenticationRequested(); |
| return ::grpc::Status::OK; |
| } |
| }; |
| |
| ::grpc::Status SendAclData(::grpc::ServerContext* context, const AclData* request, |
| ::google::protobuf::Empty* response) override { |
| std::unique_lock<std::mutex> lock(mutex_); |
| std::promise<void> promise; |
| auto future = promise.get_future(); |
| acl_connections_[request->remote().address()]->GetAclQueueEnd()->RegisterEnqueue( |
| facade_handler_, common::Bind(&AclManagerFacadeService::enqueue_packet, common::Unretained(this), |
| common::Unretained(request), common::Passed(std::move(promise)))); |
| future.wait(); |
| return ::grpc::Status::OK; |
| } |
| |
| std::unique_ptr<BasePacketBuilder> enqueue_packet(const AclData* request, std::promise<void> promise) { |
| acl_connections_[request->remote().address()]->GetAclQueueEnd()->UnregisterEnqueue(); |
| std::string req_string = request->payload(); |
| std::unique_ptr<RawBuilder> packet = std::make_unique<RawBuilder>(); |
| packet->AddOctets(std::vector<uint8_t>(req_string.begin(), req_string.end())); |
| promise.set_value(); |
| return packet; |
| } |
| |
| ::grpc::Status FetchAclData(::grpc::ServerContext* context, const facade::EventStreamRequest* request, |
| ::grpc::ServerWriter<AclData>* writer) override { |
| std::unique_lock<std::mutex> lock(mutex_); |
| return acl_stream_.HandleRequest(context, request, writer); |
| } |
| |
| ::grpc::Status TestInternalHciCommands(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, |
| ::google::protobuf::Empty* response) { |
| LocalVersionInformation local_version_information = controller_->GetControllerLocalVersionInformation(); |
| LOG_DEBUG("local name : %s", controller_->GetControllerLocalName().c_str()); |
| controller_->WriteLocalName("Device Under Test"); |
| LOG_DEBUG("new local name : %s", controller_->GetControllerLocalName().c_str()); |
| LOG_DEBUG("manufacturer name : %d", local_version_information.manufacturer_name_); |
| LOG_DEBUG("hci version : %x", (uint16_t)local_version_information.hci_version_); |
| LOG_DEBUG("lmp version : %x", (uint16_t)local_version_information.lmp_version_); |
| LOG_DEBUG("supported commands : %x", controller_->GetControllerLocalSupportedCommands()[0]); |
| LOG_DEBUG("local extended features :"); |
| |
| controller_->SetEventMask(0x00001FFFFFFFFFFF); |
| controller_->SetEventFilterInquiryResultAllDevices(); |
| ClassOfDevice class_of_device({0xab, 0xcd, 0xef}); |
| ClassOfDevice class_of_device_mask({0x12, 0x34, 0x56}); |
| controller_->SetEventFilterInquiryResultClassOfDevice(class_of_device, class_of_device_mask); |
| Address bdaddr({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}); |
| controller_->SetEventFilterInquiryResultAddress(bdaddr); |
| controller_->SetEventFilterConnectionSetupAllDevices(AutoAcceptFlag::AUTO_ACCEPT_OFF); |
| controller_->SetEventFilterConnectionSetupClassOfDevice(class_of_device, class_of_device_mask, |
| AutoAcceptFlag::AUTO_ACCEPT_ON_ROLE_SWITCH_DISABLED); |
| controller_->SetEventFilterConnectionSetupAddress(bdaddr, AutoAcceptFlag::AUTO_ACCEPT_ON_ROLE_SWITCH_ENABLED); |
| controller_->SetEventFilterClearAll(); |
| controller_->HostBufferSize(0xFF00, 0xF1, 0xFF02, 0xFF03); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status TestInternalHciLeCommands(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, |
| ::google::protobuf::Empty* response) { |
| LOG_DEBUG("le data packet length : %d", controller_->GetControllerLeBufferSize().le_data_packet_length_); |
| LOG_DEBUG("total num le packets : %d", controller_->GetControllerLeBufferSize().total_num_le_packets_); |
| LOG_DEBUG("le supported max tx octets : %d", |
| controller_->GetControllerLeMaximumDataLength().supported_max_tx_octets_); |
| LOG_DEBUG("le supported max tx times : %d", controller_->GetControllerLeMaximumDataLength().supported_max_tx_time_); |
| LOG_DEBUG("le supported max rx octets : %d", |
| controller_->GetControllerLeMaximumDataLength().supported_max_rx_octets_); |
| LOG_DEBUG("le supported max rx times : %d", controller_->GetControllerLeMaximumDataLength().supported_max_rx_time_); |
| LOG_DEBUG("le maximum advertising data length %d", controller_->GetControllerLeMaximumAdvertisingDataLength()); |
| LOG_DEBUG("le number of supported advertising sets %d", |
| controller_->GetControllerLeNumberOfSupportedAdverisingSets()); |
| |
| controller_->LeSetEventMask(0x000000000000001F); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status TestClassicConnectionManagementCommands(::grpc::ServerContext* context, |
| const facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) { |
| Address peer; |
| Address::FromString(request->address(), peer); |
| auto connection = acl_connections_.find(request->address()); |
| if (connection == acl_connections_.end()) { |
| LOG_ERROR("Invalid address"); |
| return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid address"); |
| } else { |
| // TODO add individual grpc command if necessary |
| connection->second->RoleDiscovery(); |
| connection->second->WriteLinkPolicySettings(0x07); |
| connection->second->ReadLinkPolicySettings(); |
| connection->second->SniffSubrating(0x1234, 0x1234, 0x1234); |
| connection->second->WriteAutomaticFlushTimeout(0x07FF); |
| connection->second->ReadAutomaticFlushTimeout(); |
| connection->second->ReadTransmitPowerLevel(TransmitPowerLevelType::CURRENT); |
| connection->second->ReadTransmitPowerLevel(TransmitPowerLevelType::MAXIMUM); |
| connection->second->WriteLinkSupervisionTimeout(0x5678); |
| connection->second->ReadLinkSupervisionTimeout(); |
| connection->second->ReadFailedContactCounter(); |
| connection->second->ResetFailedContactCounter(); |
| connection->second->ReadLinkQuality(); |
| connection->second->ReadAfhChannelMap(); |
| connection->second->ReadRssi(); |
| connection->second->ReadClock(WhichClock::LOCAL); |
| connection->second->ReadClock(WhichClock::PICONET); |
| |
| connection->second->ChangeConnectionPacketType(0xEE1C); |
| connection->second->SetConnectionEncryption(Enable::ENABLED); |
| connection->second->ChangeConnectionLinkKey(); |
| connection->second->ReadClockOffset(); |
| connection->second->HoldMode(0x0500, 0x0020); |
| connection->second->SniffMode(0x0500, 0x0020, 0x0040, 0x0014); |
| connection->second->ExitSniffMode(); |
| connection->second->QosSetup(ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231); |
| connection->second->FlowSpecification(FlowDirection::OUTGOING_FLOW, ServiceType::BEST_EFFORT, 0x1234, 0x1233, |
| 0x1232, 0x1231); |
| connection->second->Flush(); |
| |
| acl_manager_->MasterLinkKey(KeyFlag::TEMPORARY); |
| acl_manager_->SwitchRole(peer, Role::MASTER); |
| acl_manager_->WriteDefaultLinkPolicySettings(0x07); |
| acl_manager_->ReadDefaultLinkPolicySettings(); |
| return ::grpc::Status::OK; |
| } |
| } |
| |
| void on_incoming_acl(std::string address) { |
| auto connection = acl_connections_.find(address); |
| if (connection == acl_connections_.end()) { |
| LOG_ERROR("Invalid address"); |
| return; |
| } |
| |
| auto packet = connection->second->GetAclQueueEnd()->TryDequeue(); |
| auto acl_packet = AclPacketView::Create(*packet); |
| AclData acl_data; |
| acl_data.mutable_remote()->set_address(address); |
| std::string data = std::string(acl_packet.begin(), acl_packet.end()); |
| acl_data.set_payload(data); |
| acl_stream_.OnIncomingEvent(acl_data); |
| } |
| |
| void OnConnectSuccess(std::unique_ptr<::bluetooth::hci::AclConnection> connection) override { |
| std::unique_lock<std::mutex> lock(mutex_); |
| auto addr = connection->GetAddress(); |
| std::shared_ptr<::bluetooth::hci::AclConnection> shared_connection = std::move(connection); |
| acl_connections_.emplace(addr.ToString(), shared_connection); |
| shared_connection->RegisterDisconnectCallback( |
| common::BindOnce(&AclManagerFacadeService::on_disconnect, common::Unretained(this), addr.ToString()), |
| facade_handler_); |
| shared_connection->RegisterCallbacks(this, facade_handler_); |
| connection_complete_stream_.OnIncomingEvent(shared_connection); |
| } |
| |
| void OnMasterLinkKeyComplete(uint16_t connection_handle, KeyFlag key_flag) override { |
| LOG_DEBUG("OnMasterLinkKeyComplete connection_handle:%d", connection_handle); |
| } |
| |
| void OnRoleChange(Address bd_addr, Role new_role) override { |
| LOG_DEBUG("OnRoleChange bd_addr:%s, new_role:%d", bd_addr.ToString().c_str(), (uint8_t)new_role); |
| } |
| |
| void OnReadDefaultLinkPolicySettingsComplete(uint16_t default_link_policy_settings) override { |
| LOG_DEBUG("OnReadDefaultLinkPolicySettingsComplete default_link_policy_settings:%d", default_link_policy_settings); |
| } |
| |
| void on_disconnect(std::string address, ErrorCode code) { |
| acl_connections_.erase(address); |
| DisconnectionEvent event; |
| event.mutable_remote()->set_address(address); |
| event.set_reason(static_cast<uint32_t>(code)); |
| disconnection_stream_.OnIncomingEvent(event); |
| } |
| |
| ::grpc::Status FetchConnectionComplete(::grpc::ServerContext* context, const EventStreamRequest* request, |
| ::grpc::ServerWriter<ConnectionEvent>* writer) override { |
| return connection_complete_stream_.HandleRequest(context, request, writer); |
| }; |
| |
| void OnConnectFail(Address address, ::bluetooth::hci::ErrorCode reason) override { |
| std::unique_lock<std::mutex> lock(mutex_); |
| ConnectionFailedEvent event; |
| event.mutable_remote()->set_address(address.ToString()); |
| event.set_reason(static_cast<uint32_t>(reason)); |
| connection_failed_stream_.OnIncomingEvent(event); |
| } |
| |
| void OnConnectionPacketTypeChanged(uint16_t packet_type) override { |
| LOG_DEBUG("OnConnectionPacketTypeChanged packet_type:%d", packet_type); |
| } |
| |
| void OnAuthenticationComplete() override { |
| LOG_DEBUG("OnAuthenticationComplete"); |
| } |
| |
| void OnEncryptionChange(EncryptionEnabled enabled) override { |
| LOG_DEBUG("OnConnectionPacketTypeChanged enabled:%d", (uint8_t)enabled); |
| } |
| |
| void OnChangeConnectionLinkKeyComplete() override { |
| LOG_DEBUG("OnChangeConnectionLinkKeyComplete"); |
| }; |
| |
| void OnReadClockOffsetComplete(uint16_t clock_offset) override { |
| LOG_DEBUG("OnReadClockOffsetComplete clock_offset:%d", clock_offset); |
| }; |
| |
| void OnModeChange(Mode current_mode, uint16_t interval) override { |
| LOG_DEBUG("OnModeChange Mode:%d, interval:%d", (uint8_t)current_mode, interval); |
| }; |
| |
| void OnQosSetupComplete(ServiceType service_type, uint32_t token_rate, uint32_t peak_bandwidth, uint32_t latency, |
| uint32_t delay_variation) override { |
| LOG_DEBUG("OnQosSetupComplete service_type:%d, token_rate:%d, peak_bandwidth:%d, latency:%d, delay_variation:%d", |
| (uint8_t)service_type, token_rate, peak_bandwidth, latency, delay_variation); |
| } |
| |
| void OnFlowSpecificationComplete(FlowDirection flow_direction, ServiceType service_type, uint32_t token_rate, |
| uint32_t token_bucket_size, uint32_t peak_bandwidth, |
| uint32_t access_latency) override { |
| LOG_DEBUG( |
| "OnFlowSpecificationComplete flow_direction:%d. service_type:%d, token_rate:%d, token_bucket_size:%d, " |
| "peak_bandwidth:%d, access_latency:%d", |
| (uint8_t)flow_direction, (uint8_t)service_type, token_rate, token_bucket_size, peak_bandwidth, access_latency); |
| } |
| |
| void OnFlushOccurred() override { |
| LOG_DEBUG("OnFlushOccurred"); |
| } |
| |
| void OnRoleDiscoveryComplete(Role current_role) override { |
| LOG_DEBUG("OnRoleDiscoveryComplete current_role:%d", (uint8_t)current_role); |
| } |
| |
| void OnReadLinkPolicySettingsComplete(uint16_t link_policy_settings) override { |
| LOG_DEBUG("OnReadLinkPolicySettingsComplete link_policy_settings:%d", link_policy_settings); |
| } |
| |
| void OnReadAutomaticFlushTimeoutComplete(uint16_t flush_timeout) override { |
| LOG_DEBUG("OnReadAutomaticFlushTimeoutComplete flush_timeout:%d", flush_timeout); |
| } |
| |
| void OnReadTransmitPowerLevelComplete(uint8_t transmit_power_level) override { |
| LOG_DEBUG("OnReadTransmitPowerLevelComplete transmit_power_level:%d", transmit_power_level); |
| } |
| |
| void OnReadLinkSupervisionTimeoutComplete(uint16_t link_supervision_timeout) override { |
| LOG_DEBUG("OnReadLinkSupervisionTimeoutComplete link_supervision_timeout:%d", link_supervision_timeout); |
| } |
| |
| void OnReadFailedContactCounterComplete(uint16_t failed_contact_counter) override { |
| LOG_DEBUG("OnReadFailedContactCounterComplete failed_contact_counter:%d", failed_contact_counter); |
| } |
| |
| void OnReadLinkQualityComplete(uint8_t link_quality) override { |
| LOG_DEBUG("OnReadLinkQualityComplete link_quality:%d", link_quality); |
| } |
| |
| void OnReadAfhChannelMapComplete(AfhMode afh_mode, std::array<uint8_t, 10> afh_channel_map) { |
| LOG_DEBUG("OnReadAfhChannelMapComplete afh_mode:%d", (uint8_t)afh_mode); |
| } |
| |
| void OnReadRssiComplete(uint8_t rssi) override { |
| LOG_DEBUG("OnReadRssiComplete rssi:%d", rssi); |
| } |
| |
| void OnReadClockComplete(uint32_t clock, uint16_t accuracy) override { |
| LOG_DEBUG("OnReadClockComplete clock:%d, accuracy:%d", clock, accuracy); |
| } |
| |
| ::grpc::Status FetchConnectionFailed(::grpc::ServerContext* context, const EventStreamRequest* request, |
| ::grpc::ServerWriter<ConnectionFailedEvent>* writer) override { |
| return connection_failed_stream_.HandleRequest(context, request, writer); |
| }; |
| |
| ::grpc::Status FetchDisconnection(::grpc::ServerContext* context, |
| const ::bluetooth::facade::EventStreamRequest* request, |
| ::grpc::ServerWriter<DisconnectionEvent>* writer) override { |
| return disconnection_stream_.HandleRequest(context, request, writer); |
| } |
| |
| private: |
| AclManager* acl_manager_; |
| Controller* controller_; |
| HciLayer* hci_layer_; |
| mutable std::mutex mutex_; |
| ::bluetooth::os::Handler* facade_handler_; |
| |
| class ConnectionCompleteStreamCallback |
| : public ::bluetooth::grpc::GrpcEventStreamCallback<ConnectionEvent, std::shared_ptr<AclConnection>> { |
| public: |
| void OnWriteResponse(ConnectionEvent* response, const std::shared_ptr<AclConnection>& connection) override { |
| response->mutable_remote()->set_address(connection->GetAddress().ToString()); |
| response->set_connection_handle(connection->GetHandle()); |
| } |
| } connection_complete_stream_callback_; |
| ::bluetooth::grpc::GrpcEventStream<ConnectionEvent, std::shared_ptr<AclConnection>> connection_complete_stream_{ |
| &connection_complete_stream_callback_}; |
| |
| class ConnectionFailedStreamCallback |
| : public ::bluetooth::grpc::GrpcEventStreamCallback<ConnectionFailedEvent, ConnectionFailedEvent> { |
| public: |
| void OnWriteResponse(ConnectionFailedEvent* response, const ConnectionFailedEvent& event) override { |
| response->CopyFrom(event); |
| } |
| } connection_failed_stream_callback_; |
| ::bluetooth::grpc::GrpcEventStream<ConnectionFailedEvent, ConnectionFailedEvent> connection_failed_stream_{ |
| &connection_failed_stream_callback_}; |
| |
| class DisconnectionStreamCallback |
| : public ::bluetooth::grpc::GrpcEventStreamCallback<DisconnectionEvent, DisconnectionEvent> { |
| public: |
| void OnWriteResponse(DisconnectionEvent* response, const DisconnectionEvent& event) override { |
| response->CopyFrom(event); |
| } |
| } disconnection_stream_callback_; |
| ::bluetooth::grpc::GrpcEventStream<DisconnectionEvent, DisconnectionEvent> disconnection_stream_{ |
| &disconnection_stream_callback_}; |
| |
| class AclStreamCallback : public ::bluetooth::grpc::GrpcEventStreamCallback<AclData, AclData> { |
| public: |
| AclStreamCallback(AclManagerFacadeService* service) : service_(service) {} |
| |
| ~AclStreamCallback() { |
| if (subscribed_) { |
| for (const auto& connection : service_->acl_connections_) { |
| connection.second->GetAclQueueEnd()->UnregisterDequeue(); |
| } |
| subscribed_ = false; |
| } |
| } |
| |
| void OnSubscribe() override { |
| if (subscribed_) { |
| LOG_WARN("Already subscribed"); |
| return; |
| } |
| for (const auto& connection : service_->acl_connections_) { |
| auto remote_address = connection.second->GetAddress().ToString(); |
| connection.second->GetAclQueueEnd()->RegisterDequeue( |
| service_->facade_handler_, |
| common::Bind(&AclManagerFacadeService::on_incoming_acl, common::Unretained(service_), remote_address)); |
| } |
| subscribed_ = true; |
| } |
| |
| void OnUnsubscribe() override { |
| if (!subscribed_) { |
| LOG_WARN("Not subscribed"); |
| return; |
| } |
| for (const auto& connection : service_->acl_connections_) { |
| connection.second->GetAclQueueEnd()->UnregisterDequeue(); |
| } |
| subscribed_ = false; |
| } |
| |
| void OnWriteResponse(AclData* response, const AclData& event) override { |
| response->CopyFrom(event); |
| } |
| |
| private: |
| AclManagerFacadeService* service_; |
| bool subscribed_ = false; |
| } acl_stream_callback_{this}; |
| ::bluetooth::grpc::GrpcEventStream<AclData, AclData> acl_stream_{&acl_stream_callback_}; |
| |
| std::map<std::string, std::shared_ptr<AclConnection>> acl_connections_; |
| }; |
| |
| void AclManagerFacadeModule::ListDependencies(ModuleList* list) { |
| ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list); |
| list->add<AclManager>(); |
| list->add<Controller>(); |
| list->add<HciLayer>(); |
| } |
| |
| void AclManagerFacadeModule::Start() { |
| ::bluetooth::grpc::GrpcFacadeModule::Start(); |
| service_ = new AclManagerFacadeService(GetDependency<AclManager>(), GetDependency<Controller>(), |
| GetDependency<HciLayer>(), GetHandler()); |
| } |
| |
| void AclManagerFacadeModule::Stop() { |
| delete service_; |
| ::bluetooth::grpc::GrpcFacadeModule::Stop(); |
| } |
| |
| ::grpc::Service* AclManagerFacadeModule::GetService() const { |
| return service_; |
| } |
| |
| const ModuleFactory AclManagerFacadeModule::Factory = |
| ::bluetooth::ModuleFactory([]() { return new AclManagerFacadeModule(); }); |
| |
| class ClassicSecurityManagerFacadeService : public ClassicSecurityManagerFacade::Service, |
| public ::bluetooth::hci::ClassicSecurityCommandCallbacks { |
| public: |
| ClassicSecurityManagerFacadeService(ClassicSecurityManager* classic_security_manager, Controller* controller, |
| HciLayer* hci_layer, ::bluetooth::os::Handler* facade_handler) |
| : classic_security_manager_(classic_security_manager), facade_handler_(facade_handler) { |
| classic_security_manager_->RegisterCallbacks(this, facade_handler_); |
| } |
| |
| ::grpc::Status LinkKeyRequestReply(::grpc::ServerContext* context, |
| const ::bluetooth::hci::LinkKeyRequestReplyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| common::LinkKey link_key; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| ASSERT(common::LinkKey::FromString(request->link_key(), link_key)); |
| classic_security_manager_->LinkKeyRequestReply(peer, link_key); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status LinkKeyRequestNegativeReply(::grpc::ServerContext* context, |
| const ::bluetooth::facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->address(), peer)); |
| classic_security_manager_->LinkKeyRequestNegativeReply(peer); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status PinCodeRequestReply(::grpc::ServerContext* context, |
| const ::bluetooth::hci::PinCodeRequestReplyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| uint8_t len = request->len(); |
| std::string pin_code = request->pin_code(); |
| classic_security_manager_->PinCodeRequestReply(peer, len, pin_code); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status PinCodeRequestNegativeReply(::grpc::ServerContext* context, |
| const ::bluetooth::facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->address(), peer)); |
| classic_security_manager_->PinCodeRequestNegativeReply(peer); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status IoCapabilityRequestReply(::grpc::ServerContext* context, |
| const ::bluetooth::hci::IoCapabilityRequestReplyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| IoCapability io_capability = (IoCapability)request->io_capability(); |
| OobDataPresent oob_present = (OobDataPresent)request->oob_present(); |
| AuthenticationRequirements authentication_requirements = |
| (AuthenticationRequirements)request->authentication_requirements(); |
| classic_security_manager_->IoCapabilityRequestReply(peer, io_capability, oob_present, authentication_requirements); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status IoCapabilityRequestNegativeReply( |
| ::grpc::ServerContext* context, const ::bluetooth::hci::IoCapabilityRequestNegativeReplyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| ErrorCode reason = (ErrorCode)request->reason(); |
| classic_security_manager_->IoCapabilityRequestNegativeReply(peer, reason); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status UserConfirmationRequestReply(::grpc::ServerContext* context, |
| const ::bluetooth::facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->address(), peer)); |
| classic_security_manager_->UserConfirmationRequestReply(peer); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status UserConfirmationRequestNegativeReply(::grpc::ServerContext* context, |
| const ::bluetooth::facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->address(), peer)); |
| classic_security_manager_->UserConfirmationRequestNegativeReply(peer); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status UserPasskeyRequestReply(::grpc::ServerContext* context, |
| const ::bluetooth::hci::UserPasskeyRequestReplyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| uint32_t passkey = request->passkey(); |
| classic_security_manager_->UserPasskeyRequestReply(peer, passkey); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status UserPasskeyRequestNegativeReply(::grpc::ServerContext* context, |
| const ::bluetooth::facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->address(), peer)); |
| classic_security_manager_->UserPasskeyRequestNegativeReply(peer); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status RemoteOobDataRequestReply(::grpc::ServerContext* context, |
| const ::bluetooth::hci::RemoteOobDataRequestReplyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| std::string c_string = request->c(); |
| std::string r_string = request->r(); |
| std::array<uint8_t, 16> c; |
| std::array<uint8_t, 16> r; |
| std::copy(std::begin(c_string), std::end(c_string), std::begin(c)); |
| std::copy(std::begin(r_string), std::end(r_string), std::begin(r)); |
| classic_security_manager_->RemoteOobDataRequestReply(peer, c, r); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status RemoteOobDataRequestNegativeReply(::grpc::ServerContext* context, |
| const ::bluetooth::facade::BluetoothAddress* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->address(), peer)); |
| classic_security_manager_->RemoteOobDataRequestNegativeReply(peer); |
| return ::grpc::Status::OK; |
| } |
| |
| ::grpc::Status ReadStoredLinkKey(::grpc::ServerContext* context, |
| const ::bluetooth::hci::ReadStoredLinkKeyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| ReadStoredLinkKeyReadAllFlag read_all_flag = (ReadStoredLinkKeyReadAllFlag)request->read_all_flag(); |
| classic_security_manager_->ReadStoredLinkKey(peer, read_all_flag); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status WriteStoredLinkKey(::grpc::ServerContext* context, |
| const ::bluetooth::hci::WriteStoredLinkKeyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| uint8_t num_keys_to_write = request->num_keys_to_write(); |
| std::vector<KeyAndAddress> keys; |
| for (size_t i = 0; i < num_keys_to_write; i++) { |
| KeyAndAddress key; |
| common::LinkKey link_key; |
| ASSERT(Address::FromString(request->remote().address(), key.address_)); |
| ASSERT(common::LinkKey::FromString(request->link_keys(), link_key)); |
| std::copy(std::begin(link_key.link_key), std::end(link_key.link_key), std::begin(key.link_key_)); |
| keys.push_back(key); |
| } |
| |
| classic_security_manager_->WriteStoredLinkKey(keys); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status DeleteStoredLinkKey(::grpc::ServerContext* context, |
| const ::bluetooth::hci::DeleteStoredLinkKeyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| DeleteStoredLinkKeyDeleteAllFlag delete_all_flag = (DeleteStoredLinkKeyDeleteAllFlag)request->delete_all_flag(); |
| classic_security_manager_->DeleteStoredLinkKey(peer, delete_all_flag); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status RefreshEncryptionKey(::grpc::ServerContext* context, |
| const ::bluetooth::hci::RefreshEncryptionKeyMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| classic_security_manager_->RefreshEncryptionKey(request->connection_handle()); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status ReadSimplePairingMode(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| classic_security_manager_->ReadSimplePairingMode(); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status WriteSimplePairingMode(::grpc::ServerContext* context, |
| const ::bluetooth::hci::WriteSimplePairingModeMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Enable simple_pairing_mode = (Enable)request->simple_pairing_mode(); |
| classic_security_manager_->WriteSimplePairingMode(simple_pairing_mode); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status ReadLocalOobData(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| classic_security_manager_->ReadLocalOobData(); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status SendKeypressNotification(::grpc::ServerContext* context, |
| const ::bluetooth::hci::SendKeypressNotificationMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| Address peer; |
| ASSERT(Address::FromString(request->remote().address(), peer)); |
| KeypressNotificationType notification_type = (KeypressNotificationType)request->notification_type(); |
| classic_security_manager_->SendKeypressNotification(peer, notification_type); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status ReadLocalOobExtendedData(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| classic_security_manager_->ReadLocalOobExtendedData(); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status ReadEncryptionKeySize(::grpc::ServerContext* context, |
| const ::bluetooth::hci::ReadEncryptionKeySizeMessage* request, |
| ::google::protobuf::Empty* response) { |
| std::unique_lock<std::mutex> lock(mutex_); |
| classic_security_manager_->ReadEncryptionKeySize(request->connection_handle()); |
| return ::grpc::Status::OK; |
| }; |
| |
| ::grpc::Status FetchCommandCompleteEvent(::grpc::ServerContext* context, const EventStreamRequest* request, |
| ::grpc::ServerWriter<CommandCompleteEvent>* writer) override { |
| return command_complete_stream_.HandleRequest(context, request, writer); |
| }; |
| |
| void OnCommandComplete(CommandCompleteView status) override { |
| std::unique_lock<std::mutex> lock(mutex_); |
| command_complete_stream_.OnIncomingEvent(status); |
| } |
| |
| private: |
| ClassicSecurityManager* classic_security_manager_; |
| mutable std::mutex mutex_; |
| ::bluetooth::os::Handler* facade_handler_; |
| |
| class CommandCompleteStreamCallback |
| : public ::bluetooth::grpc::GrpcEventStreamCallback<CommandCompleteEvent, CommandCompleteView> { |
| public: |
| void OnWriteResponse(CommandCompleteEvent* response, CommandCompleteView const& status) override { |
| response->set_command_opcode((uint32_t)status.GetCommandOpCode()); |
| } |
| } command_complete_stream_callback_; |
| ::bluetooth::grpc::GrpcEventStream<CommandCompleteEvent, CommandCompleteView> command_complete_stream_{ |
| &command_complete_stream_callback_}; |
| }; |
| |
| void ClassicSecurityManagerFacadeModule::ListDependencies(ModuleList* list) { |
| ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list); |
| list->add<ClassicSecurityManager>(); |
| list->add<Controller>(); |
| list->add<HciLayer>(); |
| } |
| |
| void ClassicSecurityManagerFacadeModule::Start() { |
| ::bluetooth::grpc::GrpcFacadeModule::Start(); |
| service_ = new ClassicSecurityManagerFacadeService( |
| GetDependency<ClassicSecurityManager>(), GetDependency<Controller>(), GetDependency<HciLayer>(), GetHandler()); |
| } |
| |
| void ClassicSecurityManagerFacadeModule::Stop() { |
| delete service_; |
| ::bluetooth::grpc::GrpcFacadeModule::Stop(); |
| } |
| |
| ::grpc::Service* ClassicSecurityManagerFacadeModule::GetService() const { |
| return service_; |
| } |
| |
| const ModuleFactory ClassicSecurityManagerFacadeModule::Factory = |
| ::bluetooth::ModuleFactory([]() { return new ClassicSecurityManagerFacadeModule(); }); |
| |
| } // namespace hci |
| } // namespace bluetooth |