1/* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15//! task 16#![allow(missing_docs)] 17 18use crate::daemon_lib::{auth, daemon_unity}; 19 20use crate::daemon_lib::shell::*; 21 22use crate::daemon_lib::daemon_app::{self, AppTaskMap, DaemonAppTask}; 23use crate::daemon_lib::sys_para::*; 24use crate::utils::hdc_log::*; 25use crate::common::forward::{self, ForwardTaskMap, HdcForward}; 26use crate::common::hdcfile::{self, FileTaskMap, HdcFile}; 27use crate::common::jdwp; 28use crate::config::*; 29use crate::transfer; 30 31use std::io::{self, Error, ErrorKind}; 32 33async fn daemon_shell_task(task_message: TaskMessage, session_id: u32) -> io::Result<()> { 34 match task_message.command { 35 HdcCommand::ShellInit => { 36 let pty_task = PtyTask::new( 37 session_id, 38 task_message.channel_id, 39 None, 40 HdcCommand::KernelEchoRaw, 41 ); 42 PtyMap::put(session_id, task_message.channel_id, pty_task).await; 43 } 44 HdcCommand::UnityExecute => { 45 match String::from_utf8(task_message.payload) { 46 Ok(cmd_str) => { 47 let shell_execute_task: ShellExecuteTask = ShellExecuteTask::new( 48 session_id, 49 task_message.channel_id, 50 cmd_str, 51 HdcCommand::KernelEchoRaw, 52 ); 53 54 ShellExecuteMap::put(session_id, task_message.channel_id, shell_execute_task).await; 55 }, 56 Err(_) => { 57 crate::common::hdctransfer::echo_client( 58 session_id, 59 task_message.channel_id, 60 "only support utf-8 chars", 61 MessageLevel::Fail, 62 ) 63 .await; 64 let message = TaskMessage { 65 channel_id: task_message.channel_id, 66 command: HdcCommand::KernelChannelClose, 67 payload: [1].to_vec(), 68 }; 69 let _ = daemon_channel_close(message, session_id).await; 70 return Err(Error::new(ErrorKind::Other, "Get an FromUtf8Error")); 71 } 72 } 73 } 74 _ => { 75 let channel_id = task_message.channel_id; 76 if let Some(pty_task) = PtyMap::get(session_id, channel_id).await { 77 let _ = &pty_task.tx.send(task_message.payload.clone()).await; 78 if task_message.payload[..].contains(&0x4_u8) { 79 PtyMap::del(session_id, channel_id).await; 80 } 81 return Ok(()); 82 } else { 83 return Err(Error::new(ErrorKind::Other, "invalid channel id")); 84 } 85 } 86 } 87 Ok(()) 88} 89 90async fn remove_task(session_id: u32, channel_id: u32) { 91 jdwp::stop_task(session_id, channel_id).await; 92 AppTaskMap::remove(session_id, channel_id).await; 93 FileTaskMap::remove(session_id, channel_id).await; 94 forward::free_channel_task(session_id, channel_id).await; 95 // shell & hilog task 96 if let Some(pty_task) = PtyMap::get(session_id, channel_id).await { 97 let _ = &pty_task.tx.send(vec![0x04_u8]).await; 98 PtyMap::del(session_id, channel_id).await; 99 } 100 ShellExecuteMap::del(session_id, channel_id).await; 101} 102 103async fn daemon_channel_close(task_message: TaskMessage, session_id: u32) -> io::Result<()> { 104 // task stop: 105 crate::debug!( 106 "daemon_channel_close session_id {session_id}, channel_id {}", 107 task_message.channel_id 108 ); 109 110 remove_task(session_id, task_message.channel_id).await; 111 112 if task_message.payload[0] > 0 { 113 let message = TaskMessage { 114 channel_id: task_message.channel_id, 115 command: HdcCommand::KernelChannelClose, 116 payload: vec![task_message.payload[0] - 1], 117 }; 118 transfer::put(session_id, message).await; 119 } 120 Ok(()) 121} 122 123async fn daemon_file_task(task_message: TaskMessage, session_id: u32) -> io::Result<()> { 124 match task_message.command { 125 HdcCommand::AppCheck | HdcCommand::AppUninstall => { 126 if !AppTaskMap::exsit(session_id, task_message.channel_id).await { 127 let task = DaemonAppTask::new(session_id, task_message.channel_id); 128 AppTaskMap::put(session_id, task_message.channel_id, task).await; 129 } 130 daemon_app::command_dispatch( 131 session_id, 132 task_message.channel_id, 133 task_message.command, 134 &task_message.payload, 135 task_message.payload.len() as u16, 136 ) 137 .await; 138 return Ok(()); 139 } 140 HdcCommand::AppBegin | HdcCommand::AppData => { 141 daemon_app::command_dispatch( 142 session_id, 143 task_message.channel_id, 144 task_message.command, 145 &task_message.payload, 146 task_message.payload.len() as u16, 147 ) 148 .await; 149 return Ok(()); 150 } 151 HdcCommand::FileMode | HdcCommand::FileCheck | HdcCommand::FileInit => { 152 if !FileTaskMap::exsit(session_id, task_message.channel_id).await { 153 let mut task = HdcFile::new(session_id, task_message.channel_id); 154 task.transfer.server_or_daemon = false; 155 FileTaskMap::put(session_id, task_message.channel_id, task).await; 156 } 157 158 hdcfile::command_dispatch( 159 session_id, 160 task_message.channel_id, 161 task_message.command, 162 &task_message.payload, 163 task_message.payload.len() as u16, 164 ) 165 .await; 166 return Ok(()); 167 } 168 HdcCommand::ForwardInit | HdcCommand::ForwardCheck => { 169 let mut task = HdcForward::new(session_id, task_message.channel_id, false); 170 task.transfer.server_or_daemon = false; 171 ForwardTaskMap::update(session_id, task_message.channel_id, task).await; 172 forward::command_dispatch( 173 session_id, 174 task_message.channel_id, 175 task_message.command, 176 &task_message.payload, 177 task_message.payload.len() as u16, 178 ) 179 .await; 180 return Ok(()); 181 } 182 HdcCommand::ForwardCheckResult 183 | HdcCommand::ForwardActiveSlave 184 | HdcCommand::ForwardActiveMaster 185 | HdcCommand::ForwardData 186 | HdcCommand::ForwardFreeContext => { 187 forward::command_dispatch( 188 session_id, 189 task_message.channel_id, 190 task_message.command, 191 &task_message.payload, 192 task_message.payload.len() as u16, 193 ) 194 .await; 195 return Ok(()); 196 } 197 HdcCommand::FileBegin 198 | HdcCommand::FileData 199 | HdcCommand::FileFinish 200 | HdcCommand::DirMode => { 201 hdcfile::command_dispatch( 202 session_id, 203 task_message.channel_id, 204 task_message.command, 205 &task_message.payload, 206 task_message.payload.len() as u16, 207 ) 208 .await; 209 return Ok(()); 210 } 211 HdcCommand::UnityRunmode 212 | HdcCommand::UnityReboot 213 | HdcCommand::UnityRemount 214 | HdcCommand::UnityRootrun 215 | HdcCommand::JdwpList 216 | HdcCommand::JdwpTrack => { 217 daemon_unity::command_dispatch( 218 session_id, 219 task_message.channel_id, 220 task_message.command, 221 &task_message.payload, 222 task_message.payload.len() as u16, 223 ) 224 .await; 225 return Ok(()); 226 } 227 _ => { 228 crate::error!( 229 "other tasks, cmd {:?}. session_id {session_id}, channel_id {}", 230 task_message.command, 231 task_message.channel_id 232 ); 233 } 234 } 235 236 Ok(()) 237} 238 239async fn daemon_hilog_task(task_message: TaskMessage, session_id: u32) -> io::Result<()> { 240 let cmd = if task_message.payload.len() == 1 && task_message.payload[0] == 104 { 241 // payload is 'h' 242 "hilog -h" 243 } else { 244 // blank or unknown payload, ignore 245 "hilog" 246 } 247 .to_string(); 248 let pty_task = PtyTask::new( 249 session_id, 250 task_message.channel_id, 251 Some(cmd), 252 HdcCommand::KernelEchoRaw, 253 ); 254 PtyMap::put(session_id, task_message.channel_id, pty_task).await; 255 Ok(()) 256} 257 258async fn daemon_bug_report_task(task_message: TaskMessage, session_id: u32) -> io::Result<()> { 259 let pty_task = PtyTask::new( 260 session_id, 261 task_message.channel_id, 262 Some("hidumper".to_string()), 263 HdcCommand::UnityBugreportData, 264 ); 265 PtyMap::put(session_id, task_message.channel_id, pty_task).await; 266 Ok(()) 267} 268 269fn get_control_permission(param: &str) -> bool { 270 let (_, control_value) = get_dev_item(param, "_"); 271 if control_value.trim().to_lowercase() == "false" { 272 return false; 273 } 274 true 275} 276 277fn check_control(command: HdcCommand) -> bool { 278 let mut control_param = ""; 279 match command { 280 HdcCommand::UnityRunmode 281 | HdcCommand::UnityReboot 282 | HdcCommand::UnityRemount 283 | HdcCommand::UnityRootrun 284 | HdcCommand::ShellInit 285 | HdcCommand::ShellData 286 | HdcCommand::UnityExecute 287 | HdcCommand::UnityHilog 288 | HdcCommand::UnityBugreportInit 289 | HdcCommand::JdwpList 290 | HdcCommand::JdwpTrack => { 291 control_param = ENV_SHELL_CONTROL; 292 } 293 HdcCommand::FileInit 294 | HdcCommand::FileCheck 295 | HdcCommand::FileData 296 | HdcCommand::FileBegin 297 | HdcCommand::FileFinish 298 | HdcCommand::AppCheck 299 | HdcCommand::AppData 300 | HdcCommand::AppUninstall => { 301 control_param = ENV_FILE_CONTROL; 302 } 303 HdcCommand::ForwardInit 304 | HdcCommand::ForwardCheck 305 | HdcCommand::ForwardCheckResult 306 | HdcCommand::ForwardActiveSlave 307 | HdcCommand::ForwardActiveMaster 308 | HdcCommand::ForwardData 309 | HdcCommand::ForwardFreeContext => { 310 control_param = ENV_FPORT_CONTROL; 311 } 312 _ => {} 313 } 314 // (_, run_debug) = crate::utils::get_dev_item(param); 315 if !control_param.is_empty() && !get_control_permission(control_param) { 316 return false; 317 } 318 true 319} 320 321pub async fn dispatch_task(task_message: TaskMessage, session_id: u32) -> io::Result<()> { 322 let cmd = task_message.command; 323 let special_cmd = 324 (cmd == HdcCommand::KernelHandshake) || (cmd == HdcCommand::KernelChannelClose); 325 let auth_ok = auth::AuthStatusMap::get(session_id).await == auth::AuthStatus::Ok; 326 327 if !auth_ok && !special_cmd { 328 crate::error!("auth status is nok, cannt accept cmd: {}", cmd as u32); 329 crate::common::hdctransfer::echo_client( 330 session_id, 331 task_message.channel_id, 332 auth::get_auth_msg(session_id).await.as_str(), 333 MessageLevel::Fail, 334 ) 335 .await; 336 transfer::put( 337 session_id, 338 auth::make_channel_close_message(task_message.channel_id).await, 339 ) 340 .await; 341 return Err(Error::new( 342 ErrorKind::Other, 343 format!("auth status is nok, cannt accept cmd: {}", cmd as u32), 344 )); 345 } 346 if !check_control(task_message.command) { 347 crate::common::hdctransfer::echo_client( 348 session_id, 349 task_message.channel_id, 350 "debugging is not allowed", 351 MessageLevel::Fail, 352 ) 353 .await; 354 crate::common::hdctransfer::transfer_task_finish(task_message.channel_id, session_id).await; 355 crate::debug!( 356 "check_permission param false: {}", 357 task_message.command as u32 358 ); 359 360 return Ok(()); 361 } 362 match task_message.command { 363 HdcCommand::KernelHandshake => auth::handshake_task(task_message, session_id).await, 364 HdcCommand::UnityHilog => daemon_hilog_task(task_message, session_id).await, 365 HdcCommand::UnityBugreportInit => daemon_bug_report_task(task_message, session_id).await, 366 HdcCommand::ShellInit | HdcCommand::ShellData | HdcCommand::UnityExecute => { 367 daemon_shell_task(task_message, session_id).await 368 } 369 HdcCommand::KernelChannelClose => daemon_channel_close(task_message, session_id).await, 370 HdcCommand::FileInit 371 | HdcCommand::FileCheck 372 | HdcCommand::FileData 373 | HdcCommand::FileBegin 374 | HdcCommand::FileFinish 375 | HdcCommand::FileMode 376 | HdcCommand::DirMode 377 | HdcCommand::AppCheck 378 | HdcCommand::AppData 379 | HdcCommand::AppUninstall 380 | HdcCommand::ForwardInit 381 | HdcCommand::ForwardCheck 382 | HdcCommand::ForwardCheckResult 383 | HdcCommand::ForwardActiveSlave 384 | HdcCommand::ForwardActiveMaster 385 | HdcCommand::ForwardData 386 | HdcCommand::ForwardFreeContext 387 | HdcCommand::UnityRunmode 388 | HdcCommand::UnityReboot 389 | HdcCommand::UnityRemount 390 | HdcCommand::UnityRootrun 391 | HdcCommand::JdwpList 392 | HdcCommand::JdwpTrack => daemon_file_task(task_message, session_id).await, 393 HdcCommand::KernelWakeupSlavetask => Ok(()), 394 _ => Err(Error::new( 395 ErrorKind::Other, 396 format!("unknown command: {}", task_message.command as u32), 397 )), 398 } 399}