| // Copyright 2021 The Fuchsia 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 "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/bredr_connection_request.h" |
| |
| namespace bt::gap { |
| |
| namespace { |
| |
| const char* const kInspectHasIncomingPropertyName = "has_incoming"; |
| const char* const kInspectCallbacksPropertyName = "callbacks"; |
| const char* const kInspectFirstCreateConnectionReqMadeName = |
| "first_create_connection_request_timestamp"; |
| const char* const kInspectPeerIdPropertyName = "peer_id"; |
| constexpr pw::chrono::SystemClock::duration kRetryWindowAfterFirstCreateConn = |
| std::chrono::seconds(30); |
| |
| } // namespace |
| |
| BrEdrConnectionRequest::BrEdrConnectionRequest( |
| pw::async::Dispatcher& pw_dispatcher, |
| const DeviceAddress& addr, |
| PeerId peer_id, |
| Peer::InitializingConnectionToken token) |
| : peer_id_(peer_id), |
| address_(addr), |
| callbacks_(/*convert=*/[](auto& c) { return c.size(); }), |
| peer_init_conn_token_(std::move(token)), |
| dispatcher_(pw_dispatcher) {} |
| |
| BrEdrConnectionRequest::BrEdrConnectionRequest( |
| pw::async::Dispatcher& pw_dispatcher, |
| const DeviceAddress& addr, |
| PeerId peer_id, |
| Peer::InitializingConnectionToken token, |
| OnComplete&& callback) |
| : BrEdrConnectionRequest(pw_dispatcher, addr, peer_id, std::move(token)) { |
| callbacks_.Mutable()->push_back(std::move(callback)); |
| } |
| |
| void BrEdrConnectionRequest::NotifyCallbacks(hci::Result<> status, |
| const RefFactory& generate_ref) { |
| // Clear token before notifying callbacks so that connection state change is |
| // reflected in callbacks. |
| peer_init_conn_token_.reset(); |
| |
| // If this request has been moved from, |callbacks_| may be empty. |
| for (const auto& callback : *callbacks_) { |
| callback(status, generate_ref()); |
| } |
| } |
| |
| void BrEdrConnectionRequest::AttachInspect(inspect::Node& parent, |
| std::string name) { |
| inspect_node_ = parent.CreateChild(name); |
| has_incoming_.AttachInspect(inspect_node_, kInspectHasIncomingPropertyName); |
| callbacks_.AttachInspect(inspect_node_, kInspectCallbacksPropertyName); |
| first_create_connection_req_made_.AttachInspect( |
| inspect_node_, kInspectFirstCreateConnectionReqMadeName); |
| peer_id_property_ = inspect_node_.CreateString(kInspectPeerIdPropertyName, |
| peer_id_.ToString()); |
| } |
| |
| void BrEdrConnectionRequest::RecordHciCreateConnectionAttempt() { |
| if (!first_create_connection_req_made_.value()) { |
| first_create_connection_req_made_.Set(dispatcher_.now()); |
| } |
| } |
| |
| bool BrEdrConnectionRequest::ShouldRetry(hci::Error failure_mode) { |
| pw::chrono::SystemClock::time_point now = dispatcher_.now(); |
| std::optional<pw::chrono::SystemClock::time_point> |
| first_create_conn_req_made = first_create_connection_req_made_.value(); |
| return failure_mode.is(pw::bluetooth::emboss::StatusCode::PAGE_TIMEOUT) && |
| first_create_conn_req_made.has_value() && |
| now - *first_create_conn_req_made < kRetryWindowAfterFirstCreateConn; |
| } |
| } // namespace bt::gap |