blob: a89d0ad7038263b72add3ca69023044753f920e6 [file] [log] [blame]
Hansong Zhangcd0c3192019-09-20 15:50:42 -07001/*
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"
Hansong Zhangf0a16922019-11-22 21:27:08 -080022#include "l2cap/classic/internal/channel_configuration_state.h"
Hansong Zhangcd0c3192019-09-20 15:50:42 -070023#include "l2cap/classic/internal/link.h"
Hansong Zhangf0a16922019-11-22 21:27:08 -080024#include "l2cap/internal/data_pipeline_manager.h"
Hansong Zhangcd0c3192019-09-20 15:50:42 -070025#include "l2cap/l2cap_packets.h"
26#include "os/log.h"
27#include "packet/raw_builder.h"
28
29namespace bluetooth {
30namespace l2cap {
31namespace classic {
32namespace internal {
33static constexpr auto kTimeout = std::chrono::seconds(3);
34
35ClassicSignallingManager::ClassicSignallingManager(os::Handler* handler, Link* link,
Hansong Zhangf0a16922019-11-22 21:27:08 -080036 l2cap::internal::DataPipelineManager* data_pipeline_manager,
Hansong Zhangcd0c3192019-09-20 15:50:42 -070037 DynamicChannelServiceManagerImpl* dynamic_service_manager,
Hansong Zhang47dec642019-11-25 12:01:15 -080038 l2cap::internal::DynamicChannelAllocator* channel_allocator,
Hansong Zhangcd0c3192019-09-20 15:50:42 -070039 FixedChannelServiceManagerImpl* fixed_service_manager)
Hansong Zhangf0a16922019-11-22 21:27:08 -080040 : 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) {
Hansong Zhangcd0c3192019-09-20 15:50:42 -070043 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
52ClassicSignallingManager::~ClassicSignallingManager() {
53 enqueue_buffer_.reset();
54 signalling_channel_->GetQueueUpEnd()->UnregisterDequeue();
55 signalling_channel_ = nullptr;
56}
57
58void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) {
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -070059 if (pending_commands_.empty()) {
60 LOG_WARN("Unexpected command reject: no pending request");
61 return;
62 }
63 auto last_sent_command = std::move(pending_commands_.front());
64 pending_commands_.pop();
65
Hansong Zhangcd0c3192019-09-20 15:50:42 -070066 SignalId signal_id = command_reject_view.GetIdentifier();
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -070067 if (last_sent_command.signal_id_ != signal_id) {
Hansong Zhangcd0c3192019-09-20 15:50:42 -070068 LOG_WARN("Unknown command reject");
69 return;
70 }
Hansong Zhangad57a6e2019-10-24 17:23:18 -070071 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -070072
73 LOG_INFO("Command rejected");
74}
75
76void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) {
Hansong Zhangc83e1202019-10-16 13:31:52 -070077 PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}};
Hansong Zhangcd0c3192019-09-20 15:50:42 -070078 next_signal_id_++;
Hansong Zhangc83e1202019-10-16 13:31:52 -070079 pending_commands_.push(std::move(pending_command));
Hansong Zhangcd0c3192019-09-20 15:50:42 -070080 if (pending_commands_.size() == 1) {
81 handle_send_next_command();
82 }
83}
84
Hansong Zhangc83e1202019-10-16 13:31:52 -070085void ClassicSignallingManager::SendConfigurationRequest(Cid remote_cid,
86 std::vector<std::unique_ptr<ConfigurationOption>> config) {
87 PendingCommand pending_command = {next_signal_id_, CommandCode::CONFIGURATION_REQUEST, {}, {}, remote_cid, {},
88 std::move(config)};
89 next_signal_id_++;
90 pending_commands_.push(std::move(pending_command));
91 if (pending_commands_.size() == 1) {
92 handle_send_next_command();
93 }
94}
Hansong Zhangcd0c3192019-09-20 15:50:42 -070095
96void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) {
Hansong Zhangc83e1202019-10-16 13:31:52 -070097 PendingCommand pending_command = {
98 next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}};
Hansong Zhangcd0c3192019-09-20 15:50:42 -070099 next_signal_id_++;
Hansong Zhangc83e1202019-10-16 13:31:52 -0700100 pending_commands_.push(std::move(pending_command));
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700101 if (pending_commands_.size() == 1) {
102 handle_send_next_command();
103 }
104}
105
106void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) {
Hansong Zhangc83e1202019-10-16 13:31:52 -0700107 PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}};
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700108 next_signal_id_++;
Hansong Zhangc83e1202019-10-16 13:31:52 -0700109 pending_commands_.push(std::move(pending_command));
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700110 if (pending_commands_.size() == 1) {
111 handle_send_next_command();
112 }
113}
114
115void ClassicSignallingManager::SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload) {
116 LOG_WARN("Not supported");
117}
118
119void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid) {
120 if (!IsPsmValid(psm)) {
121 LOG_WARN("Invalid psm received from remote psm:%d remote_cid:%d", psm, remote_cid);
122 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
123 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
124 return;
125 }
126
127 if (remote_cid == kInvalidCid) {
128 LOG_WARN("Invalid remote cid received from remote psm:%d remote_cid:%d", psm, remote_cid);
129 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::INVALID_CID,
130 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
131 return;
132 }
133 if (channel_allocator_->IsPsmUsed(psm)) {
134 LOG_WARN("Psm already exists");
135 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
136 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
137 return;
138 }
139
140 if (!dynamic_service_manager_->IsServiceRegistered(psm)) {
141 LOG_INFO("Service for this psm (%d) is not registered", psm);
142 send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
143 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
144 return;
145 }
146
147 auto new_channel = link_->AllocateDynamicChannel(psm, remote_cid, {});
148 if (new_channel == nullptr) {
149 LOG_WARN("Can't allocate dynamic channel");
150 return;
151 }
152 send_connection_response(signal_id, remote_cid, new_channel->GetCid(), ConnectionResponseResult::SUCCESS,
153 ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
Hansong Zhangf0a16922019-11-22 21:27:08 -0800154 auto& configuration_state = channel_configuration_[new_channel->GetCid()];
Hansong Zhanga6312532019-11-19 14:01:36 -0800155 auto* service = dynamic_service_manager_->GetService(psm);
156 auto initial_config = service->GetConfigOption();
Hansong Zhangf0a16922019-11-22 21:27:08 -0800157
158 auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
159 mtu_configuration->mtu_ = initial_config.incoming_mtu;
160 configuration_state.incoming_mtu_ = initial_config.incoming_mtu;
161
162 auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
163 fcs_option->fcs_type_ = FcsType::DEFAULT;
164 if (!link_->GetRemoteSupportsFcs()) {
165 fcs_option->fcs_type_ = FcsType::NO_FCS;
166 configuration_state.fcs_type_ = FcsType::NO_FCS;
167 }
168
169 auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
Hansong Zhang70fb4642019-11-20 17:33:06 -0800170 if (!link_->GetRemoteSupportsErtm()) {
171 initial_config.channel_mode = DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC;
172 }
Hansong Zhanga6312532019-11-19 14:01:36 -0800173 switch (initial_config.channel_mode) {
174 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
175 retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
Hansong Zhangf0a16922019-11-22 21:27:08 -0800176 configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
Hansong Zhanga6312532019-11-19 14:01:36 -0800177 break;
178 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
179 retransmission_flow_control_configuration->mode_ =
180 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
Hansong Zhangf0a16922019-11-22 21:27:08 -0800181 configuration_state.retransmission_and_flow_control_mode_ =
182 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
Hansong Zhanga6312532019-11-19 14:01:36 -0800183 // TODO: Decide where to put initial values
184 retransmission_flow_control_configuration->tx_window_size_ = 10;
185 retransmission_flow_control_configuration->max_transmit_ = 20;
186 retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
187 retransmission_flow_control_configuration->monitor_time_out_ = 12000;
188 retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
189 break;
190 }
Hansong Zhangf0a16922019-11-22 21:27:08 -0800191 configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;
Hansong Zhanga6312532019-11-19 14:01:36 -0800192
Hansong Zhanga6312532019-11-19 14:01:36 -0800193 std::vector<std::unique_ptr<ConfigurationOption>> config;
194 config.emplace_back(std::move(mtu_configuration));
195 config.emplace_back(std::move(retransmission_flow_control_configuration));
196 config.emplace_back(std::move(fcs_option));
197 SendConfigurationRequest(remote_cid, std::move(config));
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700198}
199
Chris Manton8b39a222019-10-31 20:39:11 -0700200void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid,
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700201 ConnectionResponseResult result, ConnectionResponseStatus status) {
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700202 if (pending_commands_.empty()) {
203 LOG_WARN("Unexpected response: no pending request");
204 return;
205 }
206 auto last_sent_command = std::move(pending_commands_.front());
207 pending_commands_.pop();
208 if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::CONNECTION_REQUEST) {
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700209 LOG_WARN("Received unexpected connection response");
210 return;
211 }
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700212 if (last_sent_command.source_cid_ != cid) {
213 LOG_WARN("SCID doesn't match: expected %d, received %d", last_sent_command.source_cid_, cid);
Hansong Zhang6f1ec722019-11-04 10:12:02 -0800214 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700215 return;
216 }
217 if (result != ConnectionResponseResult::SUCCESS) {
Hansong Zhang6f1ec722019-11-04 10:12:02 -0800218 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700219 return;
220 }
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700221 Psm pending_psm = last_sent_command.psm_;
Hansong Zhangd1b6c9b2019-10-22 16:11:53 -0700222 auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid, {});
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700223 if (new_channel == nullptr) {
224 LOG_WARN("Can't allocate dynamic channel");
Hansong Zhang6f1ec722019-11-04 10:12:02 -0800225 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700226 return;
227 }
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700228 alarm_.Cancel();
Hansong Zhangf0a16922019-11-22 21:27:08 -0800229
230 auto& configuration_state = channel_configuration_[new_channel->GetCid()];
Hansong Zhanga6312532019-11-19 14:01:36 -0800231 auto initial_config = link_->GetConfigurationForInitialConfiguration(new_channel->GetCid());
Hansong Zhangf0a16922019-11-22 21:27:08 -0800232
233 auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
234 mtu_configuration->mtu_ = initial_config.incoming_mtu;
235 configuration_state.incoming_mtu_ = initial_config.incoming_mtu;
236
237 auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
238 fcs_option->fcs_type_ = FcsType::DEFAULT;
239 if (!link_->GetRemoteSupportsFcs()) {
240 fcs_option->fcs_type_ = FcsType::NO_FCS;
241 configuration_state.fcs_type_ = FcsType::NO_FCS;
242 }
243
244 auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
Hansong Zhang70fb4642019-11-20 17:33:06 -0800245 if (!link_->GetRemoteSupportsErtm()) {
246 initial_config.channel_mode = DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC;
247 }
Hansong Zhanga6312532019-11-19 14:01:36 -0800248 switch (initial_config.channel_mode) {
249 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
250 retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
Hansong Zhangf0a16922019-11-22 21:27:08 -0800251 configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
Hansong Zhanga6312532019-11-19 14:01:36 -0800252 break;
253 case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
254 retransmission_flow_control_configuration->mode_ =
255 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
Hansong Zhangf0a16922019-11-22 21:27:08 -0800256 configuration_state.retransmission_and_flow_control_mode_ =
257 RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
Hansong Zhanga6312532019-11-19 14:01:36 -0800258 // TODO: Decide where to put initial values
259 retransmission_flow_control_configuration->tx_window_size_ = 10;
260 retransmission_flow_control_configuration->max_transmit_ = 20;
261 retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
262 retransmission_flow_control_configuration->monitor_time_out_ = 12000;
263 retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
264 break;
265 }
Hansong Zhangf0a16922019-11-22 21:27:08 -0800266 configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;
267
Hansong Zhanga6312532019-11-19 14:01:36 -0800268 std::vector<std::unique_ptr<ConfigurationOption>> config;
269 config.emplace_back(std::move(mtu_configuration));
Hansong Zhangf0a16922019-11-22 21:27:08 -0800270 config.emplace_back(std::move(retransmission_flow_control_configuration));
271 config.emplace_back(std::move(fcs_option));
Chris Mantond61c90e2019-11-08 15:06:56 -0800272 SendConfigurationRequest(remote_cid, {});
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700273}
274
275void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation,
Hansong Zhang240a3c52019-11-14 10:04:41 -0800276 std::vector<std::unique_ptr<ConfigurationOption>> options) {
Hansong Zhangc83e1202019-10-16 13:31:52 -0700277 auto channel = channel_allocator_->FindChannelByCid(cid);
278 if (channel == nullptr) {
279 LOG_WARN("Configuration request for an unknown channel");
280 return;
281 }
Hansong Zhang240a3c52019-11-14 10:04:41 -0800282
Hansong Zhangf0a16922019-11-22 21:27:08 -0800283 auto& configuration_state = channel_configuration_[cid];
284
Hansong Zhang240a3c52019-11-14 10:04:41 -0800285 for (auto& option : options) {
286 switch (option->type_) {
287 case ConfigurationOptionType::MTU: {
Hansong Zhangf0a16922019-11-22 21:27:08 -0800288 configuration_state.outgoing_mtu_ = MtuConfigurationOption::Specialize(option.get())->mtu_;
289 // TODO: If less than minimum (required by spec), reject
Hansong Zhang240a3c52019-11-14 10:04:41 -0800290 break;
291 }
292 case ConfigurationOptionType::FLUSH_TIMEOUT: {
293 // TODO: Handle this configuration option
294 break;
295 }
296 case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
297 auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
Hansong Zhangf0a16922019-11-22 21:27:08 -0800298 configuration_state.remote_retransmission_and_flow_control_ = *config;
Hansong Zhang240a3c52019-11-14 10:04:41 -0800299 break;
300 }
301 case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
Hansong Zhangf0a16922019-11-22 21:27:08 -0800302 configuration_state.fcs_type_ = FrameCheckSequenceOption::Specialize(option.get())->fcs_type_;
Hansong Zhang240a3c52019-11-14 10:04:41 -0800303 break;
304 }
305 default:
306 LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
307 auto response =
308 ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
309 ConfigurationResponseResult::UNKNOWN_OPTIONS, {});
310 enqueue_buffer_->Enqueue(std::move(response), handler_);
311 return;
312 }
313 }
314
Hansong Zhangf0a16922019-11-22 21:27:08 -0800315 if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ) {
Hansong Zhang6662d502019-11-07 17:09:00 -0800316 std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
Chris Manton6230a6f2019-11-13 18:37:33 -0800317 if (channel->local_initiated_) {
318 link_->NotifyChannelCreation(cid, std::move(user_channel));
319 } else {
320 dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
321 }
Hansong Zhangf0a16922019-11-22 21:27:08 -0800322 configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED;
323 data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state);
324 } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) {
325 configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_RSP;
Hansong Zhang6662d502019-11-07 17:09:00 -0800326 }
Hansong Zhangf0a16922019-11-22 21:27:08 -0800327
328 auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
329 ConfigurationResponseResult::SUCCESS, {});
330 enqueue_buffer_->Enqueue(std::move(response), handler_);
Hansong Zhangc83e1202019-10-16 13:31:52 -0700331}
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700332
333void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation,
334 ConfigurationResponseResult result,
Hansong Zhanga6312532019-11-19 14:01:36 -0800335 std::vector<std::unique_ptr<ConfigurationOption>> options) {
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700336 if (pending_commands_.empty()) {
337 LOG_WARN("Unexpected response: no pending request");
338 return;
339 }
340
341 auto last_sent_command = std::move(pending_commands_.front());
342 pending_commands_.pop();
Chris Manton8b39a222019-10-31 20:39:11 -0700343
Chris Mantond61c90e2019-11-08 15:06:56 -0800344 auto channel = channel_allocator_->FindChannelByCid(cid);
Chris Manton8b39a222019-10-31 20:39:11 -0700345 if (channel == nullptr) {
346 LOG_WARN("Configuration request for an unknown channel");
Hansong Zhang6f1ec722019-11-04 10:12:02 -0800347 handle_send_next_command();
Chris Manton8b39a222019-10-31 20:39:11 -0700348 return;
349 }
Hansong Zhanga6312532019-11-19 14:01:36 -0800350
Hansong Zhangf0a16922019-11-22 21:27:08 -0800351 // TODO: Handle status not SUCCESS
352
353 auto& configuration_state = channel_configuration_[channel->GetCid()];
354
355 for (auto& option : options) {
356 switch (option->type_) {
357 case ConfigurationOptionType::MTU: {
358 auto config = MtuConfigurationOption::Specialize(option.get());
359 configuration_state.incoming_mtu_ = config->mtu_;
360 break;
361 }
362 case ConfigurationOptionType::FLUSH_TIMEOUT: {
363 // TODO: Handle this configuration option
364 break;
365 }
366 case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
367 auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
368 configuration_state.retransmission_and_flow_control_mode_ = config->mode_;
369 configuration_state.local_retransmission_and_flow_control_ = *config;
370 break;
371 }
372 case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
373 configuration_state.fcs_type_ = FrameCheckSequenceOption::Specialize(option.get())->fcs_type_;
374 break;
375 }
376 default:
377 LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
378 return;
379 }
380 }
381
382 if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_RSP) {
Hansong Zhang6662d502019-11-07 17:09:00 -0800383 std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
Chris Manton6230a6f2019-11-13 18:37:33 -0800384 if (channel->local_initiated_) {
385 link_->NotifyChannelCreation(cid, std::move(user_channel));
386 } else {
387 dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
388 }
Hansong Zhangf0a16922019-11-22 21:27:08 -0800389 configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED;
390 data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state);
391 } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) {
392 configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_REQ;
Hansong Zhang6662d502019-11-07 17:09:00 -0800393 }
Hansong Zhangf0a16922019-11-22 21:27:08 -0800394
Hansong Zhang6662d502019-11-07 17:09:00 -0800395 alarm_.Cancel();
Chris Mantond61c90e2019-11-08 15:06:56 -0800396 handle_send_next_command();
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700397}
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700398
399void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) {
400 // TODO: check cid match
401 auto channel = channel_allocator_->FindChannelByCid(cid);
402 if (channel == nullptr) {
403 LOG_WARN("Disconnect request for an unknown channel");
404 return;
405 }
Hansong Zhang948f4072019-11-08 15:57:17 -0800406 auto builder = DisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid);
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700407 enqueue_buffer_->Enqueue(std::move(builder), handler_);
408 channel->OnClosed(hci::ErrorCode::SUCCESS);
409 link_->FreeDynamicChannel(cid);
Chris Manton8b39a222019-10-31 20:39:11 -0700410 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700411}
412
Chris Mantond61c90e2019-11-08 15:06:56 -0800413void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) {
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700414 if (pending_commands_.empty()) {
415 LOG_WARN("Unexpected response: no pending request");
416 return;
417 }
418 auto last_sent_command = std::move(pending_commands_.front());
419 pending_commands_.pop();
Chris Mantond61c90e2019-11-08 15:06:56 -0800420 alarm_.Cancel();
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700421
422 if (last_sent_command.signal_id_ != signal_id ||
423 last_sent_command.command_code_ != CommandCode::DISCONNECTION_REQUEST) {
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700424 return;
425 }
426
427 auto channel = channel_allocator_->FindChannelByCid(cid);
428 if (channel == nullptr) {
429 LOG_WARN("Disconnect response for an unknown channel");
Hansong Zhang6f1ec722019-11-04 10:12:02 -0800430 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700431 return;
432 }
433
434 channel->OnClosed(hci::ErrorCode::SUCCESS);
435 link_->FreeDynamicChannel(cid);
Chris Manton8b39a222019-10-31 20:39:11 -0700436 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700437}
438
439void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
440 std::vector<uint8_t> packet_vector{packet.begin(), packet.end()};
441 auto raw_builder = std::make_unique<packet::RawBuilder>();
442 raw_builder->AddOctets(packet_vector);
Hansong Zhang75ebaab2019-10-25 11:05:30 -0700443 auto builder = EchoResponseBuilder::Create(signal_id.Value(), std::move(raw_builder));
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700444 enqueue_buffer_->Enqueue(std::move(builder), handler_);
Chris Manton8b39a222019-10-31 20:39:11 -0700445 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700446}
447
448void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700449 if (pending_commands_.empty()) {
450 LOG_WARN("Unexpected response: no pending request");
451 return;
452 }
453 auto last_sent_command = std::move(pending_commands_.front());
454 pending_commands_.pop();
455
456 if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::ECHO_REQUEST) {
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700457 return;
458 }
459 LOG_INFO("Echo response received");
Hansong Zhang6662d502019-11-07 17:09:00 -0800460 alarm_.Cancel();
Chris Mantond61c90e2019-11-08 15:06:56 -0800461 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700462}
463
464void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, InformationRequestInfoType type) {
465 switch (type) {
466 case InformationRequestInfoType::CONNECTIONLESS_MTU: {
Hansong Zhanga6312532019-11-19 14:01:36 -0800467 auto response = InformationResponseConnectionlessMtuBuilder::Create(
468 signal_id.Value(), InformationRequestResult::SUCCESS, kDefaultClassicMtu);
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700469 enqueue_buffer_->Enqueue(std::move(response), handler_);
Hansong Zhang6f1ec722019-11-04 10:12:02 -0800470 break;
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700471 }
472 case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
473 // TODO: implement this response
474 auto response = InformationResponseExtendedFeaturesBuilder::Create(
Hansong Zhanga6312532019-11-19 14:01:36 -0800475 signal_id.Value(), InformationRequestResult::SUCCESS, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0);
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700476 enqueue_buffer_->Enqueue(std::move(response), handler_);
Hansong Zhang6f1ec722019-11-04 10:12:02 -0800477 break;
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700478 }
479 case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
480 auto response = InformationResponseFixedChannelsBuilder::Create(
481 signal_id.Value(), InformationRequestResult::SUCCESS, fixed_service_manager_->GetSupportedFixedChannelMask());
482 enqueue_buffer_->Enqueue(std::move(response), handler_);
Hansong Zhang6f1ec722019-11-04 10:12:02 -0800483 break;
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700484 }
485 }
486}
487
Hansong Zhang70fb4642019-11-20 17:33:06 -0800488void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& response) {
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700489 if (pending_commands_.empty()) {
490 LOG_WARN("Unexpected response: no pending request");
491 return;
492 }
493 auto last_sent_command = std::move(pending_commands_.front());
494 pending_commands_.pop();
495
496 if (last_sent_command.signal_id_ != signal_id ||
497 last_sent_command.command_code_ != CommandCode::INFORMATION_REQUEST) {
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700498 return;
499 }
Hansong Zhang70fb4642019-11-20 17:33:06 -0800500
501 auto type = response.GetInfoType();
502 switch (type) {
503 case InformationRequestInfoType::CONNECTIONLESS_MTU: {
504 auto view = InformationResponseConnectionlessMtuView::Create(response);
505 if (!view.IsValid()) {
506 LOG_WARN("Invalid InformationResponseConnectionlessMtu received");
507 return;
508 }
509 link_->SetRemoteConnectionlessMtu(view.GetConnectionlessMtu());
510 break;
511 }
512 case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
513 auto view = InformationResponseExtendedFeaturesView::Create(response);
514 if (!view.IsValid()) {
515 LOG_WARN("Invalid InformationResponseExtendedFeatures received");
516 return;
517 }
518 link_->SetRemoteSupportsErtm((view.GetEnhancedRetransmissionMode()));
519 link_->SetRemoteSupportsFcs(view.GetFcsOption());
520 // We don't care about other parameters
521 break;
522 }
523 case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
524 auto view = InformationResponseFixedChannelsView::Create(response);
525 if (!view.IsValid()) {
526 LOG_WARN("Invalid InformationResponseFixedChannel received");
527 return;
528 }
529 // We don't use fixed channels (connectionless or BR/EDR security) for now so we don't care
530 break;
531 }
532 }
533
Hansong Zhang6662d502019-11-07 17:09:00 -0800534 alarm_.Cancel();
Chris Mantond61c90e2019-11-08 15:06:56 -0800535 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700536}
537
538void ClassicSignallingManager::on_incoming_packet() {
539 auto packet = signalling_channel_->GetQueueUpEnd()->TryDequeue();
540 ControlView control_packet_view = ControlView::Create(*packet);
541 if (!control_packet_view.IsValid()) {
542 LOG_WARN("Invalid signalling packet received");
543 return;
544 }
545 auto code = control_packet_view.GetCode();
546 switch (code) {
547 case CommandCode::COMMAND_REJECT: {
548 CommandRejectView command_reject_view = CommandRejectView::Create(control_packet_view);
549 if (!command_reject_view.IsValid()) {
550 return;
551 }
552 OnCommandReject(command_reject_view);
553 return;
554 }
555 case CommandCode::CONNECTION_REQUEST: {
556 ConnectionRequestView connection_request_view = ConnectionRequestView::Create(control_packet_view);
557 if (!connection_request_view.IsValid()) {
558 return;
559 }
560 OnConnectionRequest(control_packet_view.GetIdentifier(), connection_request_view.GetPsm(),
561 connection_request_view.GetSourceCid());
562 return;
563 }
564 case CommandCode::CONNECTION_RESPONSE: {
565 ConnectionResponseView connection_response_view = ConnectionResponseView::Create(control_packet_view);
566 if (!connection_response_view.IsValid()) {
567 return;
568 }
569 OnConnectionResponse(connection_response_view.GetIdentifier(), connection_response_view.GetDestinationCid(),
570 connection_response_view.GetSourceCid(), connection_response_view.GetResult(),
571 connection_response_view.GetStatus());
572 return;
573 }
574 case CommandCode::CONFIGURATION_REQUEST: {
575 ConfigurationRequestView configuration_request_view = ConfigurationRequestView::Create(control_packet_view);
576 if (!configuration_request_view.IsValid()) {
577 return;
578 }
579 OnConfigurationRequest(configuration_request_view.GetIdentifier(), configuration_request_view.GetDestinationCid(),
580 configuration_request_view.GetContinuation(), configuration_request_view.GetConfig());
581 return;
582 }
583 case CommandCode::CONFIGURATION_RESPONSE: {
584 ConfigurationResponseView configuration_response_view = ConfigurationResponseView::Create(control_packet_view);
585 if (!configuration_response_view.IsValid()) {
586 return;
587 }
588 OnConfigurationResponse(configuration_response_view.GetIdentifier(), configuration_response_view.GetSourceCid(),
589 configuration_response_view.GetContinuation(), configuration_response_view.GetResult(),
590 configuration_response_view.GetConfig());
Nick Desaulniersfc45cd92019-11-01 09:05:35 -0700591 return;
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700592 }
593 case CommandCode::DISCONNECTION_REQUEST: {
594 DisconnectionRequestView disconnection_request_view = DisconnectionRequestView::Create(control_packet_view);
595 if (!disconnection_request_view.IsValid()) {
596 return;
597 }
598 OnDisconnectionRequest(disconnection_request_view.GetIdentifier(), disconnection_request_view.GetDestinationCid(),
599 disconnection_request_view.GetSourceCid());
600 return;
601 }
602 case CommandCode::DISCONNECTION_RESPONSE: {
603 DisconnectionResponseView disconnection_response_view = DisconnectionResponseView::Create(control_packet_view);
604 if (!disconnection_response_view.IsValid()) {
605 return;
606 }
607 OnDisconnectionResponse(disconnection_response_view.GetIdentifier(),
608 disconnection_response_view.GetDestinationCid(),
609 disconnection_response_view.GetSourceCid());
610 return;
611 }
612 case CommandCode::ECHO_REQUEST: {
613 EchoRequestView echo_request_view = EchoRequestView::Create(control_packet_view);
614 if (!echo_request_view.IsValid()) {
615 return;
616 }
617 OnEchoRequest(echo_request_view.GetIdentifier(), echo_request_view.GetPayload());
618 return;
619 }
620 case CommandCode::ECHO_RESPONSE: {
621 EchoResponseView echo_response_view = EchoResponseView::Create(control_packet_view);
622 if (!echo_response_view.IsValid()) {
623 return;
624 }
625 OnEchoResponse(echo_response_view.GetIdentifier(), echo_response_view.GetPayload());
626 return;
627 }
628 case CommandCode::INFORMATION_REQUEST: {
629 InformationRequestView information_request_view = InformationRequestView::Create(control_packet_view);
630 if (!information_request_view.IsValid()) {
631 return;
632 }
633 OnInformationRequest(information_request_view.GetIdentifier(), information_request_view.GetInfoType());
634 return;
635 }
636 case CommandCode::INFORMATION_RESPONSE: {
637 InformationResponseView information_response_view = InformationResponseView::Create(control_packet_view);
638 if (!information_response_view.IsValid()) {
639 return;
640 }
641 OnInformationResponse(information_response_view.GetIdentifier(), information_response_view);
642 return;
643 }
644 default:
645 LOG_WARN("Unhandled event 0x%x", static_cast<int>(code));
Hansong Zhang2b0a4c52019-11-08 15:22:40 -0800646 auto builder = CommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier());
647 enqueue_buffer_->Enqueue(std::move(builder), handler_);
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700648 return;
649 }
650}
651
652void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid remote_cid, Cid local_cid,
653 ConnectionResponseResult result,
654 ConnectionResponseStatus status) {
Hansong Zhang4670e8c2019-11-11 11:07:46 -0800655 auto builder = ConnectionResponseBuilder::Create(signal_id.Value(), local_cid, remote_cid, result, status);
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700656 enqueue_buffer_->Enqueue(std::move(builder), handler_);
657}
658
659void ClassicSignallingManager::on_command_timeout() {
660 LOG_WARN("Response time out");
Hansong Zhang5c30ec82019-11-08 16:34:17 -0800661 if (pending_commands_.empty()) {
662 LOG_ERROR("No pending command");
663 return;
664 }
665
666 auto last_sent_command = std::move(pending_commands_.front());
667 pending_commands_.pop();
668 switch (last_sent_command.command_code_) {
669 case CommandCode::CONFIGURATION_REQUEST: {
670 SendDisconnectionRequest(last_sent_command.source_cid_, last_sent_command.destination_cid_);
671 break;
672 }
673 default:
674 break;
675 }
676 handle_send_next_command();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700677}
678
679void ClassicSignallingManager::handle_send_next_command() {
680 if (pending_commands_.empty()) {
681 return;
682 }
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700683 auto& last_sent_command = pending_commands_.front();
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700684
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700685 auto signal_id = last_sent_command.signal_id_;
686 auto psm = last_sent_command.psm_;
687 auto source_cid = last_sent_command.source_cid_;
688 auto destination_cid = last_sent_command.destination_cid_;
689 auto info_type = last_sent_command.info_type_;
690 auto config = std::move(last_sent_command.config_);
691 switch (last_sent_command.command_code_) {
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700692 case CommandCode::CONNECTION_REQUEST: {
693 auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid);
694 enqueue_buffer_->Enqueue(std::move(builder), handler_);
695 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
696 kTimeout);
697 break;
698 }
Hansong Zhangc83e1202019-10-16 13:31:52 -0700699 case CommandCode::CONFIGURATION_REQUEST: {
700 auto builder =
701 ConfigurationRequestBuilder::Create(signal_id.Value(), destination_cid, Continuation::END, std::move(config));
702 enqueue_buffer_->Enqueue(std::move(builder), handler_);
703 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
704 kTimeout);
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700705 break;
Hansong Zhangc83e1202019-10-16 13:31:52 -0700706 }
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700707 case CommandCode::DISCONNECTION_REQUEST: {
708 auto builder = DisconnectionRequestBuilder::Create(signal_id.Value(), destination_cid, source_cid);
709 enqueue_buffer_->Enqueue(std::move(builder), handler_);
710 alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
711 kTimeout);
712 break;
713 }
714 case CommandCode::INFORMATION_REQUEST: {
715 auto builder = InformationRequestBuilder::Create(signal_id.Value(), info_type);
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 default:
Hansong Zhang1ab6b3e2019-10-28 14:55:02 -0700722 LOG_WARN("Unsupported command code 0x%x", static_cast<int>(last_sent_command.command_code_));
Hansong Zhangcd0c3192019-09-20 15:50:42 -0700723 }
724}
725
726} // namespace internal
727} // namespace classic
728} // namespace l2cap
729} // namespace bluetooth