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