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