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
18 use crate::daemon_lib::{auth, daemon_unity};
19
20 use crate::daemon_lib::shell::*;
21
22 use crate::daemon_lib::daemon_app::{self, AppTaskMap, DaemonAppTask};
23 use crate::daemon_lib::sys_para::*;
24 use crate::utils::hdc_log::*;
25 use crate::common::forward::{self, ForwardTaskMap, HdcForward};
26 use crate::common::hdcfile::{self, FileTaskMap, HdcFile};
27 use crate::common::jdwp;
28 use crate::config::*;
29 use crate::transfer;
30
31 use std::io::{self, Error, ErrorKind};
32
33 async 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
90 async 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
103 async 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
123 async 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
239 async 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
258 async 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
get_control_permissionnull269 fn 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
check_controlnull277 fn 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
321 pub 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 }