• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "l2cap/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