1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "l2cap/le/internal/signalling_manager.h"
18 
19 #include <chrono>
20 
21 #include "common/bind.h"
22 #include "l2cap/internal/data_pipeline_manager.h"
23 #include "l2cap/internal/dynamic_channel_impl.h"
24 #include "l2cap/internal/le_credit_based_channel_data_controller.h"
25 #include "l2cap/l2cap_packets.h"
26 #include "l2cap/le/internal/link.h"
27 #include "os/log.h"
28 #include "packet/raw_builder.h"
29 
30 namespace bluetooth {
31 namespace l2cap {
32 namespace le {
33 namespace internal {
34 
35 static constexpr auto kTimeout = std::chrono::seconds(3);
36 
LeSignallingManager(os::Handler * handler,Link * link,l2cap::internal::DataPipelineManager * data_pipeline_manager,DynamicChannelServiceManagerImpl * dynamic_service_manager,l2cap::internal::DynamicChannelAllocator * channel_allocator)37 LeSignallingManager::LeSignallingManager(os::Handler* handler, Link* link,
38                                          l2cap::internal::DataPipelineManager* data_pipeline_manager,
39                                          DynamicChannelServiceManagerImpl* dynamic_service_manager,
40                                          l2cap::internal::DynamicChannelAllocator* channel_allocator)
41     : handler_(handler), link_(link), data_pipeline_manager_(data_pipeline_manager),
42       dynamic_service_manager_(dynamic_service_manager), channel_allocator_(channel_allocator), alarm_(handler) {
43   ASSERT(handler_ != nullptr);
44   ASSERT(link_ != nullptr);
45   signalling_channel_ =
46       link_->AllocateFixedChannel(kLeSignallingCid, SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK);
47   signalling_channel_->GetQueueUpEnd()->RegisterDequeue(
48       handler_, common::Bind(&LeSignallingManager::on_incoming_packet, common::Unretained(this)));
49   enqueue_buffer_ =
50       std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>(signalling_channel_->GetQueueUpEnd());
51 }
52 
~LeSignallingManager()53 LeSignallingManager::~LeSignallingManager() {
54   enqueue_buffer_.reset();
55   signalling_channel_->GetQueueUpEnd()->UnregisterDequeue();
56   signalling_channel_ = nullptr;
57 }
58 
SendConnectionRequest(Psm psm,Cid local_cid,Mtu mtu)59 void LeSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid, Mtu mtu) {
60   dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce(
61       link_->GetDevice(),
62       dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(),
63       handler_->BindOnceOn(this, &LeSignallingManager::on_security_result_for_outgoing, psm, local_cid, mtu));
64 }
65 
on_security_result_for_outgoing(Psm psm,Cid local_cid,Mtu mtu,bool result)66 void LeSignallingManager::on_security_result_for_outgoing(Psm psm, Cid local_cid, Mtu mtu, bool result) {
67   if (!result) {
68     LOG_WARN("Security requirement can't be satisfied. Dropping connection request");
69     return;
70   }
71 
72   PendingCommand pending_command = PendingCommand::CreditBasedConnectionRequest(
73       next_signal_id_, psm, local_cid, mtu, link_->GetMps(), link_->GetInitialCredit());
74   next_signal_id_++;
75   pending_commands_.push(pending_command);
76   if (pending_commands_.size() == 1) {
77     handle_send_next_command();
78   }
79 }
80 
SendDisconnectRequest(Cid scid,Cid dcid)81 void LeSignallingManager::SendDisconnectRequest(Cid scid, Cid dcid) {
82   PendingCommand pending_command = PendingCommand::DisconnectionRequest(next_signal_id_, scid, dcid);
83   next_signal_id_++;
84   pending_commands_.push(pending_command);
85   if (pending_commands_.size() == 1) {
86     handle_send_next_command();
87   }
88 }
89 
SendConnectionParameterUpdateRequest(uint16_t interval_min,uint16_t interval_max,uint16_t slave_latency,uint16_t timeout_multiplier)90 void LeSignallingManager::SendConnectionParameterUpdateRequest(uint16_t interval_min, uint16_t interval_max,
91                                                                uint16_t slave_latency, uint16_t timeout_multiplier) {
92   PendingCommand pending_command = PendingCommand::ConnectionParameterUpdate(
93       next_signal_id_, interval_min, interval_max, slave_latency, timeout_multiplier);
94   next_signal_id_++;
95   pending_commands_.push(pending_command);
96   if (pending_commands_.size() == 1) {
97     handle_send_next_command();
98   }
99 }
100 
SendConnectionParameterUpdateResponse(SignalId signal_id,ConnectionParameterUpdateResponseResult result)101 void LeSignallingManager::SendConnectionParameterUpdateResponse(SignalId signal_id,
102                                                                 ConnectionParameterUpdateResponseResult result) {
103   auto builder = ConnectionParameterUpdateResponseBuilder::Create(signal_id.Value(), result);
104   enqueue_buffer_->Enqueue(std::move(builder), handler_);
105 }
106 
SendCredit(Cid local_cid,uint16_t credits)107 void LeSignallingManager::SendCredit(Cid local_cid, uint16_t credits) {
108   auto builder = LeFlowControlCreditBuilder::Create(next_signal_id_.Value(), local_cid, credits);
109   next_signal_id_++;
110   enqueue_buffer_->Enqueue(std::move(builder), handler_);
111 }
112 
CancelAlarm()113 void LeSignallingManager::CancelAlarm() {
114   alarm_.Cancel();
115 }
116 
OnCommandReject(LeCommandRejectView command_reject_view)117 void LeSignallingManager::OnCommandReject(LeCommandRejectView command_reject_view) {
118   auto signal_id = command_reject_view.GetIdentifier();
119   if (signal_id != command_just_sent_.signal_id_) {
120     LOG_WARN("Unexpected response: no pending request");
121     return;
122   }
123   alarm_.Cancel();
124   if (command_just_sent_.command_code_ == LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST) {
125     link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_,
126                                            LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE);
127   }
128   handle_send_next_command();
129 
130   LOG_WARN("Command rejected");
131 }
132 
OnConnectionParameterUpdateRequest(SignalId signal_id,uint16_t interval_min,uint16_t interval_max,uint16_t slave_latency,uint16_t timeout_multiplier)133 void LeSignallingManager::OnConnectionParameterUpdateRequest(SignalId signal_id, uint16_t interval_min,
134                                                              uint16_t interval_max, uint16_t slave_latency,
135                                                              uint16_t timeout_multiplier) {
136   if (link_->GetRole() == hci::Role::SLAVE) {
137     LOG_WARN("Received request from LL master");
138     auto builder = LeCommandRejectNotUnderstoodBuilder::Create(signal_id.Value());
139     enqueue_buffer_->Enqueue(std::move(builder), handler_);
140     return;
141   }
142 
143   if (!link_->CheckConnectionParameters(interval_min, interval_max, slave_latency, timeout_multiplier)) {
144     LOG_WARN("Received invalid connection parameter update request from LL master");
145     auto builder = ConnectionParameterUpdateResponseBuilder::Create(signal_id.Value(),
146                                                                     ConnectionParameterUpdateResponseResult::REJECTED);
147     enqueue_buffer_->Enqueue(std::move(builder), handler_);
148     return;
149   }
150   link_->UpdateConnectionParameterFromRemote(signal_id, interval_min, interval_max, slave_latency, timeout_multiplier);
151 }
152 
OnConnectionParameterUpdateResponse(SignalId signal_id,ConnectionParameterUpdateResponseResult result)153 void LeSignallingManager::OnConnectionParameterUpdateResponse(SignalId signal_id,
154                                                               ConnectionParameterUpdateResponseResult result) {
155   if (signal_id != command_just_sent_.signal_id_) {
156     LOG_WARN("Unexpected response: no pending request");
157     return;
158   }
159   if (command_just_sent_.command_code_ != LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST) {
160     LOG_WARN("Unexpected response: no pending request");
161     return;
162   }
163   alarm_.Cancel();
164   command_just_sent_.signal_id_ = kInitialSignalId;
165   if (result != ConnectionParameterUpdateResponseResult::ACCEPTED) {
166     LOG_ERROR("Connection parameter update is not accepted");
167   }
168 }
169 
OnConnectionRequest(SignalId signal_id,Psm psm,Cid remote_cid,Mtu mtu,uint16_t mps,uint16_t initial_credits)170 void LeSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid, Mtu mtu, uint16_t mps,
171                                               uint16_t initial_credits) {
172   if (!IsPsmValid(psm)) {
173     LOG_WARN("Invalid psm received from remote psm:%d remote_cid:%d", psm, remote_cid);
174     send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
175                              LeCreditBasedConnectionResponseResult::LE_PSM_NOT_SUPPORTED);
176     return;
177   }
178 
179   if (remote_cid == kInvalidCid) {
180     LOG_WARN("Invalid remote cid received from remote psm:%d remote_cid:%d", psm, remote_cid);
181     send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
182                              LeCreditBasedConnectionResponseResult::INVALID_SOURCE_CID);
183     return;
184   }
185 
186   if (channel_allocator_->IsPsmUsed(psm)) {
187     LOG_WARN("Psm already exists");
188     send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
189                              LeCreditBasedConnectionResponseResult::LE_PSM_NOT_SUPPORTED);
190     return;
191   }
192 
193   if (!dynamic_service_manager_->IsServiceRegistered(psm)) {
194     LOG_INFO("Service for this psm (%d) is not registered", psm);
195     send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
196                              LeCreditBasedConnectionResponseResult::LE_PSM_NOT_SUPPORTED);
197     return;
198   }
199 
200   PendingConnection pending{
201       .remote_cid = remote_cid,
202       .incoming_signal_id = signal_id,
203       .initial_credits = initial_credits,
204       .max_pdu_size = mps,
205       .mtu = mtu,
206   };
207   dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce(
208       link_->GetDevice(),
209       dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(),
210       handler_->BindOnceOn(this, &LeSignallingManager::on_security_result_for_incoming, psm, pending));
211 }
212 
on_security_result_for_incoming(Psm psm,PendingConnection request,bool result)213 void LeSignallingManager::on_security_result_for_incoming(Psm psm, PendingConnection request, bool result) {
214   auto signal_id = request.incoming_signal_id;
215   auto* service = dynamic_service_manager_->GetService(psm);
216   if (!result) {
217     auto security_policy = service->GetSecurityPolicy();
218     switch (security_policy) {
219       case SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK:
220         LOG_ERROR("If no security requirement, we should never fail");
221         break;
222       case SecurityPolicy::ENCRYPTED_TRANSPORT:
223         send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
224                                  LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHENTICATION);
225         return;
226       case SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT:
227       case SecurityPolicy::BEST:
228         send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
229                                  LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHENTICATION);
230         return;
231       case SecurityPolicy::_NOT_FOR_YOU__AUTHENTICATED_PAIRING_WITH_128_BIT_KEY:
232         send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
233                                  LeCreditBasedConnectionResponseResult::INSUFFICIENT_ENCRYPTION_KEY_SIZE);
234         return;
235       case SecurityPolicy::_NOT_FOR_YOU__AUTHORIZATION:
236         send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
237                                  LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHORIZATION);
238         return;
239     }
240   }
241   auto config = service->GetConfigOption();
242   auto local_mtu = config.mtu;
243   auto local_mps = link_->GetMps();
244 
245   auto new_channel = link_->AllocateDynamicChannel(psm, request.remote_cid);
246   if (new_channel == nullptr) {
247     LOG_WARN("Can't allocate dynamic channel");
248     // TODO: We need to respond with the correct reason
249     send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
250                              LeCreditBasedConnectionResponseResult::SOURCE_CID_ALREADY_ALLOCATED);
251     return;
252   }
253 
254   send_connection_response(signal_id, new_channel->GetCid(), local_mtu, local_mps, link_->GetInitialCredit(),
255                            LeCreditBasedConnectionResponseResult::SUCCESS);
256   auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>(
257       data_pipeline_manager_->GetDataController(new_channel->GetCid()));
258   data_controller->SetMtu(std::min(request.mtu, local_mtu));
259   data_controller->SetMps(std::min(request.max_pdu_size, local_mps));
260   data_controller->OnCredit(request.initial_credits);
261   auto user_channel = std::make_unique<DynamicChannel>(new_channel, handler_, link_);
262   dynamic_service_manager_->GetService(psm)->NotifyChannelCreation(std::move(user_channel));
263 }
264 
OnConnectionResponse(SignalId signal_id,Cid remote_cid,Mtu mtu,uint16_t mps,uint16_t initial_credits,LeCreditBasedConnectionResponseResult result)265 void LeSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Mtu mtu, uint16_t mps,
266                                                uint16_t initial_credits, LeCreditBasedConnectionResponseResult result) {
267   if (signal_id != command_just_sent_.signal_id_) {
268     LOG_WARN("Unexpected response: no pending request");
269     return;
270   }
271   if (command_just_sent_.command_code_ != LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST) {
272     LOG_WARN("Unexpected response: no pending request");
273     return;
274   }
275   alarm_.Cancel();
276   command_just_sent_.signal_id_ = kInitialSignalId;
277   if (result != LeCreditBasedConnectionResponseResult::SUCCESS) {
278     LOG_WARN("Connection failed: %s", LeCreditBasedConnectionResponseResultText(result).data());
279     link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_, result);
280     handle_send_next_command();
281     return;
282   }
283   auto new_channel =
284       link_->AllocateReservedDynamicChannel(command_just_sent_.source_cid_, command_just_sent_.psm_, remote_cid);
285   if (new_channel == nullptr) {
286     LOG_WARN("Can't allocate dynamic channel");
287     link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_,
288                                            LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE);
289     handle_send_next_command();
290     return;
291   }
292   auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>(
293       data_pipeline_manager_->GetDataController(new_channel->GetCid()));
294   data_controller->SetMtu(std::min(mtu, command_just_sent_.mtu_));
295   data_controller->SetMps(std::min(mps, command_just_sent_.mps_));
296   data_controller->OnCredit(initial_credits);
297   std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(new_channel, handler_, link_);
298   dynamic_service_manager_->GetService(command_just_sent_.psm_)->NotifyChannelCreation(std::move(user_channel));
299 }
300 
OnDisconnectionRequest(SignalId signal_id,Cid cid,Cid remote_cid)301 void LeSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) {
302   auto channel = channel_allocator_->FindChannelByCid(cid);
303   if (channel == nullptr) {
304     LOG_WARN("Disconnect request for an unknown channel");
305     return;
306   }
307   if (channel->GetRemoteCid() != remote_cid) {
308     LOG_WARN("Disconnect request for an unmatching channel");
309     return;
310   }
311   auto builder = LeDisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid);
312   enqueue_buffer_->Enqueue(std::move(builder), handler_);
313   channel->OnClosed(hci::ErrorCode::SUCCESS);
314   link_->FreeDynamicChannel(cid);
315 }
316 
OnDisconnectionResponse(SignalId signal_id,Cid remote_cid,Cid cid)317 void LeSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) {
318   if (signal_id != command_just_sent_.signal_id_ ||
319       command_just_sent_.command_code_ != LeCommandCode::DISCONNECTION_REQUEST) {
320     LOG_WARN("Unexpected response: no pending request");
321     return;
322   }
323   if (command_just_sent_.source_cid_ != cid || command_just_sent_.destination_cid_ != remote_cid) {
324     LOG_WARN("Unexpected response: cid doesn't match. Expected scid %d dcid %d, got scid %d dcid %d",
325              command_just_sent_.source_cid_, command_just_sent_.destination_cid_, cid, remote_cid);
326     handle_send_next_command();
327     return;
328   }
329   alarm_.Cancel();
330   command_just_sent_.signal_id_ = kInitialSignalId;
331   auto channel = channel_allocator_->FindChannelByCid(cid);
332   if (channel == nullptr) {
333     LOG_WARN("Disconnect response for an unknown channel");
334     handle_send_next_command();
335     return;
336   }
337 
338   channel->OnClosed(hci::ErrorCode::SUCCESS);
339   link_->FreeDynamicChannel(cid);
340   handle_send_next_command();
341 }
342 
OnCredit(Cid remote_cid,uint16_t credits)343 void LeSignallingManager::OnCredit(Cid remote_cid, uint16_t credits) {
344   auto channel = channel_allocator_->FindChannelByRemoteCid(remote_cid);
345   if (channel == nullptr) {
346     LOG_WARN("Received credit for invalid cid %d", channel->GetCid());
347     return;
348   }
349   auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>(
350       data_pipeline_manager_->GetDataController(channel->GetCid()));
351   data_controller->OnCredit(credits);
352 }
353 
on_incoming_packet()354 void LeSignallingManager::on_incoming_packet() {
355   auto packet = signalling_channel_->GetQueueUpEnd()->TryDequeue();
356   LeControlView control_packet_view = LeControlView::Create(*packet);
357   if (!control_packet_view.IsValid()) {
358     LOG_WARN("Invalid signalling packet received");
359     return;
360   }
361   auto code = control_packet_view.GetCode();
362   switch (code) {
363     case LeCommandCode::COMMAND_REJECT: {
364       LeCommandRejectView command_reject_view = LeCommandRejectView::Create(control_packet_view);
365       if (!command_reject_view.IsValid()) {
366         return;
367       }
368       OnCommandReject(command_reject_view);
369       return;
370     }
371 
372     case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: {
373       ConnectionParameterUpdateRequestView parameter_update_req_view =
374           ConnectionParameterUpdateRequestView::Create(control_packet_view);
375       if (!parameter_update_req_view.IsValid()) {
376         return;
377       }
378       OnConnectionParameterUpdateRequest(
379           parameter_update_req_view.GetIdentifier(), parameter_update_req_view.GetIntervalMin(),
380           parameter_update_req_view.GetIntervalMax(), parameter_update_req_view.GetSlaveLatency(),
381           parameter_update_req_view.GetTimeoutMultiplier());
382       return;
383     }
384     case LeCommandCode::CONNECTION_PARAMETER_UPDATE_RESPONSE: {
385       ConnectionParameterUpdateResponseView parameter_update_rsp_view =
386           ConnectionParameterUpdateResponseView::Create(control_packet_view);
387       if (!parameter_update_rsp_view.IsValid()) {
388         return;
389       }
390       OnConnectionParameterUpdateResponse(parameter_update_rsp_view.GetIdentifier(),
391                                           parameter_update_rsp_view.GetResult());
392       return;
393     }
394     case LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST: {
395       LeCreditBasedConnectionRequestView connection_request_view =
396           LeCreditBasedConnectionRequestView::Create(control_packet_view);
397       if (!connection_request_view.IsValid()) {
398         return;
399       }
400       OnConnectionRequest(connection_request_view.GetIdentifier(), connection_request_view.GetLePsm(),
401                           connection_request_view.GetSourceCid(), connection_request_view.GetMtu(),
402                           connection_request_view.GetMps(), connection_request_view.GetInitialCredits());
403       return;
404     }
405     case LeCommandCode::LE_CREDIT_BASED_CONNECTION_RESPONSE: {
406       LeCreditBasedConnectionResponseView connection_response_view =
407           LeCreditBasedConnectionResponseView::Create(control_packet_view);
408       if (!connection_response_view.IsValid()) {
409         return;
410       }
411       OnConnectionResponse(connection_response_view.GetIdentifier(), connection_response_view.GetDestinationCid(),
412                            connection_response_view.GetMtu(), connection_response_view.GetMps(),
413                            connection_response_view.GetInitialCredits(), connection_response_view.GetResult());
414       return;
415     }
416     case LeCommandCode::LE_FLOW_CONTROL_CREDIT: {
417       LeFlowControlCreditView credit_view = LeFlowControlCreditView::Create(control_packet_view);
418       if (!credit_view.IsValid()) {
419         return;
420       }
421       OnCredit(credit_view.GetCid(), credit_view.GetCredits());
422       return;
423     }
424     case LeCommandCode::DISCONNECTION_REQUEST: {
425       LeDisconnectionRequestView disconnection_request_view = LeDisconnectionRequestView::Create(control_packet_view);
426       if (!disconnection_request_view.IsValid()) {
427         return;
428       }
429       OnDisconnectionRequest(disconnection_request_view.GetIdentifier(), disconnection_request_view.GetDestinationCid(),
430                              disconnection_request_view.GetSourceCid());
431       return;
432     }
433     case LeCommandCode::DISCONNECTION_RESPONSE: {
434       LeDisconnectionResponseView disconnection_response_view =
435           LeDisconnectionResponseView::Create(control_packet_view);
436       if (!disconnection_response_view.IsValid()) {
437         return;
438       }
439       OnDisconnectionResponse(disconnection_response_view.GetIdentifier(),
440                               disconnection_response_view.GetDestinationCid(),
441                               disconnection_response_view.GetSourceCid());
442       return;
443     }
444     default:
445       LOG_WARN("Unhandled event 0x%x", static_cast<int>(code));
446       auto builder = LeCommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier());
447       enqueue_buffer_->Enqueue(std::move(builder), handler_);
448       return;
449   }
450 }
451 
send_connection_response(SignalId signal_id,Cid local_cid,Mtu mtu,uint16_t mps,uint16_t initial_credit,LeCreditBasedConnectionResponseResult result)452 void LeSignallingManager::send_connection_response(SignalId signal_id, Cid local_cid, Mtu mtu, uint16_t mps,
453                                                    uint16_t initial_credit,
454                                                    LeCreditBasedConnectionResponseResult result) {
455   auto builder =
456       LeCreditBasedConnectionResponseBuilder::Create(signal_id.Value(), local_cid, mtu, mps, initial_credit, result);
457   enqueue_buffer_->Enqueue(std::move(builder), handler_);
458 }
459 
on_command_timeout()460 void LeSignallingManager::on_command_timeout() {
461   LOG_WARN("Response time out");
462   if (command_just_sent_.signal_id_ == kInvalidSignalId) {
463     LOG_ERROR("No pending command");
464     return;
465   }
466   switch (command_just_sent_.command_code_) {
467     case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: {
468       link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_,
469                                              LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE);
470       break;
471     }
472     default:
473       break;
474   }
475   handle_send_next_command();
476 }
477 
handle_send_next_command()478 void LeSignallingManager::handle_send_next_command() {
479   command_just_sent_.signal_id_ = kInvalidSignalId;
480   if (pending_commands_.empty()) {
481     return;
482   }
483 
484   command_just_sent_ = pending_commands_.front();
485   pending_commands_.pop();
486   switch (command_just_sent_.command_code_) {
487     case LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST: {
488       auto builder = LeCreditBasedConnectionRequestBuilder::Create(
489           command_just_sent_.signal_id_.Value(), command_just_sent_.psm_, command_just_sent_.source_cid_,
490           command_just_sent_.mtu_, command_just_sent_.mps_, command_just_sent_.credits_);
491       enqueue_buffer_->Enqueue(std::move(builder), handler_);
492       alarm_.Schedule(common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout);
493       break;
494     }
495     case LeCommandCode::DISCONNECTION_REQUEST: {
496       auto builder = LeDisconnectionRequestBuilder::Create(
497           command_just_sent_.signal_id_.Value(), command_just_sent_.destination_cid_, command_just_sent_.source_cid_);
498       enqueue_buffer_->Enqueue(std::move(builder), handler_);
499       alarm_.Schedule(common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout);
500       break;
501     }
502     case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: {
503       auto builder = ConnectionParameterUpdateRequestBuilder::Create(
504           command_just_sent_.signal_id_.Value(), command_just_sent_.interval_min_, command_just_sent_.interval_max_,
505           command_just_sent_.slave_latency_, command_just_sent_.timeout_multiplier_);
506       enqueue_buffer_->Enqueue(std::move(builder), handler_);
507       alarm_.Schedule(common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout);
508       break;
509     }
510     default: {
511       LOG_WARN("Unsupported command code 0x%x", static_cast<int>(command_just_sent_.command_code_));
512     }
513   }
514 }
515 }  // namespace internal
516 }  // namespace le
517 }  // namespace l2cap
518 }  // namespace bluetooth
519