Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 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" |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 22 | #include "l2cap/classic/internal/channel_configuration_state.h" |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 23 | #include "l2cap/classic/internal/link.h" |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 24 | #include "l2cap/internal/data_pipeline_manager.h" |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 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 | |
| 35 | ClassicSignallingManager::ClassicSignallingManager(os::Handler* handler, Link* link, |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 36 | l2cap::internal::DataPipelineManager* data_pipeline_manager, |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 37 | DynamicChannelServiceManagerImpl* dynamic_service_manager, |
Hansong Zhang | 47dec64 | 2019-11-25 12:01:15 -0800 | [diff] [blame^] | 38 | l2cap::internal::DynamicChannelAllocator* channel_allocator, |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 39 | FixedChannelServiceManagerImpl* fixed_service_manager) |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 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) { |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 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 | |
| 52 | ClassicSignallingManager::~ClassicSignallingManager() { |
| 53 | enqueue_buffer_.reset(); |
| 54 | signalling_channel_->GetQueueUpEnd()->UnregisterDequeue(); |
| 55 | signalling_channel_ = nullptr; |
| 56 | } |
| 57 | |
| 58 | void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) { |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 59 | 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 66 | SignalId signal_id = command_reject_view.GetIdentifier(); |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 67 | if (last_sent_command.signal_id_ != signal_id) { |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 68 | LOG_WARN("Unknown command reject"); |
| 69 | return; |
| 70 | } |
Hansong Zhang | ad57a6e | 2019-10-24 17:23:18 -0700 | [diff] [blame] | 71 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 72 | |
| 73 | LOG_INFO("Command rejected"); |
| 74 | } |
| 75 | |
| 76 | void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) { |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 77 | PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}}; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 78 | next_signal_id_++; |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 79 | pending_commands_.push(std::move(pending_command)); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 80 | if (pending_commands_.size() == 1) { |
| 81 | handle_send_next_command(); |
| 82 | } |
| 83 | } |
| 84 | |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 85 | void 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 95 | |
| 96 | void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) { |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 97 | PendingCommand pending_command = { |
| 98 | next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}}; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 99 | next_signal_id_++; |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 100 | pending_commands_.push(std::move(pending_command)); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 101 | if (pending_commands_.size() == 1) { |
| 102 | handle_send_next_command(); |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) { |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 107 | PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}}; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 108 | next_signal_id_++; |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 109 | pending_commands_.push(std::move(pending_command)); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 110 | if (pending_commands_.size() == 1) { |
| 111 | handle_send_next_command(); |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | void ClassicSignallingManager::SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload) { |
| 116 | LOG_WARN("Not supported"); |
| 117 | } |
| 118 | |
| 119 | void 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 Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 154 | auto& configuration_state = channel_configuration_[new_channel->GetCid()]; |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 155 | auto* service = dynamic_service_manager_->GetService(psm); |
| 156 | auto initial_config = service->GetConfigOption(); |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 157 | |
| 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 Zhang | 70fb464 | 2019-11-20 17:33:06 -0800 | [diff] [blame] | 170 | if (!link_->GetRemoteSupportsErtm()) { |
| 171 | initial_config.channel_mode = DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC; |
| 172 | } |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 173 | switch (initial_config.channel_mode) { |
| 174 | case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC: |
| 175 | retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC; |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 176 | configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC; |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 177 | break; |
| 178 | case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION: |
| 179 | retransmission_flow_control_configuration->mode_ = |
| 180 | RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION; |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 181 | configuration_state.retransmission_and_flow_control_mode_ = |
| 182 | RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION; |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 183 | // 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 Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 191 | configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration; |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 192 | |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 193 | 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 198 | } |
| 199 | |
Chris Manton | 8b39a22 | 2019-10-31 20:39:11 -0700 | [diff] [blame] | 200 | void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid, |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 201 | ConnectionResponseResult result, ConnectionResponseStatus status) { |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 202 | 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 209 | LOG_WARN("Received unexpected connection response"); |
| 210 | return; |
| 211 | } |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 212 | 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 Zhang | 6f1ec72 | 2019-11-04 10:12:02 -0800 | [diff] [blame] | 214 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 215 | return; |
| 216 | } |
| 217 | if (result != ConnectionResponseResult::SUCCESS) { |
Hansong Zhang | 6f1ec72 | 2019-11-04 10:12:02 -0800 | [diff] [blame] | 218 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 219 | return; |
| 220 | } |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 221 | Psm pending_psm = last_sent_command.psm_; |
Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 222 | auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid, {}); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 223 | if (new_channel == nullptr) { |
| 224 | LOG_WARN("Can't allocate dynamic channel"); |
Hansong Zhang | 6f1ec72 | 2019-11-04 10:12:02 -0800 | [diff] [blame] | 225 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 226 | return; |
| 227 | } |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 228 | alarm_.Cancel(); |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 229 | |
| 230 | auto& configuration_state = channel_configuration_[new_channel->GetCid()]; |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 231 | auto initial_config = link_->GetConfigurationForInitialConfiguration(new_channel->GetCid()); |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 232 | |
| 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 Zhang | 70fb464 | 2019-11-20 17:33:06 -0800 | [diff] [blame] | 245 | if (!link_->GetRemoteSupportsErtm()) { |
| 246 | initial_config.channel_mode = DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC; |
| 247 | } |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 248 | switch (initial_config.channel_mode) { |
| 249 | case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC: |
| 250 | retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC; |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 251 | configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC; |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 252 | break; |
| 253 | case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION: |
| 254 | retransmission_flow_control_configuration->mode_ = |
| 255 | RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION; |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 256 | configuration_state.retransmission_and_flow_control_mode_ = |
| 257 | RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION; |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 258 | // 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 Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 266 | configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration; |
| 267 | |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 268 | std::vector<std::unique_ptr<ConfigurationOption>> config; |
| 269 | config.emplace_back(std::move(mtu_configuration)); |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 270 | config.emplace_back(std::move(retransmission_flow_control_configuration)); |
| 271 | config.emplace_back(std::move(fcs_option)); |
Chris Manton | d61c90e | 2019-11-08 15:06:56 -0800 | [diff] [blame] | 272 | SendConfigurationRequest(remote_cid, {}); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation, |
Hansong Zhang | 240a3c5 | 2019-11-14 10:04:41 -0800 | [diff] [blame] | 276 | std::vector<std::unique_ptr<ConfigurationOption>> options) { |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 277 | auto channel = channel_allocator_->FindChannelByCid(cid); |
| 278 | if (channel == nullptr) { |
| 279 | LOG_WARN("Configuration request for an unknown channel"); |
| 280 | return; |
| 281 | } |
Hansong Zhang | 240a3c5 | 2019-11-14 10:04:41 -0800 | [diff] [blame] | 282 | |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 283 | auto& configuration_state = channel_configuration_[cid]; |
| 284 | |
Hansong Zhang | 240a3c5 | 2019-11-14 10:04:41 -0800 | [diff] [blame] | 285 | for (auto& option : options) { |
| 286 | switch (option->type_) { |
| 287 | case ConfigurationOptionType::MTU: { |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 288 | configuration_state.outgoing_mtu_ = MtuConfigurationOption::Specialize(option.get())->mtu_; |
| 289 | // TODO: If less than minimum (required by spec), reject |
Hansong Zhang | 240a3c5 | 2019-11-14 10:04:41 -0800 | [diff] [blame] | 290 | 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 Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 298 | configuration_state.remote_retransmission_and_flow_control_ = *config; |
Hansong Zhang | 240a3c5 | 2019-11-14 10:04:41 -0800 | [diff] [blame] | 299 | break; |
| 300 | } |
| 301 | case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: { |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 302 | configuration_state.fcs_type_ = FrameCheckSequenceOption::Specialize(option.get())->fcs_type_; |
Hansong Zhang | 240a3c5 | 2019-11-14 10:04:41 -0800 | [diff] [blame] | 303 | 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 Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 315 | if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ) { |
Hansong Zhang | 6662d50 | 2019-11-07 17:09:00 -0800 | [diff] [blame] | 316 | std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_); |
Chris Manton | 6230a6f | 2019-11-13 18:37:33 -0800 | [diff] [blame] | 317 | 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 Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 322 | 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 Zhang | 6662d50 | 2019-11-07 17:09:00 -0800 | [diff] [blame] | 326 | } |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 327 | |
| 328 | auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation, |
| 329 | ConfigurationResponseResult::SUCCESS, {}); |
| 330 | enqueue_buffer_->Enqueue(std::move(response), handler_); |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 331 | } |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 332 | |
| 333 | void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation, |
| 334 | ConfigurationResponseResult result, |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 335 | std::vector<std::unique_ptr<ConfigurationOption>> options) { |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 336 | 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 Manton | 8b39a22 | 2019-10-31 20:39:11 -0700 | [diff] [blame] | 343 | |
Chris Manton | d61c90e | 2019-11-08 15:06:56 -0800 | [diff] [blame] | 344 | auto channel = channel_allocator_->FindChannelByCid(cid); |
Chris Manton | 8b39a22 | 2019-10-31 20:39:11 -0700 | [diff] [blame] | 345 | if (channel == nullptr) { |
| 346 | LOG_WARN("Configuration request for an unknown channel"); |
Hansong Zhang | 6f1ec72 | 2019-11-04 10:12:02 -0800 | [diff] [blame] | 347 | handle_send_next_command(); |
Chris Manton | 8b39a22 | 2019-10-31 20:39:11 -0700 | [diff] [blame] | 348 | return; |
| 349 | } |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 350 | |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 351 | // 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 Zhang | 6662d50 | 2019-11-07 17:09:00 -0800 | [diff] [blame] | 383 | std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_); |
Chris Manton | 6230a6f | 2019-11-13 18:37:33 -0800 | [diff] [blame] | 384 | 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 Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 389 | 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 Zhang | 6662d50 | 2019-11-07 17:09:00 -0800 | [diff] [blame] | 393 | } |
Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 394 | |
Hansong Zhang | 6662d50 | 2019-11-07 17:09:00 -0800 | [diff] [blame] | 395 | alarm_.Cancel(); |
Chris Manton | d61c90e | 2019-11-08 15:06:56 -0800 | [diff] [blame] | 396 | handle_send_next_command(); |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 397 | } |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 398 | |
| 399 | void 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 Zhang | 948f407 | 2019-11-08 15:57:17 -0800 | [diff] [blame] | 406 | auto builder = DisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 407 | enqueue_buffer_->Enqueue(std::move(builder), handler_); |
| 408 | channel->OnClosed(hci::ErrorCode::SUCCESS); |
| 409 | link_->FreeDynamicChannel(cid); |
Chris Manton | 8b39a22 | 2019-10-31 20:39:11 -0700 | [diff] [blame] | 410 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 411 | } |
| 412 | |
Chris Manton | d61c90e | 2019-11-08 15:06:56 -0800 | [diff] [blame] | 413 | void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) { |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 414 | 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 Manton | d61c90e | 2019-11-08 15:06:56 -0800 | [diff] [blame] | 420 | alarm_.Cancel(); |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 421 | |
| 422 | if (last_sent_command.signal_id_ != signal_id || |
| 423 | last_sent_command.command_code_ != CommandCode::DISCONNECTION_REQUEST) { |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 424 | return; |
| 425 | } |
| 426 | |
| 427 | auto channel = channel_allocator_->FindChannelByCid(cid); |
| 428 | if (channel == nullptr) { |
| 429 | LOG_WARN("Disconnect response for an unknown channel"); |
Hansong Zhang | 6f1ec72 | 2019-11-04 10:12:02 -0800 | [diff] [blame] | 430 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 431 | return; |
| 432 | } |
| 433 | |
| 434 | channel->OnClosed(hci::ErrorCode::SUCCESS); |
| 435 | link_->FreeDynamicChannel(cid); |
Chris Manton | 8b39a22 | 2019-10-31 20:39:11 -0700 | [diff] [blame] | 436 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 437 | } |
| 438 | |
| 439 | void 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 Zhang | 75ebaab | 2019-10-25 11:05:30 -0700 | [diff] [blame] | 443 | auto builder = EchoResponseBuilder::Create(signal_id.Value(), std::move(raw_builder)); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 444 | enqueue_buffer_->Enqueue(std::move(builder), handler_); |
Chris Manton | 8b39a22 | 2019-10-31 20:39:11 -0700 | [diff] [blame] | 445 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 446 | } |
| 447 | |
| 448 | void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) { |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 449 | 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 457 | return; |
| 458 | } |
| 459 | LOG_INFO("Echo response received"); |
Hansong Zhang | 6662d50 | 2019-11-07 17:09:00 -0800 | [diff] [blame] | 460 | alarm_.Cancel(); |
Chris Manton | d61c90e | 2019-11-08 15:06:56 -0800 | [diff] [blame] | 461 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 462 | } |
| 463 | |
| 464 | void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, InformationRequestInfoType type) { |
| 465 | switch (type) { |
| 466 | case InformationRequestInfoType::CONNECTIONLESS_MTU: { |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 467 | auto response = InformationResponseConnectionlessMtuBuilder::Create( |
| 468 | signal_id.Value(), InformationRequestResult::SUCCESS, kDefaultClassicMtu); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 469 | enqueue_buffer_->Enqueue(std::move(response), handler_); |
Hansong Zhang | 6f1ec72 | 2019-11-04 10:12:02 -0800 | [diff] [blame] | 470 | break; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 471 | } |
| 472 | case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: { |
| 473 | // TODO: implement this response |
| 474 | auto response = InformationResponseExtendedFeaturesBuilder::Create( |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 475 | signal_id.Value(), InformationRequestResult::SUCCESS, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 476 | enqueue_buffer_->Enqueue(std::move(response), handler_); |
Hansong Zhang | 6f1ec72 | 2019-11-04 10:12:02 -0800 | [diff] [blame] | 477 | break; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 478 | } |
| 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 Zhang | 6f1ec72 | 2019-11-04 10:12:02 -0800 | [diff] [blame] | 483 | break; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 484 | } |
| 485 | } |
| 486 | } |
| 487 | |
Hansong Zhang | 70fb464 | 2019-11-20 17:33:06 -0800 | [diff] [blame] | 488 | void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& response) { |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 489 | 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 498 | return; |
| 499 | } |
Hansong Zhang | 70fb464 | 2019-11-20 17:33:06 -0800 | [diff] [blame] | 500 | |
| 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 Zhang | 6662d50 | 2019-11-07 17:09:00 -0800 | [diff] [blame] | 534 | alarm_.Cancel(); |
Chris Manton | d61c90e | 2019-11-08 15:06:56 -0800 | [diff] [blame] | 535 | handle_send_next_command(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 536 | } |
| 537 | |
| 538 | void 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 Desaulniers | fc45cd9 | 2019-11-01 09:05:35 -0700 | [diff] [blame] | 591 | return; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 592 | } |
| 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 Zhang | 2b0a4c5 | 2019-11-08 15:22:40 -0800 | [diff] [blame] | 646 | auto builder = CommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier()); |
| 647 | enqueue_buffer_->Enqueue(std::move(builder), handler_); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 648 | return; |
| 649 | } |
| 650 | } |
| 651 | |
| 652 | void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid remote_cid, Cid local_cid, |
| 653 | ConnectionResponseResult result, |
| 654 | ConnectionResponseStatus status) { |
Hansong Zhang | 4670e8c | 2019-11-11 11:07:46 -0800 | [diff] [blame] | 655 | auto builder = ConnectionResponseBuilder::Create(signal_id.Value(), local_cid, remote_cid, result, status); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 656 | enqueue_buffer_->Enqueue(std::move(builder), handler_); |
| 657 | } |
| 658 | |
| 659 | void ClassicSignallingManager::on_command_timeout() { |
| 660 | LOG_WARN("Response time out"); |
Hansong Zhang | 5c30ec8 | 2019-11-08 16:34:17 -0800 | [diff] [blame] | 661 | 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 677 | } |
| 678 | |
| 679 | void ClassicSignallingManager::handle_send_next_command() { |
| 680 | if (pending_commands_.empty()) { |
| 681 | return; |
| 682 | } |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 683 | auto& last_sent_command = pending_commands_.front(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 684 | |
Hansong Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 685 | 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 692 | 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 Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 699 | 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 Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 705 | break; |
Hansong Zhang | c83e120 | 2019-10-16 13:31:52 -0700 | [diff] [blame] | 706 | } |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 707 | 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 Zhang | 1ab6b3e | 2019-10-28 14:55:02 -0700 | [diff] [blame] | 722 | LOG_WARN("Unsupported command code 0x%x", static_cast<int>(last_sent_command.command_code_)); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 723 | } |
| 724 | } |
| 725 | |
| 726 | } // namespace internal |
| 727 | } // namespace classic |
| 728 | } // namespace l2cap |
| 729 | } // namespace bluetooth |