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/classic/internal/signalling_manager.h"
18
19 #include <chrono>
20
21 #include "common/bind.h"
22 #include "l2cap/classic/internal/channel_configuration_state.h"
23 #include "l2cap/classic/internal/link.h"
24 #include "l2cap/internal/data_pipeline_manager.h"
25 #include "l2cap/l2cap_packets.h"
26 #include "os/log.h"
27 #include "packet/raw_builder.h"
28
29 namespace bluetooth {
30 namespace l2cap {
31 namespace classic {
32 namespace internal {
33 static constexpr auto kTimeout = std::chrono::seconds(3);
34
GetCommandsFromPacketView(PacketView<kLittleEndian> packet)35 static std::vector<ControlView> GetCommandsFromPacketView(PacketView<kLittleEndian> packet) {
36 size_t curr = 0;
37 size_t end = packet.size();
38 std::vector<ControlView> result;
39 while (curr < end) {
40 auto sub_view = packet.GetLittleEndianSubview(curr, end);
41 auto control = ControlView::Create(sub_view);
42 if (!control.IsValid()) {
43 return {};
44 }
45 result.push_back(control);
46 curr += 1 + 1 + 2 + control.GetPayload().size();
47 }
48 return result;
49 }
50
ClassicSignallingManager(os::Handler * handler,Link * link,l2cap::internal::DataPipelineManager * data_pipeline_manager,DynamicChannelServiceManagerImpl * dynamic_service_manager,l2cap::internal::DynamicChannelAllocator * channel_allocator,FixedChannelServiceManagerImpl * fixed_service_manager)51 ClassicSignallingManager::ClassicSignallingManager(os::Handler* handler, Link* link,
52 l2cap::internal::DataPipelineManager* data_pipeline_manager,
53 DynamicChannelServiceManagerImpl* dynamic_service_manager,
54 l2cap::internal::DynamicChannelAllocator* channel_allocator,
55 FixedChannelServiceManagerImpl* fixed_service_manager)
56 : handler_(handler), link_(link), data_pipeline_manager_(data_pipeline_manager),
57 dynamic_service_manager_(dynamic_service_manager), channel_allocator_(channel_allocator),
58 fixed_service_manager_(fixed_service_manager), alarm_(handler) {
59 ASSERT(handler_ != nullptr);
60 ASSERT(link_ != nullptr);
61 signalling_channel_ = link_->AllocateFixedChannel(kClassicSignallingCid);
62 signalling_channel_->GetQueueUpEnd()->RegisterDequeue(
63 handler_, common::Bind(&ClassicSignallingManager::on_incoming_packet, common::Unretained(this)));
64 enqueue_buffer_ =
65 std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>(signalling_channel_->GetQueueUpEnd());
66 }
67
~ClassicSignallingManager()68 ClassicSignallingManager::~ClassicSignallingManager() {
69 alarm_.Cancel();
70 signalling_channel_->GetQueueUpEnd()->UnregisterDequeue();
71 signalling_channel_ = nullptr;
72 enqueue_buffer_->Clear();
73 enqueue_buffer_.reset();
74 }
75
OnCommandReject(CommandRejectView command_reject_view)76 void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) {
77 if (command_just_sent_.signal_id_ != command_reject_view.GetIdentifier()) {
78 LOG_WARN("Unexpected command reject: no pending request");
79 return;
80 }
81 if (command_just_sent_.command_code_ == CommandCode::INFORMATION_REQUEST &&
82 command_just_sent_.info_type_ == InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED) {
83 link_->OnRemoteExtendedFeatureReceived(false, false);
84 }
85 alarm_.Cancel();
86 handle_send_next_command();
87
88 LOG_INFO("Command rejected");
89 }
90
SendConnectionRequest(Psm psm,Cid local_cid)91 void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) {
92 dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce(
93 link_->GetDevice(),
94 dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(),
95 handler_->BindOnceOn(
96 this,
97 &ClassicSignallingManager::on_security_result_for_outgoing,
98 SecurityEnforcementType::LINK_KEY,
99 psm,
100 local_cid));
101 }
102
on_security_result_for_outgoing(SecurityEnforcementType type,Psm psm,Cid local_cid,bool result)103 void ClassicSignallingManager::on_security_result_for_outgoing(
104 SecurityEnforcementType type, Psm psm, Cid local_cid, bool result) {
105 if (enqueue_buffer_.get() == nullptr) {
106 LOG_ERROR("Got security result callback after deletion");
107 return;
108 }
109 if (!result) {
110 LOG_WARN("Security requirement can't be satisfied. Dropping connection request");
111 DynamicChannelManager::ConnectionResult connection_result{
112 .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_SECURITY_BLOCK,
113 .hci_error = hci::ErrorCode::SUCCESS,
114 .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE,
115 };
116 link_->OnOutgoingConnectionRequestFail(local_cid, connection_result);
117 return;
118 }
119 if (type == SecurityEnforcementType::LINK_KEY && !link_->IsAuthenticated() &&
120 dynamic_service_manager_->GetService(psm)->GetSecurityPolicy() !=
121 SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK) {
122 link_->Encrypt();
123 // TODO(b/171253721): If we can receive ENCRYPTION_CHANGE event, we can send command after callback is received.
124 }
125
126 PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}};
127 next_signal_id_++;
128 pending_commands_.push(std::move(pending_command));
129 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
130 handle_send_next_command();
131 }
132 }
133
send_configuration_request(Cid remote_cid,std::vector<std::unique_ptr<ConfigurationOption>> config)134 void ClassicSignallingManager::send_configuration_request(Cid remote_cid,
135 std::vector<std::unique_ptr<ConfigurationOption>> config) {
136 PendingCommand pending_command = {next_signal_id_, CommandCode::CONFIGURATION_REQUEST, {}, {}, remote_cid, {},
137 std::move(config)};
138 next_signal_id_++;
139 pending_commands_.push(std::move(pending_command));
140 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
141 handle_send_next_command();
142 }
143 }
144
SendDisconnectionRequest(Cid local_cid,Cid remote_cid)145 void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) {
146 PendingCommand pending_command = {
147 next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}};
148 next_signal_id_++;
149 pending_commands_.push(std::move(pending_command));
150 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
151 handle_send_next_command();
152 }
153 }
154
SendInformationRequest(InformationRequestInfoType type)155 void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) {
156 PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}};
157 next_signal_id_++;
158 pending_commands_.push(std::move(pending_command));
159 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
160 handle_send_next_command();
161 }
162 }
163
SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload)164 void ClassicSignallingManager::SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload) {
165 LOG_WARN("Not supported");
166 }
167
CancelAlarm()168 void ClassicSignallingManager::CancelAlarm() {
169 alarm_.Cancel();
170 }
171
OnConnectionRequest(SignalId signal_id,Psm psm,Cid remote_cid)172 void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid) {
173 if (!IsPsmValid(psm)) {
174 LOG_WARN("Invalid psm received from remote psm:%d remote_cid:%d", psm, remote_cid);
175 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
176 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
177 return;
178 }
179
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, remote_cid, kInvalidCid, ConnectionResponseResult::INVALID_CID,
183 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
184 return;
185 }
186 /* TODO(zachoverflow): add back in with policy
187 if (channel_allocator_->IsPsmUsed(psm)) {
188 LOG_WARN("Psm already exists");
189 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
190 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
191 return;
192 }
193 */
194
195 if (!dynamic_service_manager_->IsServiceRegistered(psm)) {
196 LOG_INFO("Service for this psm (%d) is not registered", psm);
197 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
198 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
199 return;
200 }
201
202 dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce(
203 link_->GetDevice(),
204 dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(),
205 handler_->BindOnceOn(
206 this, &ClassicSignallingManager::on_security_result_for_incoming, psm, remote_cid, signal_id));
207 }
208
on_security_result_for_incoming(Psm psm,Cid remote_cid,SignalId signal_id,bool result)209 void ClassicSignallingManager::on_security_result_for_incoming(
210 Psm psm, Cid remote_cid, SignalId signal_id, bool result) {
211 if (enqueue_buffer_.get() == nullptr) {
212 LOG_ERROR("Got security result callback after deletion");
213 return;
214 }
215 if (!result) {
216 send_connection_response(
217 signal_id,
218 remote_cid,
219 0,
220 ConnectionResponseResult::SECURITY_BLOCK,
221 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
222 DynamicChannelManager::ConnectionResult connection_result{
223 .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_SECURITY_BLOCK,
224 .hci_error = hci::ErrorCode::SUCCESS,
225 .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE,
226 };
227 link_->OnOutgoingConnectionRequestFail(0, connection_result);
228 }
229
230 auto new_channel = link_->AllocateDynamicChannel(psm, remote_cid);
231 if (new_channel == nullptr) {
232 LOG_WARN("Can't allocate dynamic channel");
233 return;
234 }
235 send_connection_response(
236 signal_id,
237 remote_cid,
238 new_channel->GetCid(),
239 ConnectionResponseResult::SUCCESS,
240 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
241
242 link_->SendInitialConfigRequestOrQueue(new_channel->GetCid());
243 }
244
OnConnectionResponse(SignalId signal_id,Cid remote_cid,Cid cid,ConnectionResponseResult result,ConnectionResponseStatus status)245 void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid,
246 ConnectionResponseResult result, ConnectionResponseStatus status) {
247 if (command_just_sent_.signal_id_ != signal_id ||
248 command_just_sent_.command_code_ != CommandCode::CONNECTION_REQUEST) {
249 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
250 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
251 signal_id.Value());
252 return;
253 }
254 if (command_just_sent_.source_cid_ != cid) {
255 LOG_WARN("SCID doesn't match: expected %d, received %d", command_just_sent_.source_cid_, cid);
256 handle_send_next_command();
257 return;
258 }
259 if (result == ConnectionResponseResult::PENDING) {
260 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
261 kTimeout);
262 return;
263 }
264
265 command_just_sent_.signal_id_ = kInvalidSignalId;
266 alarm_.Cancel();
267 if (result != ConnectionResponseResult::SUCCESS) {
268 DynamicChannelManager::ConnectionResult connection_result{
269 .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR,
270 .hci_error = hci::ErrorCode::SUCCESS,
271 .l2cap_connection_response_result = result,
272 };
273 link_->OnOutgoingConnectionRequestFail(cid, connection_result);
274 handle_send_next_command();
275 return;
276 }
277 Psm pending_psm = command_just_sent_.psm_;
278 auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid);
279 if (new_channel == nullptr) {
280 LOG_WARN("Can't allocate dynamic channel");
281 DynamicChannelManager::ConnectionResult connection_result{
282 .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR,
283 .hci_error = hci::ErrorCode::SUCCESS,
284 .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE,
285 };
286 link_->OnOutgoingConnectionRequestFail(cid, connection_result);
287 handle_send_next_command();
288 return;
289 }
290
291 link_->SendInitialConfigRequestOrQueue(cid);
292 }
293
OnConfigurationRequest(SignalId signal_id,Cid cid,Continuation is_continuation,std::vector<std::unique_ptr<ConfigurationOption>> options)294 void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation,
295 std::vector<std::unique_ptr<ConfigurationOption>> options) {
296 auto channel = channel_allocator_->FindChannelByCid(cid);
297 if (channel == nullptr) {
298 LOG_WARN("Configuration request for an unknown channel");
299 return;
300 }
301
302 auto& configuration_state = channel_configuration_[cid];
303 std::vector<std::unique_ptr<ConfigurationOption>> rsp_options;
304 ConfigurationResponseResult result = ConfigurationResponseResult::SUCCESS;
305 auto remote_rfc_mode = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
306
307 auto initial_config_option = dynamic_service_manager_->GetService(channel->GetPsm())->GetConfigOption();
308
309 for (auto& option : options) {
310 switch (option->type_) {
311 case ConfigurationOptionType::MTU: {
312 auto* config = MtuConfigurationOption::Specialize(option.get());
313 if (config->mtu_ < initial_config_option.minimal_remote_mtu) {
314 LOG_WARN("Configuration request with unacceptable MTU");
315 config->mtu_ = initial_config_option.minimal_remote_mtu;
316 result = ConfigurationResponseResult::UNACCEPTABLE_PARAMETERS;
317 }
318 rsp_options.emplace_back(std::make_unique<MtuConfigurationOption>(*config));
319 break;
320 }
321 case ConfigurationOptionType::FLUSH_TIMEOUT: {
322 auto* config = FlushTimeoutConfigurationOption::Specialize(option.get());
323 rsp_options.emplace_back(std::make_unique<FlushTimeoutConfigurationOption>(*config));
324 break;
325 }
326 case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
327 auto* config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
328 remote_rfc_mode = config->mode_;
329 if (config->mode_ == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) {
330 if (config->retransmission_time_out_ == 0) {
331 config->retransmission_time_out_ = 2000;
332 }
333 if (config->monitor_time_out_ == 0) {
334 config->monitor_time_out_ = 12000;
335 }
336 }
337 configuration_state.remote_retransmission_and_flow_control_ = *config;
338 configuration_state.retransmission_and_flow_control_mode_ = config->mode_;
339 rsp_options.emplace_back(std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config));
340 break;
341 }
342 case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
343 // We determine whether to use FCS or not when we send config request
344 break;
345 }
346 default:
347 if (option->is_hint_ != ConfigurationOptionIsHint::OPTION_IS_A_HINT) {
348 LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
349 auto response =
350 ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
351 ConfigurationResponseResult::UNKNOWN_OPTIONS, {});
352 enqueue_buffer_->Enqueue(std::move(response), handler_);
353 return;
354 }
355 break;
356 }
357 }
358
359 if (remote_rfc_mode == RetransmissionAndFlowControlModeOption::L2CAP_BASIC &&
360 initial_config_option.channel_mode ==
361 DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION) {
362 LOG_WARN("ERTM mandatory not allow mode configuration, disconnect channel.");
363 SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
364 return;
365 }
366
367 if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ) {
368 std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
369 if (channel->local_initiated_) {
370 link_->NotifyChannelCreation(cid, std::move(user_channel));
371 } else {
372 dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
373 }
374 configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED;
375 data_pipeline_manager_->AttachChannel(cid, channel, l2cap::internal::DataPipelineManager::ChannelMode::BASIC);
376 data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state);
377 } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) {
378 configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_RSP;
379 }
380
381 auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
382 result, std::move(rsp_options));
383 enqueue_buffer_->Enqueue(std::move(response), handler_);
384 }
385
SendInitialConfigRequest(Cid local_cid)386 void ClassicSignallingManager::SendInitialConfigRequest(Cid local_cid) {
387 auto channel = channel_allocator_->FindChannelByCid(local_cid);
388 auto psm = channel->GetPsm();
389 auto& configuration_state = channel_configuration_[local_cid];
390 auto* service = dynamic_service_manager_->GetService(psm);
391 auto initial_config = service->GetConfigOption();
392
393 auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
394 mtu_configuration->mtu_ = initial_config.incoming_mtu;
395
396 auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
397 fcs_option->fcs_type_ = FcsType::NO_FCS;
398 configuration_state.fcs_type_ = FcsType::NO_FCS;
399 if (link_->GetRemoteSupportsFcs()) {
400 fcs_option->fcs_type_ = FcsType::DEFAULT;
401 configuration_state.fcs_type_ = FcsType::DEFAULT;
402 }
403
404 auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
405 switch (initial_config.channel_mode) {
406 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
407 retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
408 configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
409 break;
410 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
411 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION_OPTIONAL:
412 retransmission_flow_control_configuration->mode_ =
413 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
414 configuration_state.retransmission_and_flow_control_mode_ =
415 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
416 // TODO: Decide where to put initial values
417 retransmission_flow_control_configuration->tx_window_size_ = 10;
418 retransmission_flow_control_configuration->max_transmit_ = 20;
419 retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
420 retransmission_flow_control_configuration->monitor_time_out_ = 12000;
421 retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
422 break;
423 }
424 configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;
425
426 std::vector<std::unique_ptr<ConfigurationOption>> config;
427 config.emplace_back(std::move(mtu_configuration));
428 if (initial_config.channel_mode != DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) {
429 config.emplace_back(std::move(retransmission_flow_control_configuration));
430 config.emplace_back(std::move(fcs_option));
431 }
432 send_configuration_request(channel->GetRemoteCid(), std::move(config));
433 }
434
negotiate_configuration(Cid cid,Continuation is_continuation,std::vector<std::unique_ptr<ConfigurationOption>> options)435 void ClassicSignallingManager::negotiate_configuration(Cid cid, Continuation is_continuation,
436 std::vector<std::unique_ptr<ConfigurationOption>> options) {
437 auto channel = channel_allocator_->FindChannelByCid(cid);
438 auto& configuration_state = channel_configuration_[channel->GetCid()];
439 std::vector<std::unique_ptr<ConfigurationOption>> negotiation_config;
440 bool can_negotiate = false;
441 for (auto& option : options) {
442 switch (option->type_) {
443 case ConfigurationOptionType::MTU: {
444 // MTU is non-negotiable option. Use default mtu size
445 auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
446 mtu_configuration->mtu_ = kDefaultClassicMtu;
447 negotiation_config.emplace_back(std::move(mtu_configuration));
448 can_negotiate = true;
449 break;
450 }
451 case ConfigurationOptionType::FRAME_CHECK_SEQUENCE:
452 case ConfigurationOptionType::FLUSH_TIMEOUT: {
453 // TODO: Handle these two configuration options negotiation.
454 can_negotiate = true;
455 break;
456 }
457 case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
458 auto* config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
459 if (config->mode_ == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) {
460 configuration_state.retransmission_and_flow_control_mode_ = config->mode_;
461 configuration_state.local_retransmission_and_flow_control_ = *config;
462 negotiation_config.emplace_back(std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config));
463 } else if (config->mode_ == RetransmissionAndFlowControlModeOption::L2CAP_BASIC) {
464 auto initial_config_option = dynamic_service_manager_->GetService(channel->GetPsm())->GetConfigOption();
465 if (initial_config_option.channel_mode ==
466 DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION) {
467 // ERTM mandatory is not allow negotiating of retransmission and flow control mode, disconnect channel
468 SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
469 return;
470 } else if (initial_config_option.channel_mode ==
471 DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::
472 ENHANCED_RETRANSMISSION_OPTIONAL) {
473 can_negotiate = true;
474 negotiation_config.emplace_back(std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config));
475 }
476 } else {
477 // Not support other retransmission and flow control mode, disconnect channel.
478 SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
479 return;
480 }
481 break;
482 }
483 default:
484 LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
485 return;
486 }
487 }
488 if (can_negotiate) {
489 send_configuration_request(channel->GetRemoteCid(), std::move(negotiation_config));
490 } else {
491 LOG_INFO("No suggested parameter received");
492 }
493 }
494
OnConfigurationResponse(SignalId signal_id,Cid cid,Continuation is_continuation,ConfigurationResponseResult result,std::vector<std::unique_ptr<ConfigurationOption>> options)495 void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation,
496 ConfigurationResponseResult result,
497 std::vector<std::unique_ptr<ConfigurationOption>> options) {
498 if (command_just_sent_.signal_id_ != signal_id ||
499 command_just_sent_.command_code_ != CommandCode::CONFIGURATION_REQUEST) {
500 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
501 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
502 signal_id.Value());
503 return;
504 }
505
506 auto channel = channel_allocator_->FindChannelByCid(cid);
507 if (channel == nullptr) {
508 LOG_WARN("Configuration request for an unknown channel");
509 handle_send_next_command();
510 return;
511 }
512
513 switch (result) {
514 default:
515 case ConfigurationResponseResult::REJECTED:
516 case ConfigurationResponseResult::UNKNOWN_OPTIONS:
517 case ConfigurationResponseResult::FLOW_SPEC_REJECTED:
518 LOG_WARN("Configuration response not SUCCESS: %s", ConfigurationResponseResultText(result).c_str());
519 alarm_.Cancel();
520 handle_send_next_command();
521 return;
522
523 case ConfigurationResponseResult::PENDING:
524 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
525 kTimeout);
526 return;
527
528 case ConfigurationResponseResult::UNACCEPTABLE_PARAMETERS:
529 LOG_INFO("Configuration response with unacceptable parameters");
530 alarm_.Cancel();
531 negotiate_configuration(cid, is_continuation, std::move(options));
532 handle_send_next_command();
533 return;
534
535 case ConfigurationResponseResult::SUCCESS:
536 break;
537 }
538 auto& configuration_state = channel_configuration_[channel->GetCid()];
539
540 for (auto& option : options) {
541 switch (option->type_) {
542 case ConfigurationOptionType::MTU: {
543 // Since they accepted our MTU, no need to read the new value.
544 break;
545 }
546 case ConfigurationOptionType::FLUSH_TIMEOUT: {
547 break;
548 }
549 case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
550 auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
551 if (configuration_state.retransmission_and_flow_control_mode_ != config->mode_) {
552 SendDisconnectionRequest(cid, channel->GetRemoteCid());
553 alarm_.Cancel();
554 handle_send_next_command();
555 return;
556 }
557 configuration_state.local_retransmission_and_flow_control_ = *config;
558 break;
559 }
560 case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
561 configuration_state.fcs_type_ = FrameCheckSequenceOption::Specialize(option.get())->fcs_type_;
562 break;
563 }
564 default:
565 LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
566 alarm_.Cancel();
567 handle_send_next_command();
568 return;
569 }
570 }
571
572 if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_RSP) {
573 std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
574 if (channel->local_initiated_) {
575 link_->NotifyChannelCreation(cid, std::move(user_channel));
576 } else {
577 dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
578 }
579 configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED;
580 data_pipeline_manager_->AttachChannel(cid, channel, l2cap::internal::DataPipelineManager::ChannelMode::BASIC);
581 data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state);
582 } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) {
583 configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_REQ;
584 }
585
586 alarm_.Cancel();
587 handle_send_next_command();
588 }
589
OnDisconnectionRequest(SignalId signal_id,Cid cid,Cid remote_cid)590 void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) {
591 // TODO: check cid match
592 auto channel = channel_allocator_->FindChannelByCid(cid);
593 if (channel == nullptr) {
594 LOG_WARN("Disconnect request for an unknown channel");
595 return;
596 }
597 auto builder = DisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid);
598 enqueue_buffer_->Enqueue(std::move(builder), handler_);
599 channel->OnClosed(hci::ErrorCode::SUCCESS);
600 auto& configuration_state = channel_configuration_[channel->GetCid()];
601 if (configuration_state.state_ == configuration_state.CONFIGURED) {
602 data_pipeline_manager_->DetachChannel(cid);
603 }
604 link_->FreeDynamicChannel(cid);
605 channel_configuration_.erase(cid);
606 }
607
OnDisconnectionResponse(SignalId signal_id,Cid remote_cid,Cid cid)608 void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) {
609 if (command_just_sent_.signal_id_ != signal_id ||
610 command_just_sent_.command_code_ != CommandCode::DISCONNECTION_REQUEST) {
611 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
612 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
613 signal_id.Value());
614 return;
615 }
616
617 alarm_.Cancel();
618
619 auto channel = channel_allocator_->FindChannelByCid(cid);
620 if (channel == nullptr) {
621 LOG_WARN("Disconnect response for an unknown channel");
622 handle_send_next_command();
623 return;
624 }
625
626 channel->OnClosed(hci::ErrorCode::SUCCESS);
627 auto& configuration_state = channel_configuration_[cid];
628 if (configuration_state.state_ == configuration_state.CONFIGURED) {
629 data_pipeline_manager_->DetachChannel(cid);
630 }
631 link_->FreeDynamicChannel(cid);
632 handle_send_next_command();
633 channel_configuration_.erase(cid);
634 }
635
OnEchoRequest(SignalId signal_id,const PacketView<kLittleEndian> & packet)636 void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
637 std::vector<uint8_t> packet_vector{packet.begin(), packet.end()};
638 auto raw_builder = std::make_unique<packet::RawBuilder>();
639 raw_builder->AddOctets(packet_vector);
640 auto builder = EchoResponseBuilder::Create(signal_id.Value(), std::move(raw_builder));
641 enqueue_buffer_->Enqueue(std::move(builder), handler_);
642 }
643
OnEchoResponse(SignalId signal_id,const PacketView<kLittleEndian> & packet)644 void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
645 if (command_just_sent_.signal_id_ != signal_id || command_just_sent_.command_code_ != CommandCode::ECHO_REQUEST) {
646 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
647 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
648 signal_id.Value());
649 return;
650 }
651 LOG_INFO("Echo response received");
652 alarm_.Cancel();
653 handle_send_next_command();
654 }
655
OnInformationRequest(SignalId signal_id,InformationRequestInfoType type)656 void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, InformationRequestInfoType type) {
657 switch (type) {
658 case InformationRequestInfoType::CONNECTIONLESS_MTU: {
659 auto response = InformationResponseConnectionlessMtuBuilder::Create(
660 signal_id.Value(), InformationRequestResult::SUCCESS, kDefaultClassicMtu);
661 enqueue_buffer_->Enqueue(std::move(response), handler_);
662 break;
663 }
664 case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
665 auto response = InformationResponseExtendedFeaturesBuilder::Create(
666 signal_id.Value(), InformationRequestResult::SUCCESS, 0, 0, 0, 1 /* ERTM */, 0 /* Streaming mode */,
667 1 /* FCS */, 0, 1 /* Fixed Channels */, 0, 0, 0 /* COC */);
668 enqueue_buffer_->Enqueue(std::move(response), handler_);
669 break;
670 }
671 case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
672 auto response = InformationResponseFixedChannelsBuilder::Create(
673 signal_id.Value(), InformationRequestResult::SUCCESS, fixed_service_manager_->GetSupportedFixedChannelMask());
674 enqueue_buffer_->Enqueue(std::move(response), handler_);
675 break;
676 }
677 }
678 }
679
OnInformationResponse(SignalId signal_id,const InformationResponseView & response)680 void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& response) {
681 if (command_just_sent_.signal_id_ != signal_id ||
682 command_just_sent_.command_code_ != CommandCode::INFORMATION_REQUEST) {
683 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
684 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
685 signal_id.Value());
686 return;
687 }
688
689 auto type = response.GetInfoType();
690 switch (type) {
691 case InformationRequestInfoType::CONNECTIONLESS_MTU: {
692 auto view = InformationResponseConnectionlessMtuView::Create(response);
693 if (!view.IsValid()) {
694 LOG_WARN("Invalid InformationResponseConnectionlessMtu received");
695 return;
696 }
697 link_->SetRemoteConnectionlessMtu(view.GetConnectionlessMtu());
698 break;
699 }
700 case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
701 auto view = InformationResponseExtendedFeaturesView::Create(response);
702 if (!view.IsValid()) {
703 LOG_WARN("Invalid InformationResponseExtendedFeatures received");
704 return;
705 }
706 link_->OnRemoteExtendedFeatureReceived(view.GetEnhancedRetransmissionMode(), view.GetFcsOption());
707 // We don't care about other parameters
708 break;
709 }
710 case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
711 auto view = InformationResponseFixedChannelsView::Create(response);
712 if (!view.IsValid()) {
713 LOG_WARN("Invalid InformationResponseFixedChannel received");
714 return;
715 }
716 // We don't use fixed channels (connectionless or BR/EDR security) for now so we don't care
717 break;
718 }
719 }
720
721 alarm_.Cancel();
722 handle_send_next_command();
723 }
724
on_incoming_packet()725 void ClassicSignallingManager::on_incoming_packet() {
726 auto packet = signalling_channel_->GetQueueUpEnd()->TryDequeue();
727 auto command_list = GetCommandsFromPacketView(*packet);
728 for (auto& command : command_list) {
729 handle_one_command(command);
730 }
731 }
732
handle_one_command(ControlView control_packet_view)733 void ClassicSignallingManager::handle_one_command(ControlView control_packet_view) {
734 if (!control_packet_view.IsValid()) {
735 LOG_WARN("Invalid signalling packet received");
736 return;
737 }
738 auto code = control_packet_view.GetCode();
739 switch (code) {
740 case CommandCode::COMMAND_REJECT: {
741 CommandRejectView command_reject_view = CommandRejectView::Create(control_packet_view);
742 if (!command_reject_view.IsValid()) {
743 return;
744 }
745 OnCommandReject(command_reject_view);
746 return;
747 }
748 case CommandCode::CONNECTION_REQUEST: {
749 ConnectionRequestView connection_request_view = ConnectionRequestView::Create(control_packet_view);
750 if (!connection_request_view.IsValid()) {
751 return;
752 }
753 OnConnectionRequest(control_packet_view.GetIdentifier(), connection_request_view.GetPsm(),
754 connection_request_view.GetSourceCid());
755 return;
756 }
757 case CommandCode::CONNECTION_RESPONSE: {
758 ConnectionResponseView connection_response_view = ConnectionResponseView::Create(control_packet_view);
759 if (!connection_response_view.IsValid()) {
760 return;
761 }
762 OnConnectionResponse(connection_response_view.GetIdentifier(), connection_response_view.GetDestinationCid(),
763 connection_response_view.GetSourceCid(), connection_response_view.GetResult(),
764 connection_response_view.GetStatus());
765 return;
766 }
767 case CommandCode::CONFIGURATION_REQUEST: {
768 ConfigurationRequestView configuration_request_view = ConfigurationRequestView::Create(control_packet_view);
769 if (!configuration_request_view.IsValid()) {
770 return;
771 }
772 OnConfigurationRequest(configuration_request_view.GetIdentifier(), configuration_request_view.GetDestinationCid(),
773 configuration_request_view.GetContinuation(), configuration_request_view.GetConfig());
774 return;
775 }
776 case CommandCode::CONFIGURATION_RESPONSE: {
777 ConfigurationResponseView configuration_response_view = ConfigurationResponseView::Create(control_packet_view);
778 if (!configuration_response_view.IsValid()) {
779 return;
780 }
781 OnConfigurationResponse(configuration_response_view.GetIdentifier(), configuration_response_view.GetSourceCid(),
782 configuration_response_view.GetContinuation(), configuration_response_view.GetResult(),
783 configuration_response_view.GetConfig());
784 return;
785 }
786 case CommandCode::DISCONNECTION_REQUEST: {
787 DisconnectionRequestView disconnection_request_view = DisconnectionRequestView::Create(control_packet_view);
788 if (!disconnection_request_view.IsValid()) {
789 return;
790 }
791 OnDisconnectionRequest(disconnection_request_view.GetIdentifier(), disconnection_request_view.GetDestinationCid(),
792 disconnection_request_view.GetSourceCid());
793 return;
794 }
795 case CommandCode::DISCONNECTION_RESPONSE: {
796 DisconnectionResponseView disconnection_response_view = DisconnectionResponseView::Create(control_packet_view);
797 if (!disconnection_response_view.IsValid()) {
798 return;
799 }
800 OnDisconnectionResponse(disconnection_response_view.GetIdentifier(),
801 disconnection_response_view.GetDestinationCid(),
802 disconnection_response_view.GetSourceCid());
803 return;
804 }
805 case CommandCode::ECHO_REQUEST: {
806 EchoRequestView echo_request_view = EchoRequestView::Create(control_packet_view);
807 if (!echo_request_view.IsValid()) {
808 return;
809 }
810 OnEchoRequest(echo_request_view.GetIdentifier(), echo_request_view.GetPayload());
811 return;
812 }
813 case CommandCode::ECHO_RESPONSE: {
814 EchoResponseView echo_response_view = EchoResponseView::Create(control_packet_view);
815 if (!echo_response_view.IsValid()) {
816 return;
817 }
818 OnEchoResponse(echo_response_view.GetIdentifier(), echo_response_view.GetPayload());
819 return;
820 }
821 case CommandCode::INFORMATION_REQUEST: {
822 InformationRequestView information_request_view = InformationRequestView::Create(control_packet_view);
823 if (!information_request_view.IsValid()) {
824 return;
825 }
826 OnInformationRequest(information_request_view.GetIdentifier(), information_request_view.GetInfoType());
827 return;
828 }
829 case CommandCode::INFORMATION_RESPONSE: {
830 InformationResponseView information_response_view = InformationResponseView::Create(control_packet_view);
831 if (!information_response_view.IsValid()) {
832 return;
833 }
834 OnInformationResponse(information_response_view.GetIdentifier(), information_response_view);
835 return;
836 }
837 case CommandCode::CREDIT_BASED_CONNECTION_REQUEST: {
838 CreditBasedConnectionRequestView request_view = CreditBasedConnectionRequestView::Create(control_packet_view);
839 if (!request_view.IsValid()) {
840 return;
841 }
842 return;
843 }
844 case CommandCode::CREDIT_BASED_CONNECTION_RESPONSE: {
845 CreditBasedConnectionResponseView response_view = CreditBasedConnectionResponseView::Create(control_packet_view);
846 if (!response_view.IsValid()) {
847 return;
848 }
849 return;
850 }
851 case CommandCode::CREDIT_BASED_RECONFIGURE_REQUEST: {
852 CreditBasedReconfigureRequestView request_view = CreditBasedReconfigureRequestView::Create(control_packet_view);
853 if (!request_view.IsValid()) {
854 return;
855 }
856 return;
857 }
858 case CommandCode::CREDIT_BASED_RECONFIGURE_RESPONSE: {
859 CreditBasedReconfigureResponseView response_view =
860 CreditBasedReconfigureResponseView::Create(control_packet_view);
861 if (!response_view.IsValid()) {
862 return;
863 }
864 return;
865 }
866 case CommandCode::FLOW_CONTROL_CREDIT: {
867 FlowControlCreditView credit_view = FlowControlCreditView::Create(control_packet_view);
868 if (!credit_view.IsValid()) {
869 return;
870 }
871 return;
872 }
873 default:
874 LOG_WARN("Unhandled event 0x%x", static_cast<int>(code));
875 auto builder = CommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier());
876 enqueue_buffer_->Enqueue(std::move(builder), handler_);
877 return;
878 }
879 }
880
send_connection_response(SignalId signal_id,Cid remote_cid,Cid local_cid,ConnectionResponseResult result,ConnectionResponseStatus status)881 void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid remote_cid, Cid local_cid,
882 ConnectionResponseResult result,
883 ConnectionResponseStatus status) {
884 auto builder = ConnectionResponseBuilder::Create(signal_id.Value(), local_cid, remote_cid, result, status);
885 enqueue_buffer_->Enqueue(std::move(builder), handler_);
886 }
887
on_command_timeout()888 void ClassicSignallingManager::on_command_timeout() {
889 LOG_WARN("Response time out");
890 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
891 LOG_ERROR("No pending command");
892 return;
893 }
894 LOG_WARN("Response time out for %s", CommandCodeText(command_just_sent_.command_code_).c_str());
895 switch (command_just_sent_.command_code_) {
896 case CommandCode::CONNECTION_REQUEST: {
897 DynamicChannelManager::ConnectionResult connection_result{
898 .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR,
899 .hci_error = hci::ErrorCode::SUCCESS,
900 .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE,
901 };
902 link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_, connection_result);
903 break;
904 }
905 case CommandCode::CONFIGURATION_REQUEST: {
906 auto channel = channel_allocator_->FindChannelByRemoteCid(command_just_sent_.destination_cid_);
907 SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
908 return;
909 }
910 case CommandCode::INFORMATION_REQUEST: {
911 if (command_just_sent_.info_type_ == InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED) {
912 link_->OnRemoteExtendedFeatureReceived(false, false);
913 }
914 break;
915 }
916 default:
917 break;
918 }
919 handle_send_next_command();
920 }
921
handle_send_next_command()922 void ClassicSignallingManager::handle_send_next_command() {
923 command_just_sent_.signal_id_ = kInvalidSignalId;
924 if (pending_commands_.empty()) {
925 return;
926 }
927 command_just_sent_ = std::move(pending_commands_.front());
928 pending_commands_.pop();
929
930 auto signal_id = command_just_sent_.signal_id_;
931 auto psm = command_just_sent_.psm_;
932 auto source_cid = command_just_sent_.source_cid_;
933 auto destination_cid = command_just_sent_.destination_cid_;
934 auto info_type = command_just_sent_.info_type_;
935 auto config = std::move(command_just_sent_.config_);
936 switch (command_just_sent_.command_code_) {
937 case CommandCode::CONNECTION_REQUEST: {
938 auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid);
939 enqueue_buffer_->Enqueue(std::move(builder), handler_);
940 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
941 kTimeout);
942 break;
943 }
944 case CommandCode::CONFIGURATION_REQUEST: {
945 auto builder =
946 ConfigurationRequestBuilder::Create(signal_id.Value(), destination_cid, Continuation::END, std::move(config));
947 enqueue_buffer_->Enqueue(std::move(builder), handler_);
948 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
949 kTimeout);
950 break;
951 }
952 case CommandCode::DISCONNECTION_REQUEST: {
953 auto builder = DisconnectionRequestBuilder::Create(signal_id.Value(), destination_cid, source_cid);
954 enqueue_buffer_->Enqueue(std::move(builder), handler_);
955 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
956 kTimeout);
957 break;
958 }
959 case CommandCode::INFORMATION_REQUEST: {
960 auto builder = InformationRequestBuilder::Create(signal_id.Value(), info_type);
961 enqueue_buffer_->Enqueue(std::move(builder), handler_);
962 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
963 kTimeout);
964 break;
965 }
966 default:
967 LOG_WARN("Unsupported command code 0x%x", static_cast<int>(command_just_sent_.command_code_));
968 }
969 }
970
971 } // namespace internal
972 } // namespace classic
973 } // namespace l2cap
974 } // namespace bluetooth
975