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
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)35 ClassicSignallingManager::ClassicSignallingManager(os::Handler* handler, Link* link,
36 l2cap::internal::DataPipelineManager* data_pipeline_manager,
37 DynamicChannelServiceManagerImpl* dynamic_service_manager,
38 l2cap::internal::DynamicChannelAllocator* channel_allocator,
39 FixedChannelServiceManagerImpl* fixed_service_manager)
40 : handler_(handler), link_(link), data_pipeline_manager_(data_pipeline_manager),
41 dynamic_service_manager_(dynamic_service_manager), channel_allocator_(channel_allocator),
42 fixed_service_manager_(fixed_service_manager), alarm_(handler) {
43 ASSERT(handler_ != nullptr);
44 ASSERT(link_ != nullptr);
45 signalling_channel_ = link_->AllocateFixedChannel(kClassicSignallingCid, {});
46 signalling_channel_->GetQueueUpEnd()->RegisterDequeue(
47 handler_, common::Bind(&ClassicSignallingManager::on_incoming_packet, common::Unretained(this)));
48 enqueue_buffer_ =
49 std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>(signalling_channel_->GetQueueUpEnd());
50 }
51
~ClassicSignallingManager()52 ClassicSignallingManager::~ClassicSignallingManager() {
53 enqueue_buffer_.reset();
54 signalling_channel_->GetQueueUpEnd()->UnregisterDequeue();
55 signalling_channel_ = nullptr;
56 }
57
OnCommandReject(CommandRejectView command_reject_view)58 void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) {
59 if (command_just_sent_.signal_id_ != command_reject_view.GetIdentifier() ||
60 command_just_sent_.command_code_ != command_reject_view.GetCode()) {
61 LOG_WARN("Unexpected command reject: no pending request");
62 return;
63 }
64 alarm_.Cancel();
65 handle_send_next_command();
66
67 LOG_INFO("Command rejected");
68 }
69
SendConnectionRequest(Psm psm,Cid local_cid)70 void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) {
71 PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}};
72 next_signal_id_++;
73 pending_commands_.push(std::move(pending_command));
74 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
75 handle_send_next_command();
76 }
77 }
78
SendConfigurationRequest(Cid remote_cid,std::vector<std::unique_ptr<ConfigurationOption>> config)79 void ClassicSignallingManager::SendConfigurationRequest(Cid remote_cid,
80 std::vector<std::unique_ptr<ConfigurationOption>> config) {
81 PendingCommand pending_command = {next_signal_id_, CommandCode::CONFIGURATION_REQUEST, {}, {}, remote_cid, {},
82 std::move(config)};
83 next_signal_id_++;
84 pending_commands_.push(std::move(pending_command));
85 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
86 handle_send_next_command();
87 }
88 }
89
SendDisconnectionRequest(Cid local_cid,Cid remote_cid)90 void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) {
91 PendingCommand pending_command = {
92 next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}};
93 next_signal_id_++;
94 pending_commands_.push(std::move(pending_command));
95 channel_configuration_.erase(local_cid);
96 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
97 handle_send_next_command();
98 }
99 }
100
SendInformationRequest(InformationRequestInfoType type)101 void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) {
102 PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}};
103 next_signal_id_++;
104 pending_commands_.push(std::move(pending_command));
105 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
106 handle_send_next_command();
107 }
108 }
109
SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload)110 void ClassicSignallingManager::SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload) {
111 LOG_WARN("Not supported");
112 }
113
CancelAlarm()114 void ClassicSignallingManager::CancelAlarm() {
115 alarm_.Cancel();
116 }
117
OnConnectionRequest(SignalId signal_id,Psm psm,Cid remote_cid)118 void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid) {
119 if (!IsPsmValid(psm)) {
120 LOG_WARN("Invalid psm received from remote psm:%d remote_cid:%d", psm, remote_cid);
121 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
122 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
123 return;
124 }
125
126 if (remote_cid == kInvalidCid) {
127 LOG_WARN("Invalid remote cid received from remote psm:%d remote_cid:%d", psm, remote_cid);
128 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::INVALID_CID,
129 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
130 return;
131 }
132 if (channel_allocator_->IsPsmUsed(psm)) {
133 LOG_WARN("Psm already exists");
134 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
135 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
136 return;
137 }
138
139 if (!dynamic_service_manager_->IsServiceRegistered(psm)) {
140 LOG_INFO("Service for this psm (%d) is not registered", psm);
141 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
142 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
143 return;
144 }
145
146 auto new_channel = link_->AllocateDynamicChannel(psm, remote_cid, {});
147 if (new_channel == nullptr) {
148 LOG_WARN("Can't allocate dynamic channel");
149 return;
150 }
151 send_connection_response(signal_id, remote_cid, new_channel->GetCid(), ConnectionResponseResult::SUCCESS,
152 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
153 auto& configuration_state = channel_configuration_[new_channel->GetCid()];
154 auto* service = dynamic_service_manager_->GetService(psm);
155 auto initial_config = service->GetConfigOption();
156
157 auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
158 mtu_configuration->mtu_ = initial_config.incoming_mtu;
159 configuration_state.incoming_mtu_ = initial_config.incoming_mtu;
160
161 auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
162 fcs_option->fcs_type_ = FcsType::NO_FCS;
163 if (link_->GetRemoteSupportsFcs()) {
164 fcs_option->fcs_type_ = FcsType::DEFAULT;
165 configuration_state.fcs_type_ = FcsType::DEFAULT;
166 }
167
168 auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
169 switch (initial_config.channel_mode) {
170 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
171 retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
172 configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
173 break;
174 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
175 retransmission_flow_control_configuration->mode_ =
176 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
177 configuration_state.retransmission_and_flow_control_mode_ =
178 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
179 // TODO: Decide where to put initial values
180 retransmission_flow_control_configuration->tx_window_size_ = 10;
181 retransmission_flow_control_configuration->max_transmit_ = 20;
182 retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
183 retransmission_flow_control_configuration->monitor_time_out_ = 12000;
184 retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
185 break;
186 }
187 configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;
188
189 std::vector<std::unique_ptr<ConfigurationOption>> config;
190 config.emplace_back(std::move(mtu_configuration));
191 if (initial_config.channel_mode != DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) {
192 config.emplace_back(std::move(retransmission_flow_control_configuration));
193 config.emplace_back(std::move(fcs_option));
194 }
195 SendConfigurationRequest(remote_cid, std::move(config));
196 }
197
OnConnectionResponse(SignalId signal_id,Cid remote_cid,Cid cid,ConnectionResponseResult result,ConnectionResponseStatus status)198 void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid,
199 ConnectionResponseResult result, ConnectionResponseStatus status) {
200 if (command_just_sent_.signal_id_ != signal_id ||
201 command_just_sent_.command_code_ != CommandCode::CONNECTION_REQUEST) {
202 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
203 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
204 signal_id.Value());
205 return;
206 }
207 if (command_just_sent_.source_cid_ != cid) {
208 LOG_WARN("SCID doesn't match: expected %d, received %d", command_just_sent_.source_cid_, cid);
209 handle_send_next_command();
210 return;
211 }
212 if (result == ConnectionResponseResult::PENDING) {
213 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
214 kTimeout);
215 return;
216 }
217
218 command_just_sent_.signal_id_ = kInvalidSignalId;
219 alarm_.Cancel();
220 if (result != ConnectionResponseResult::SUCCESS) {
221 link_->OnOutgoingConnectionRequestFail(cid);
222 handle_send_next_command();
223 return;
224 }
225 Psm pending_psm = command_just_sent_.psm_;
226 auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid, {});
227 if (new_channel == nullptr) {
228 LOG_WARN("Can't allocate dynamic channel");
229 link_->OnOutgoingConnectionRequestFail(cid);
230 handle_send_next_command();
231 return;
232 }
233
234 auto& configuration_state = channel_configuration_[new_channel->GetCid()];
235 auto initial_config = link_->GetConfigurationForInitialConfiguration(new_channel->GetCid());
236
237 auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
238 mtu_configuration->mtu_ = initial_config.incoming_mtu;
239 configuration_state.incoming_mtu_ = initial_config.incoming_mtu;
240
241 auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
242 fcs_option->fcs_type_ = FcsType::DEFAULT;
243 if (!link_->GetRemoteSupportsFcs()) {
244 fcs_option->fcs_type_ = FcsType::NO_FCS;
245 configuration_state.fcs_type_ = FcsType::NO_FCS;
246 }
247
248 auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
249 switch (initial_config.channel_mode) {
250 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
251 retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
252 configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
253 break;
254 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
255 retransmission_flow_control_configuration->mode_ =
256 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
257 configuration_state.retransmission_and_flow_control_mode_ =
258 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
259 // TODO: Decide where to put initial values
260 retransmission_flow_control_configuration->tx_window_size_ = 10;
261 retransmission_flow_control_configuration->max_transmit_ = 20;
262 retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
263 retransmission_flow_control_configuration->monitor_time_out_ = 12000;
264 retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
265 break;
266 }
267 configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;
268
269 std::vector<std::unique_ptr<ConfigurationOption>> config;
270 config.emplace_back(std::move(mtu_configuration));
271 if (initial_config.channel_mode != DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) {
272 config.emplace_back(std::move(retransmission_flow_control_configuration));
273 config.emplace_back(std::move(fcs_option));
274 }
275 SendConfigurationRequest(remote_cid, std::move(config));
276 }
277
OnConfigurationRequest(SignalId signal_id,Cid cid,Continuation is_continuation,std::vector<std::unique_ptr<ConfigurationOption>> options)278 void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation,
279 std::vector<std::unique_ptr<ConfigurationOption>> options) {
280 auto channel = channel_allocator_->FindChannelByCid(cid);
281 if (channel == nullptr) {
282 LOG_WARN("Configuration request for an unknown channel");
283 return;
284 }
285
286 auto& configuration_state = channel_configuration_[cid];
287 std::vector<std::unique_ptr<ConfigurationOption>> rsp_options;
288
289 for (auto& option : options) {
290 switch (option->type_) {
291 case ConfigurationOptionType::MTU: {
292 configuration_state.outgoing_mtu_ = MtuConfigurationOption::Specialize(option.get())->mtu_;
293 // TODO: If less than minimum (required by spec), reject
294 break;
295 }
296 case ConfigurationOptionType::FLUSH_TIMEOUT: {
297 // TODO: Handle this configuration option
298 break;
299 }
300 case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
301 auto* config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
302 if (config->retransmission_time_out_ == 0) {
303 config->retransmission_time_out_ = 2000;
304 }
305 if (config->monitor_time_out_ == 0) {
306 config->monitor_time_out_ = 12000;
307 }
308 configuration_state.remote_retransmission_and_flow_control_ = *config;
309 rsp_options.emplace_back(std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config));
310 break;
311 }
312 case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
313 configuration_state.fcs_type_ = FrameCheckSequenceOption::Specialize(option.get())->fcs_type_;
314 break;
315 }
316 default:
317 LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
318 auto response =
319 ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
320 ConfigurationResponseResult::UNKNOWN_OPTIONS, {});
321 enqueue_buffer_->Enqueue(std::move(response), handler_);
322 return;
323 }
324 }
325
326 if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ) {
327 std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
328 if (channel->local_initiated_) {
329 link_->NotifyChannelCreation(cid, std::move(user_channel));
330 } else {
331 dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
332 }
333 configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED;
334 data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state);
335 } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) {
336 configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_RSP;
337 }
338
339 auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
340 ConfigurationResponseResult::SUCCESS, std::move(rsp_options));
341 enqueue_buffer_->Enqueue(std::move(response), handler_);
342 }
343
OnConfigurationResponse(SignalId signal_id,Cid cid,Continuation is_continuation,ConfigurationResponseResult result,std::vector<std::unique_ptr<ConfigurationOption>> options)344 void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation,
345 ConfigurationResponseResult result,
346 std::vector<std::unique_ptr<ConfigurationOption>> options) {
347 if (command_just_sent_.signal_id_ != signal_id ||
348 command_just_sent_.command_code_ != CommandCode::CONFIGURATION_REQUEST) {
349 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
350 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
351 signal_id.Value());
352 return;
353 }
354
355 auto channel = channel_allocator_->FindChannelByCid(cid);
356 if (channel == nullptr) {
357 LOG_WARN("Configuration request for an unknown channel");
358 handle_send_next_command();
359 return;
360 }
361
362 if (result == ConfigurationResponseResult::PENDING) {
363 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
364 kTimeout);
365 return;
366 }
367
368 if (result != ConfigurationResponseResult::SUCCESS) {
369 LOG_WARN("Configuration response not SUCCESS");
370 handle_send_next_command();
371 return;
372 }
373
374 auto& configuration_state = channel_configuration_[channel->GetCid()];
375
376 for (auto& option : options) {
377 switch (option->type_) {
378 case ConfigurationOptionType::MTU: {
379 auto config = MtuConfigurationOption::Specialize(option.get());
380 configuration_state.incoming_mtu_ = config->mtu_;
381 break;
382 }
383 case ConfigurationOptionType::FLUSH_TIMEOUT: {
384 // TODO: Handle this configuration option
385 break;
386 }
387 case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
388 auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
389 configuration_state.retransmission_and_flow_control_mode_ = config->mode_;
390 configuration_state.local_retransmission_and_flow_control_ = *config;
391 break;
392 }
393 case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
394 configuration_state.fcs_type_ = FrameCheckSequenceOption::Specialize(option.get())->fcs_type_;
395 break;
396 }
397 default:
398 LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
399 return;
400 }
401 }
402
403 if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_RSP) {
404 std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
405 if (channel->local_initiated_) {
406 link_->NotifyChannelCreation(cid, std::move(user_channel));
407 } else {
408 dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
409 }
410 configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED;
411 data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state);
412 } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) {
413 configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_REQ;
414 }
415
416 alarm_.Cancel();
417 handle_send_next_command();
418 }
419
OnDisconnectionRequest(SignalId signal_id,Cid cid,Cid remote_cid)420 void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) {
421 // TODO: check cid match
422 auto channel = channel_allocator_->FindChannelByCid(cid);
423 if (channel == nullptr) {
424 LOG_WARN("Disconnect request for an unknown channel");
425 return;
426 }
427 channel_configuration_.erase(cid);
428 auto builder = DisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid);
429 enqueue_buffer_->Enqueue(std::move(builder), handler_);
430 channel->OnClosed(hci::ErrorCode::SUCCESS);
431 link_->FreeDynamicChannel(cid);
432 }
433
OnDisconnectionResponse(SignalId signal_id,Cid remote_cid,Cid cid)434 void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) {
435 if (command_just_sent_.signal_id_ != signal_id ||
436 command_just_sent_.command_code_ != CommandCode::DISCONNECTION_REQUEST) {
437 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
438 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
439 signal_id.Value());
440 return;
441 }
442
443 alarm_.Cancel();
444
445 auto channel = channel_allocator_->FindChannelByCid(cid);
446 if (channel == nullptr) {
447 LOG_WARN("Disconnect response for an unknown channel");
448 handle_send_next_command();
449 return;
450 }
451
452 channel->OnClosed(hci::ErrorCode::SUCCESS);
453 link_->FreeDynamicChannel(cid);
454 handle_send_next_command();
455 }
456
OnEchoRequest(SignalId signal_id,const PacketView<kLittleEndian> & packet)457 void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
458 std::vector<uint8_t> packet_vector{packet.begin(), packet.end()};
459 auto raw_builder = std::make_unique<packet::RawBuilder>();
460 raw_builder->AddOctets(packet_vector);
461 auto builder = EchoResponseBuilder::Create(signal_id.Value(), std::move(raw_builder));
462 enqueue_buffer_->Enqueue(std::move(builder), handler_);
463 }
464
OnEchoResponse(SignalId signal_id,const PacketView<kLittleEndian> & packet)465 void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
466 if (command_just_sent_.signal_id_ != signal_id || command_just_sent_.command_code_ != CommandCode::ECHO_REQUEST) {
467 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
468 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
469 signal_id.Value());
470 return;
471 }
472 LOG_INFO("Echo response received");
473 alarm_.Cancel();
474 handle_send_next_command();
475 }
476
OnInformationRequest(SignalId signal_id,InformationRequestInfoType type)477 void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, InformationRequestInfoType type) {
478 switch (type) {
479 case InformationRequestInfoType::CONNECTIONLESS_MTU: {
480 auto response = InformationResponseConnectionlessMtuBuilder::Create(
481 signal_id.Value(), InformationRequestResult::SUCCESS, kDefaultClassicMtu);
482 enqueue_buffer_->Enqueue(std::move(response), handler_);
483 break;
484 }
485 case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
486 // TODO: implement this response
487 auto response = InformationResponseExtendedFeaturesBuilder::Create(
488 signal_id.Value(), InformationRequestResult::SUCCESS, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0);
489 enqueue_buffer_->Enqueue(std::move(response), handler_);
490 break;
491 }
492 case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
493 auto response = InformationResponseFixedChannelsBuilder::Create(
494 signal_id.Value(), InformationRequestResult::SUCCESS, fixed_service_manager_->GetSupportedFixedChannelMask());
495 enqueue_buffer_->Enqueue(std::move(response), handler_);
496 break;
497 }
498 }
499 }
500
OnInformationResponse(SignalId signal_id,const InformationResponseView & response)501 void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& response) {
502 if (command_just_sent_.signal_id_ != signal_id ||
503 command_just_sent_.command_code_ != CommandCode::INFORMATION_REQUEST) {
504 LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
505 command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
506 signal_id.Value());
507 return;
508 }
509
510 auto type = response.GetInfoType();
511 switch (type) {
512 case InformationRequestInfoType::CONNECTIONLESS_MTU: {
513 auto view = InformationResponseConnectionlessMtuView::Create(response);
514 if (!view.IsValid()) {
515 LOG_WARN("Invalid InformationResponseConnectionlessMtu received");
516 return;
517 }
518 link_->SetRemoteConnectionlessMtu(view.GetConnectionlessMtu());
519 break;
520 }
521 case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
522 auto view = InformationResponseExtendedFeaturesView::Create(response);
523 if (!view.IsValid()) {
524 LOG_WARN("Invalid InformationResponseExtendedFeatures received");
525 return;
526 }
527 link_->SetRemoteSupportsErtm((view.GetEnhancedRetransmissionMode()));
528 link_->SetRemoteSupportsFcs(view.GetFcsOption());
529 // We don't care about other parameters
530 break;
531 }
532 case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
533 auto view = InformationResponseFixedChannelsView::Create(response);
534 if (!view.IsValid()) {
535 LOG_WARN("Invalid InformationResponseFixedChannel received");
536 return;
537 }
538 // We don't use fixed channels (connectionless or BR/EDR security) for now so we don't care
539 break;
540 }
541 }
542
543 alarm_.Cancel();
544 handle_send_next_command();
545 }
546
on_incoming_packet()547 void ClassicSignallingManager::on_incoming_packet() {
548 auto packet = signalling_channel_->GetQueueUpEnd()->TryDequeue();
549 ControlView control_packet_view = ControlView::Create(*packet);
550 if (!control_packet_view.IsValid()) {
551 LOG_WARN("Invalid signalling packet received");
552 return;
553 }
554 auto code = control_packet_view.GetCode();
555 switch (code) {
556 case CommandCode::COMMAND_REJECT: {
557 CommandRejectView command_reject_view = CommandRejectView::Create(control_packet_view);
558 if (!command_reject_view.IsValid()) {
559 return;
560 }
561 OnCommandReject(command_reject_view);
562 return;
563 }
564 case CommandCode::CONNECTION_REQUEST: {
565 ConnectionRequestView connection_request_view = ConnectionRequestView::Create(control_packet_view);
566 if (!connection_request_view.IsValid()) {
567 return;
568 }
569 OnConnectionRequest(control_packet_view.GetIdentifier(), connection_request_view.GetPsm(),
570 connection_request_view.GetSourceCid());
571 return;
572 }
573 case CommandCode::CONNECTION_RESPONSE: {
574 ConnectionResponseView connection_response_view = ConnectionResponseView::Create(control_packet_view);
575 if (!connection_response_view.IsValid()) {
576 return;
577 }
578 OnConnectionResponse(connection_response_view.GetIdentifier(), connection_response_view.GetDestinationCid(),
579 connection_response_view.GetSourceCid(), connection_response_view.GetResult(),
580 connection_response_view.GetStatus());
581 return;
582 }
583 case CommandCode::CONFIGURATION_REQUEST: {
584 ConfigurationRequestView configuration_request_view = ConfigurationRequestView::Create(control_packet_view);
585 if (!configuration_request_view.IsValid()) {
586 return;
587 }
588 OnConfigurationRequest(configuration_request_view.GetIdentifier(), configuration_request_view.GetDestinationCid(),
589 configuration_request_view.GetContinuation(), configuration_request_view.GetConfig());
590 return;
591 }
592 case CommandCode::CONFIGURATION_RESPONSE: {
593 ConfigurationResponseView configuration_response_view = ConfigurationResponseView::Create(control_packet_view);
594 if (!configuration_response_view.IsValid()) {
595 return;
596 }
597 OnConfigurationResponse(configuration_response_view.GetIdentifier(), configuration_response_view.GetSourceCid(),
598 configuration_response_view.GetContinuation(), configuration_response_view.GetResult(),
599 configuration_response_view.GetConfig());
600 return;
601 }
602 case CommandCode::DISCONNECTION_REQUEST: {
603 DisconnectionRequestView disconnection_request_view = DisconnectionRequestView::Create(control_packet_view);
604 if (!disconnection_request_view.IsValid()) {
605 return;
606 }
607 OnDisconnectionRequest(disconnection_request_view.GetIdentifier(), disconnection_request_view.GetDestinationCid(),
608 disconnection_request_view.GetSourceCid());
609 return;
610 }
611 case CommandCode::DISCONNECTION_RESPONSE: {
612 DisconnectionResponseView disconnection_response_view = DisconnectionResponseView::Create(control_packet_view);
613 if (!disconnection_response_view.IsValid()) {
614 return;
615 }
616 OnDisconnectionResponse(disconnection_response_view.GetIdentifier(),
617 disconnection_response_view.GetDestinationCid(),
618 disconnection_response_view.GetSourceCid());
619 return;
620 }
621 case CommandCode::ECHO_REQUEST: {
622 EchoRequestView echo_request_view = EchoRequestView::Create(control_packet_view);
623 if (!echo_request_view.IsValid()) {
624 return;
625 }
626 OnEchoRequest(echo_request_view.GetIdentifier(), echo_request_view.GetPayload());
627 return;
628 }
629 case CommandCode::ECHO_RESPONSE: {
630 EchoResponseView echo_response_view = EchoResponseView::Create(control_packet_view);
631 if (!echo_response_view.IsValid()) {
632 return;
633 }
634 OnEchoResponse(echo_response_view.GetIdentifier(), echo_response_view.GetPayload());
635 return;
636 }
637 case CommandCode::INFORMATION_REQUEST: {
638 InformationRequestView information_request_view = InformationRequestView::Create(control_packet_view);
639 if (!information_request_view.IsValid()) {
640 return;
641 }
642 OnInformationRequest(information_request_view.GetIdentifier(), information_request_view.GetInfoType());
643 return;
644 }
645 case CommandCode::INFORMATION_RESPONSE: {
646 InformationResponseView information_response_view = InformationResponseView::Create(control_packet_view);
647 if (!information_response_view.IsValid()) {
648 return;
649 }
650 OnInformationResponse(information_response_view.GetIdentifier(), information_response_view);
651 return;
652 }
653 default:
654 LOG_WARN("Unhandled event 0x%x", static_cast<int>(code));
655 auto builder = CommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier());
656 enqueue_buffer_->Enqueue(std::move(builder), handler_);
657 return;
658 }
659 }
660
send_connection_response(SignalId signal_id,Cid remote_cid,Cid local_cid,ConnectionResponseResult result,ConnectionResponseStatus status)661 void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid remote_cid, Cid local_cid,
662 ConnectionResponseResult result,
663 ConnectionResponseStatus status) {
664 auto builder = ConnectionResponseBuilder::Create(signal_id.Value(), local_cid, remote_cid, result, status);
665 enqueue_buffer_->Enqueue(std::move(builder), handler_);
666 }
667
on_command_timeout()668 void ClassicSignallingManager::on_command_timeout() {
669 LOG_WARN("Response time out");
670 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
671 LOG_ERROR("No pending command");
672 return;
673 }
674
675 switch (command_just_sent_.command_code_) {
676 case CommandCode::CONNECTION_REQUEST: {
677 link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_);
678 break;
679 }
680 case CommandCode::CONFIGURATION_REQUEST: {
681 auto channel = channel_allocator_->FindChannelByRemoteCid(command_just_sent_.destination_cid_);
682 SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
683 break;
684 }
685 default:
686 break;
687 }
688 handle_send_next_command();
689 }
690
handle_send_next_command()691 void ClassicSignallingManager::handle_send_next_command() {
692 command_just_sent_.signal_id_ = kInvalidSignalId;
693 if (pending_commands_.empty()) {
694 return;
695 }
696 command_just_sent_ = std::move(pending_commands_.front());
697 pending_commands_.pop();
698
699 auto signal_id = command_just_sent_.signal_id_;
700 auto psm = command_just_sent_.psm_;
701 auto source_cid = command_just_sent_.source_cid_;
702 auto destination_cid = command_just_sent_.destination_cid_;
703 auto info_type = command_just_sent_.info_type_;
704 auto config = std::move(command_just_sent_.config_);
705 switch (command_just_sent_.command_code_) {
706 case CommandCode::CONNECTION_REQUEST: {
707 auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid);
708 enqueue_buffer_->Enqueue(std::move(builder), handler_);
709 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
710 kTimeout);
711 break;
712 }
713 case CommandCode::CONFIGURATION_REQUEST: {
714 auto builder =
715 ConfigurationRequestBuilder::Create(signal_id.Value(), destination_cid, Continuation::END, std::move(config));
716 enqueue_buffer_->Enqueue(std::move(builder), handler_);
717 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
718 kTimeout);
719 break;
720 }
721 case CommandCode::DISCONNECTION_REQUEST: {
722 auto builder = DisconnectionRequestBuilder::Create(signal_id.Value(), destination_cid, source_cid);
723 enqueue_buffer_->Enqueue(std::move(builder), handler_);
724 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
725 kTimeout);
726 break;
727 }
728 case CommandCode::INFORMATION_REQUEST: {
729 auto builder = InformationRequestBuilder::Create(signal_id.Value(), info_type);
730 enqueue_buffer_->Enqueue(std::move(builder), handler_);
731 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
732 kTimeout);
733 break;
734 }
735 default:
736 LOG_WARN("Unsupported command code 0x%x", static_cast<int>(command_just_sent_.command_code_));
737 }
738 }
739
740 } // namespace internal
741 } // namespace classic
742 } // namespace l2cap
743 } // namespace bluetooth
744