};
struct classic_impl : public security::ISecurityManagerListener {
- classic_impl(HciLayer* hci_layer, Controller* controller, os::Handler* handler,
- RoundRobinScheduler* round_robin_scheduler)
- : hci_layer_(hci_layer), controller_(controller), round_robin_scheduler_(round_robin_scheduler) {
+ classic_impl(
+ HciLayer* hci_layer,
+ Controller* controller,
+ os::Handler* handler,
+ RoundRobinScheduler* round_robin_scheduler,
+ bool crash_on_unknown_handle)
+ : hci_layer_(hci_layer),
+ controller_(controller),
+ round_robin_scheduler_(round_robin_scheduler),
+ crash_on_unknown_handle_(crash_on_unknown_handle) {
hci_layer_ = hci_layer;
controller_ = controller;
handler_ = handler;
security_manager_.reset();
}
+ ConnectionManagementCallbacks* get_callbacks(uint16_t handle) {
+ auto conn = acl_connections_.find(handle);
+ if (conn == acl_connections_.end()) {
+ return nullptr;
+ } else {
+ return conn->second.connection_management_callbacks_;
+ }
+ }
+
void on_classic_event(EventPacketView event_packet) {
EventCode event_code = event_packet.GetEventCode();
switch (event_code) {
case EventCode::LINK_SUPERVISION_TIMEOUT_CHANGED:
on_link_supervision_timeout_changed(event_packet);
break;
+ case EventCode::CENTRAL_LINK_KEY_COMPLETE:
+ on_central_link_key_complete(event_packet);
+ break;
default:
LOG_ALWAYS_FATAL("Unhandled event code %s", EventCodeText(event_code).c_str());
}
}
void on_classic_disconnect(uint16_t handle, ErrorCode reason) {
- if (acl_connections_.count(handle) == 1) {
- auto& connection = acl_connections_.find(handle)->second;
+ auto callbacks = get_callbacks(handle);
+ if (callbacks != nullptr) {
round_robin_scheduler_->Unregister(handle);
- connection.connection_management_callbacks_->OnDisconnection(reason);
+ callbacks->OnDisconnection(reason);
acl_connections_.erase(handle);
}
}
client_handler_ = handler;
}
- void handle_disconnect(uint16_t handle, DisconnectReason reason) {
- acl_connection_interface_->EnqueueCommand(hci::DisconnectBuilder::Create(handle, reason),
- handler_->BindOnce(&check_command_status<DisconnectStatusView>));
- }
-
void on_incoming_connection(EventPacketView packet) {
ConnectionRequestView request = ConnectionRequestView::Create(packet);
ASSERT(request.IsValid());
return;
}
uint16_t handle = connection_complete.GetConnectionHandle();
- ASSERT(acl_connections_.count(handle) == 0);
auto queue = std::make_shared<AclConnection::Queue>(10);
- acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle),
- std::forward_as_tuple(AddressWithType{address, AddressType::PUBLIC_DEVICE_ADDRESS},
- queue->GetDownEnd(), handler_));
+ auto conn_pair = acl_connections_.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(handle),
+ std::forward_as_tuple(
+ AddressWithType{address, AddressType::PUBLIC_DEVICE_ADDRESS}, queue->GetDownEnd(), handler_));
+ ASSERT(conn_pair.second); // Make sure it's not a duplicate
round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, queue);
std::unique_ptr<ClassicAclConnection> connection(
new ClassicAclConnection(std::move(queue), acl_connection_interface_, handle, address));
connection->locally_initiated_ = locally_initiated;
- auto& connection_proxy = check_and_get_connection(handle);
+ auto& connection_proxy = conn_pair.first->second;
connection_proxy.connection_management_callbacks_ = connection->GetEventCallbacks();
connection_proxy.connection_management_callbacks_->OnRoleChange(current_role);
client_handler_->Post(common::BindOnce(&ConnectionCallbacks::OnConnectSuccess,
LOG_ERROR("Received on_connection_packet_type_changed with error code %s", error_code.c_str());
return;
}
+ uint16_t handle = packet_type_changed.GetConnectionHandle();
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
// We don't handle this event; we didn't do this in legacy stack either.
}
return;
}
uint16_t handle = complete_view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
KeyFlag key_flag = complete_view.GetKeyFlag();
- acl_connection.connection_management_callbacks_->OnCentralLinkKeyComplete(key_flag);
+ callbacks->OnCentralLinkKeyComplete(key_flag);
}
void on_authentication_complete(EventPacketView packet) {
return;
}
uint16_t handle = authentication_complete.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
- acl_connection.connection_management_callbacks_->OnAuthenticationComplete();
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
+ callbacks->OnAuthenticationComplete();
}
void cancel_connect(Address address) {
return;
}
uint16_t handle = complete_view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
- acl_connection.connection_management_callbacks_->OnChangeConnectionLinkKeyComplete();
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
+ callbacks->OnChangeConnectionLinkKeyComplete();
}
void on_read_clock_offset_complete(EventPacketView packet) {
return;
}
uint16_t handle = complete_view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
uint16_t clock_offset = complete_view.GetClockOffset();
- acl_connection.connection_management_callbacks_->OnReadClockOffsetComplete(clock_offset);
+ callbacks->OnReadClockOffsetComplete(clock_offset);
}
void on_mode_change(EventPacketView packet) {
return;
}
uint16_t handle = mode_change_view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
Mode current_mode = mode_change_view.GetCurrentMode();
uint16_t interval = mode_change_view.GetInterval();
- acl_connection.connection_management_callbacks_->OnModeChange(current_mode, interval);
+ callbacks->OnModeChange(current_mode, interval);
}
void on_qos_setup_complete(EventPacketView packet) {
return;
}
uint16_t handle = complete_view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
ServiceType service_type = complete_view.GetServiceType();
uint32_t token_rate = complete_view.GetTokenRate();
uint32_t peak_bandwidth = complete_view.GetPeakBandwidth();
uint32_t latency = complete_view.GetLatency();
uint32_t delay_variation = complete_view.GetDelayVariation();
- acl_connection.connection_management_callbacks_->OnQosSetupComplete(service_type, token_rate, peak_bandwidth,
- latency, delay_variation);
+ callbacks->OnQosSetupComplete(service_type, token_rate, peak_bandwidth, latency, delay_variation);
}
void on_role_change(EventPacketView packet) {
return;
}
uint16_t handle = complete_view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
FlowDirection flow_direction = complete_view.GetFlowDirection();
ServiceType service_type = complete_view.GetServiceType();
uint32_t token_rate = complete_view.GetTokenRate();
uint32_t token_bucket_size = complete_view.GetTokenBucketSize();
uint32_t peak_bandwidth = complete_view.GetPeakBandwidth();
uint32_t access_latency = complete_view.GetAccessLatency();
- acl_connection.connection_management_callbacks_->OnFlowSpecificationComplete(
+ callbacks->OnFlowSpecificationComplete(
flow_direction, service_type, token_rate, token_bucket_size, peak_bandwidth, access_latency);
}
return;
}
uint16_t handle = flush_occurred_view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
- acl_connection.connection_management_callbacks_->OnFlushOccurred();
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
+ callbacks->OnFlushOccurred();
}
void on_read_remote_version_information(
uint16_t handle, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version) {
- auto acl_connection = acl_connections_.find(handle);
- if (acl_connection != acl_connections_.end()) {
- acl_connection->second.connection_management_callbacks_->OnReadRemoteVersionInformationComplete(
- version, manufacturer_name, sub_version);
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
}
+ callbacks->OnReadRemoteVersionInformationComplete(version, manufacturer_name, sub_version);
}
void on_read_remote_supported_features_complete(EventPacketView packet) {
auto view = ReadRemoteSupportedFeaturesCompleteView::Create(packet);
ASSERT_LOG(view.IsValid(), "Read remote supported features packet invalid");
uint16_t handle = view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
- acl_connection.connection_management_callbacks_->OnReadRemoteExtendedFeaturesComplete(0, 1, view.GetLmpFeatures());
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
+ callbacks->OnReadRemoteExtendedFeaturesComplete(0, 1, view.GetLmpFeatures());
}
void on_read_remote_extended_features_complete(EventPacketView packet) {
auto view = ReadRemoteExtendedFeaturesCompleteView::Create(packet);
ASSERT_LOG(view.IsValid(), "Read remote extended features packet invalid");
uint16_t handle = view.GetConnectionHandle();
- auto& acl_connection = acl_connections_.find(handle)->second;
- acl_connection.connection_management_callbacks_->OnReadRemoteExtendedFeaturesComplete(
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
+ callbacks->OnReadRemoteExtendedFeaturesComplete(
view.GetPageNumber(), view.GetMaximumPageNumber(), view.GetExtendedLmpFeatures());
}
std::move(builder), handler_->BindOnce(&check_command_status<RejectConnectionRequestStatusView>));
}
- acl_connection& check_and_get_connection(uint16_t handle) {
- auto connection = acl_connections_.find(handle);
- ASSERT(connection != acl_connections_.end());
- return connection->second;
- }
-
void OnDeviceBonded(bluetooth::hci::AddressWithType device) override {}
void OnDeviceUnbonded(bluetooth::hci::AddressWithType device) override {}
void OnDeviceBondFailed(bluetooth::hci::AddressWithType device, security::PairingFailure status) override {}
return;
}
uint16_t handle = encryption_change_view.GetConnectionHandle();
- auto acl_connection = acl_connections_.find(handle);
- if (acl_connection == acl_connections_.end()) {
- LOG_INFO("Invalid handle (already closed?) %d", handle);
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Unknown connection handle 0x%04hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
return;
}
EncryptionEnabled enabled = encryption_change_view.GetEncryptionEnabled();
- acl_connection->second.connection_management_callbacks_->OnEncryptionChange(enabled);
+ callbacks->OnEncryptionChange(enabled);
}
void set_security_module(security::SecurityModule* security_module) {
std::queue<std::pair<Address, std::unique_ptr<CreateConnectionBuilder>>> pending_outgoing_connections_;
std::unique_ptr<security::SecurityManager> security_manager_;
+ bool crash_on_unknown_handle_ = false;
};
} // namespace acl_manager
};
struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
- le_impl(HciLayer* hci_layer, Controller* controller, os::Handler* handler, RoundRobinScheduler* round_robin_scheduler)
- : hci_layer_(hci_layer), controller_(controller), round_robin_scheduler_(round_robin_scheduler) {
+ le_impl(
+ HciLayer* hci_layer,
+ Controller* controller,
+ os::Handler* handler,
+ RoundRobinScheduler* round_robin_scheduler,
+ bool crash_on_unknown_handle)
+ : hci_layer_(hci_layer),
+ controller_(controller),
+ round_robin_scheduler_(round_robin_scheduler),
+ crash_on_unknown_handle_(crash_on_unknown_handle) {
hci_layer_ = hci_layer;
controller_ = controller;
handler_ = handler;
}
}
+ LeConnectionManagementCallbacks* get_callbacks(uint16_t handle) {
+ auto connection = le_acl_connections_.find(handle);
+ if (connection == le_acl_connections_.end()) {
+ return nullptr;
+ }
+ return connection->second.le_connection_management_callbacks_;
+ }
+
void on_le_disconnect(uint16_t handle, ErrorCode reason) {
- if (le_acl_connections_.count(handle) == 1) {
- auto& connection = le_acl_connections_.find(handle)->second;
- round_robin_scheduler_->Unregister(handle);
- connection.le_connection_management_callbacks_->OnDisconnection(reason);
- le_acl_connections_.erase(handle);
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ return;
}
+ round_robin_scheduler_->Unregister(handle);
+ callbacks->OnDisconnection(reason);
+ le_acl_connections_.erase(handle);
}
void on_common_le_connection_complete(AddressWithType address_with_type) {
auto role = connection_complete.GetRole();
uint16_t handle = connection_complete.GetConnectionHandle();
- ASSERT(le_acl_connections_.count(handle) == 0);
auto queue = std::make_shared<AclConnection::Queue>(10);
- le_acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle),
- std::forward_as_tuple(remote_address, queue->GetDownEnd(), handler_));
- auto& connection_proxy = check_and_get_le_connection(handle);
+ auto emplace_pair = le_acl_connections_.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(handle),
+ std::forward_as_tuple(remote_address, queue->GetDownEnd(), handler_));
+ ASSERT(emplace_pair.second); // Make sure the connection is unique
+ auto& connection_proxy = emplace_pair.first->second;
round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, handle, queue);
std::unique_ptr<LeAclConnection> connection(new LeAclConnection(
std::move(queue), le_acl_connection_interface_, handle, local_address, remote_address, role));
return;
}
uint16_t handle = connection_complete.GetConnectionHandle();
- ASSERT(le_acl_connections_.count(handle) == 0);
auto queue = std::make_shared<AclConnection::Queue>(10);
- le_acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle),
- std::forward_as_tuple(remote_address, queue->GetDownEnd(), handler_));
- auto& connection_proxy = check_and_get_le_connection(handle);
+ auto emplace_pair = le_acl_connections_.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(handle),
+ std::forward_as_tuple(remote_address, queue->GetDownEnd(), handler_));
+ ASSERT(emplace_pair.second); // Make sure it's not a duplicate
+ auto& connection_proxy = emplace_pair.first->second;
round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, handle, queue);
std::unique_ptr<LeAclConnection> connection(new LeAclConnection(
std::move(queue), le_acl_connection_interface_, handle, local_address, remote_address, role));
return;
}
auto handle = complete_view.GetConnectionHandle();
- if (le_acl_connections_.find(handle) == le_acl_connections_.end()) {
- LOG_WARN("Can't find connection %hd", handle);
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Can't find connection 0x%hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
return;
}
- auto& connection = le_acl_connections_.find(handle)->second;
- connection.le_connection_management_callbacks_->OnConnectionUpdate(
+ callbacks->OnConnectionUpdate(
complete_view.GetConnInterval(), complete_view.GetConnLatency(), complete_view.GetSupervisionTimeout());
}
void on_le_read_remote_version_information(
uint16_t handle, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version) {
- auto connection = le_acl_connections_.find(handle);
- if (connection != le_acl_connections_.end()) {
- connection->second.le_connection_management_callbacks_->OnReadRemoteVersionInformationComplete(
- version, manufacturer_name, sub_version);
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Can't find connection 0x%hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
}
+ callbacks->OnReadRemoteVersionInformationComplete(version, manufacturer_name, sub_version);
}
void enqueue_command(std::unique_ptr<CommandPacketBuilder> command_packet) {
return;
}
auto handle = data_length_view.GetConnectionHandle();
- auto connection_iterator = le_acl_connections_.find(handle);
- if (connection_iterator == le_acl_connections_.end()) {
- LOG_WARN("Can't find connection %hd", handle);
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Can't find connection 0x%hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
return;
}
- connection_iterator->second.le_connection_management_callbacks_->OnDataLengthChange(
+ callbacks->OnDataLengthChange(
data_length_view.GetMaxTxOctets(),
data_length_view.GetMaxTxTime(),
data_length_view.GetMaxRxOctets(),
return;
}
+ auto handle = request_view.GetConnectionHandle();
+ auto callbacks = get_callbacks(handle);
+ if (callbacks == nullptr) {
+ LOG_WARN("Can't find connection 0x%hx", handle);
+ ASSERT(!crash_on_unknown_handle_);
+ return;
+ }
// TODO: this is blindly accepting any parameters, just so we don't hang connection
// have proper parameter negotiation
le_acl_connection_interface_->EnqueueCommand(
LeRemoteConnectionParameterRequestReplyBuilder::Create(
- request_view.GetConnectionHandle(),
+ handle,
request_view.GetIntervalMin(),
request_view.GetIntervalMax(),
request_view.GetLatency(),
le_client_handler_ = handler;
}
- le_acl_connection& check_and_get_le_connection(uint16_t handle) {
- auto connection = le_acl_connections_.find(handle);
- ASSERT(connection != le_acl_connections_.end());
- return connection->second;
- }
-
bool check_connection_parameters(
uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout) {
if (conn_interval_min < 0x0006 || conn_interval_min > 0x0C80 || conn_interval_max < 0x0006 ||
bool address_manager_registered = false;
bool ready_to_unregister = false;
bool pause_connection = false;
+ bool crash_on_unknown_handle_ = false;
};
} // namespace acl_manager