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