You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
4.4 KiB

/*
*
* 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 "security/channel/security_manager_channel.h"
#include "hci/address.h"
#include "security/smp_packets.h"
namespace bluetooth {
namespace security {
namespace channel {
/**
* Main Constructor
*/
SecurityManagerChannel::SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer)
: listener_(nullptr),
hci_security_interface_(
hci_layer->GetSecurityInterface(handler->BindOn(this, &SecurityManagerChannel::OnHciEventReceived))),
handler_(handler),
l2cap_security_interface_(nullptr) {}
SecurityManagerChannel::~SecurityManagerChannel() {
l2cap_security_interface_->Unregister();
l2cap_security_interface_ = nullptr;
}
void SecurityManagerChannel::Connect(hci::Address address) {
ASSERT_LOG(l2cap_security_interface_ != nullptr, "L2cap Security Interface is null!");
auto entry = link_map_.find(address);
if (entry != link_map_.end()) {
LOG_WARN("Already connected to '%s'", address.ToString().c_str());
entry->second->Hold();
entry->second->EnsureAuthenticated();
return;
}
l2cap_security_interface_->InitiateConnectionForSecurity(address);
outgoing_pairing_remote_devices_.insert(address);
}
void SecurityManagerChannel::Release(hci::Address address) {
auto entry = link_map_.find(address);
if (entry == link_map_.end()) {
LOG_WARN("Unknown address '%s'", address.ToString().c_str());
return;
}
entry->second->Release();
}
void SecurityManagerChannel::Disconnect(hci::Address address) {
outgoing_pairing_remote_devices_.erase(address);
auto entry = link_map_.find(address);
if (entry == link_map_.end()) {
LOG_WARN("Unknown address '%s'", address.ToString().c_str());
return;
}
entry->second->Disconnect();
}
void SecurityManagerChannel::OnCommandComplete(hci::CommandCompleteView packet) {
ASSERT_LOG(packet.IsValid(), "Bad command response");
}
void SecurityManagerChannel::SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command) {
hci_security_interface_->EnqueueCommand(std::move(command),
handler_->BindOnceOn(this, &SecurityManagerChannel::OnCommandComplete));
}
void SecurityManagerChannel::SendCommand(
std::unique_ptr<hci::SecurityCommandBuilder> command, SecurityCommandStatusCallback callback) {
hci_security_interface_->EnqueueCommand(std::move(command), std::forward<SecurityCommandStatusCallback>(callback));
}
void SecurityManagerChannel::OnHciEventReceived(hci::EventView packet) {
ASSERT_LOG(listener_ != nullptr, "No listener set!");
ASSERT(packet.IsValid());
listener_->OnHciEventReceived(packet);
}
void SecurityManagerChannel::OnLinkConnected(std::unique_ptr<l2cap::classic::LinkSecurityInterface> link) {
// Multiple links possible?
auto remote = link->GetRemoteAddress();
if (outgoing_pairing_remote_devices_.count(remote) == 1) {
link->Hold();
link->EnsureAuthenticated();
outgoing_pairing_remote_devices_.erase(remote);
}
link_map_.emplace(remote, std::move(link));
}
void SecurityManagerChannel::OnLinkDisconnected(hci::Address address) {
auto entry = link_map_.find(address);
if (entry == link_map_.end()) {
LOG_WARN("Unknown address '%s'", address.ToString().c_str());
return;
}
entry->second.reset();
link_map_.erase(entry);
ASSERT_LOG(listener_ != nullptr, "Set listener!");
listener_->OnConnectionClosed(address);
}
void SecurityManagerChannel::OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address remote) {
ASSERT_LOG(l2cap_security_interface_ != nullptr, "L2cap Security Interface is null!");
auto entry = link_map_.find(remote);
if (entry != link_map_.end()) {
entry->second->EnsureEncrypted();
return;
}
}
void SecurityManagerChannel::OnEncryptionChange(hci::Address remote, bool encrypted) {
}
} // namespace channel
} // namespace security
} // namespace bluetooth