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 use crate::auth::{handshake_task, start_handshake_with_daemon};
16 use crate::config::*;
17 use crate::host_app;
18 use crate::host_app::HostAppTaskMap;
19 use hdc::common::forward::{self, ForwardTaskMap, HdcForward};
20 /// ActionType 未定义,临时屏蔽
21 /// use crate::host_app::HostAppTask;
22 /// use hdc::common::hdcfile::HdcFile;
23 use hdc::common::hdcfile::{self, FileTaskMap, HdcFile};
24 use hdc::config::{ConnectType, HdcCommand};
25 use hdc::host_transfer::host_usb;
26 use hdc::transfer;
27 use hdc::transfer::send_channel_data;
28 use hdc::utils;
29 #[allow(unused)]
30 use hdc::utils::hdc_log::*;
31 use std::collections::HashMap;
32 use std::io::{self, Error, ErrorKind};
33 use std::sync::Arc;
34 
35 #[cfg(feature = "host")]
36 extern crate ylong_runtime_static as ylong_runtime;
37 use ylong_runtime::net::SplitReadHalf;
38 use ylong_runtime::net::TcpStream;
39 use ylong_runtime::sync::{Mutex, RwLock, mpsc};
40 
41 use crate::host_app::HostAppTask;
42 
43 #[derive(Debug, Clone)]
44 pub struct TaskInfo {
45     pub command: HdcCommand,
46     pub connect_key: String,
47     pub channel_id: u32,
48     pub params: Vec<String>,
49 }
50 
51 pub async fn channel_task_dispatch(task_info: TaskInfo) -> io::Result<()> {
52     hdc::debug!(
53         "in channel_task_dispatch, task_info={:#?}",
54         task_info.clone()
55     );
56 
57     match task_info.command {
58         HdcCommand::UnityRunmode | HdcCommand::UnityRootrun => {
59             hdc::trace!("dispatch to runmode task");
60             channel_unity_task(task_info).await?
61         }
62         HdcCommand::UnityReboot => {
63             send_to_daemon(task_info, HdcCommand::UnityReboot, 0, true).await?;
64         }
65         | HdcCommand::UnityRemount => {
66             send_to_daemon(task_info, HdcCommand::UnityRemount, 2, false).await?;
67         }
68         HdcCommand::UnityExecute | HdcCommand::ShellInit | HdcCommand::ShellData => {
69             hdc::trace!("dispatch to shell task");
70             channel_shell_task(task_info).await?
71         }
72         HdcCommand::KernelTargetConnect => {
73             hdc::trace!("dispatch to tconn task");
74             channel_connect_task(task_info).await?;
75         }
76         HdcCommand::KernelTargetList => {
77             hdc::trace!("dispatch to list task");
78             channel_list_targets_task(task_info).await?;
79         }
80         HdcCommand::KernelWaitFor => {
81             hdc::trace!("dispatch to wait");
82             channel_wait_for_any(task_info).await?;
83         }
84         HdcCommand::KernelChannelClose => {
85             hdc::trace!("dispatch to close task");
86             transfer::TcpMap::end(task_info.channel_id).await;
87         }
88         HdcCommand::FileInit
89         | HdcCommand::FileBegin
90         | HdcCommand::FileData
91         | HdcCommand::FileCheck
92         | HdcCommand::FileFinish
93         | HdcCommand::AppInit
94         | HdcCommand::AppBegin
95         | HdcCommand::AppData
96         | HdcCommand::AppFinish
97         | HdcCommand::AppUninstall => {
98             channel_file_task(task_info).await?;
99         }
100         HdcCommand::FileRecvInit => {
101             send_to_daemon(task_info, HdcCommand::FileInit, 2, false).await?;
102         }
103         HdcCommand::UnityHilog => {
104             channel_hilog_task(task_info).await?;
105         }
106         HdcCommand::UnityBugreportInit => {
107             channel_bug_report_task(task_info).await?;
108         }
109 
110         HdcCommand::ForwardInit => {
111             channel_forward_task(task_info).await?;
112         }
113         HdcCommand::ForwardRportInit => {
114             send_to_daemon(task_info, HdcCommand::ForwardInit, 1, false).await?;
115         }
116         HdcCommand::ForwardRportList => {
117             channel_forward_list(task_info, false).await?;
118         }
119         HdcCommand::ForwardList => {
120             channel_forward_list(task_info, true).await?;
121         }
122         HdcCommand::ForwardRemove => {
123             channel_forward_remove(task_info, true).await?;
124         }
125         HdcCommand::ForwardRportRemove => {
126             channel_forward_remove(task_info, false).await?;
127         }
128         HdcCommand::JdwpList | HdcCommand::JdwpTrack => {
129             channel_jdwp_task(task_info).await?;
130         }
131         HdcCommand::KernelCheckServer => {
132             check_server_task(task_info).await?;
133         }
134         _ => {
135             hdc::info!("get unknown command {:#?}", task_info.command);
136             return Err(Error::new(ErrorKind::Other, "command not found"));
137         }
138     }
139     Ok(())
140 }
141 
142 async fn channel_forward_task(task_info: TaskInfo) -> io::Result<()> {
143     let session_id =
144         get_valid_session_id(task_info.connect_key.clone(), task_info.channel_id).await?;
145     let payload = task_info.params[1..].join(" ").into_bytes();
146     match task_info.command {
147         HdcCommand::ForwardInit => {
148             let mut task = HdcForward::new(session_id, task_info.channel_id, true);
149             task.transfer.server_or_daemon = true;
150             ForwardTaskMap::update(session_id, task_info.channel_id, task).await;
151             forward::command_dispatch(
152                 session_id,
153                 task_info.channel_id,
154                 task_info.command,
155                 payload.as_slice(),
156                 payload.len() as u16,
157             )
158             .await;
159             return Ok(());
160         }
161         _ => {
162             hdc::warn!("channel_forward_task, other commands");
163         }
164     }
165     Ok(())
166 }
167 
168 async fn channel_forward_remove(task_info: TaskInfo, forward_or_reverse: bool) -> io::Result<()> {
169     let task_string = task_info.params[2..].join(" ").clone();
170     let session_id =
171         get_valid_session_id(task_info.connect_key.clone(), task_info.channel_id).await?;
172     hdc::info!(
173         "channel_forward_remove task_string:{}, session_id:{}",
174         task_string,
175         session_id
176     );
177     let _result =
178         forward::HdcForwardInfoMap::remove_forward(task_string.clone(), forward_or_reverse).await;
179     hdc::info!("channel_forward_remove remove result:{}", _result);
180     if !_result {
181         let message_str = format!("Remove forward ruler failed, ruler is not exist {}", task_string);
182         let _ = transfer::send_channel_msg(
183             task_info.channel_id,
184             transfer::EchoLevel::FAIL,
185             message_str,
186         )
187         .await;
188         transfer::TcpMap::end(task_info.channel_id).await;
189         return Ok(());
190     }
191     let forward_channel_id = forward::ForwardTaskMap::get_channel_id(session_id, task_string.clone()).await;
192     if let Some(_channel_id) = forward_channel_id {
193         forward::free_channel_task(session_id, _channel_id).await;
194     }
195     let message_str = format!("Remove forward ruler success, ruler:{}", task_string);
196     send_channel_data(
197         task_info.channel_id,
198         message_str.as_bytes().to_vec(),
199     )
200     .await;
201     transfer::TcpMap::end(task_info.channel_id).await;
202     Ok(())
203 }
204 
205 async fn channel_forward_list(task_info: TaskInfo, forward_or_reverse: bool) -> io::Result<()> {
206     let mut result = forward::HdcForwardInfoMap::get_all_forward_infos().await;
207     if result.is_empty() {
208         send_channel_data(task_info.channel_id, "[Empty]".as_bytes().to_vec()).await;
209         transfer::TcpMap::end(task_info.channel_id).await;
210         return Ok(());
211     }
212     for item in &mut result {
213         let connect_key = ConnectMap::get_connect_key(item.session_id).await;
214         if let Some(key) = connect_key {
215             item.connect_key = key.clone();
216         }
217     }
218 
219     let mut result_str = String::new();
220     for info in result {
221         if info.forward_direction != forward_or_reverse {
222             continue;
223         }
224         let task_string = info.task_string[2..].to_string();
225         let forward_str = if info.forward_direction {
226             "[Forward]".to_string()
227         } else {
228             "[Reverse]".to_string()
229         };
230         let line = format!(
231             "{}    {}    {}\n",
232             info.connect_key, task_string, forward_str
233         );
234         result_str.push_str(&line);
235     }
236     send_channel_data(task_info.channel_id, result_str.as_bytes().to_vec()).await;
237     transfer::TcpMap::end(task_info.channel_id).await;
238     Ok(())
239 }
240 
241 async fn channel_jdwp_task(task_info: TaskInfo) -> io::Result<()> {
242     let session_id =
243         get_valid_session_id(task_info.connect_key.clone(), task_info.channel_id).await?;
244     let mut payload = Vec::<u8>::new();
245     if task_info.params.len() >= 2 && task_info.params[1].starts_with('-') && task_info.params[1].len() >= 2 {
246         payload = task_info.params[1][1..].as_bytes().to_vec();
247     }
248     transfer::put(
249         session_id,
250         TaskMessage {
251             channel_id: task_info.channel_id,
252             command: task_info.command,
253             payload,
254         },
255     )
256         .await;
257     Ok(())
258 }
259 
260 async fn channel_hilog_task(task_info: TaskInfo) -> io::Result<()> {
261     let session_id =
262         get_valid_session_id(task_info.connect_key.clone(), task_info.channel_id).await?;
263     let payload = if task_info.params.len() > 1 && task_info.params[1] == "-h" {
264         vec![104]
265     } else {
266         vec![0]
267     };
268     transfer::put(
269         session_id,
270         TaskMessage {
271             channel_id: task_info.channel_id,
272             command: HdcCommand::UnityHilog,
273             payload,
274         },
275     )
276     .await;
277     Ok(())
278 }
279 
280 async fn channel_bug_report_task(task_info: TaskInfo) -> io::Result<()> {
281     let session_id =
282         get_valid_session_id(task_info.connect_key.clone(), task_info.channel_id).await?;
283     transfer::put(
284         session_id,
285         TaskMessage {
286             channel_id: task_info.channel_id,
287             command: HdcCommand::UnityBugreportInit,
288             payload: vec![],
289         },
290     )
291     .await;
292     Ok(())
293 }
294 
295 async fn channel_file_task(task_info: TaskInfo) -> io::Result<()> {
296     let session_id =
297         get_valid_session_id(task_info.connect_key.clone(), task_info.channel_id).await?;
298     let payload = task_info.params.join(" ").into_bytes();
299     match task_info.command {
300         HdcCommand::AppInit | HdcCommand::AppUninstall => {
301             match HostAppTaskMap::exist(session_id, task_info.channel_id).await {
302                 Ok(true) => {}
303                 Ok(false) => {
304                     HostAppTaskMap::put(
305                         session_id,
306                         task_info.channel_id,
307                         HostAppTask::new(session_id, task_info.channel_id),
308                     )
309                     .await;
310                 }
311                 Err(err) => {
312                     return Err(io::Error::new(
313                         io::ErrorKind::Other,
314                         format!("call HostAppTaskMap::exist failed, {err:?}"),
315                     ));
316                 }
317             }
318             let _ = host_app::command_dispatch(session_id, task_info.channel_id, task_info.command, &payload) .await;
319         }
320 
321         HdcCommand::FileCheck | HdcCommand::FileInit => {
322             if !FileTaskMap::exsit(session_id, task_info.channel_id).await {
323                 let mut task = HdcFile::new(session_id, task_info.channel_id);
324                 task.transfer.server_or_daemon = true;
325                 FileTaskMap::put(session_id, task_info.channel_id, task).await;
326             }
327             hdcfile::command_dispatch(
328                 session_id,
329                 task_info.channel_id,
330                 task_info.command,
331                 &payload,
332                 payload.len() as u16,
333             )
334             .await;
335             return Ok(());
336         }
337         HdcCommand::FileBegin | HdcCommand::FileData | HdcCommand::FileFinish => {
338             hdcfile::command_dispatch(
339                 session_id,
340                 task_info.channel_id,
341                 task_info.command,
342                 &payload,
343                 payload.len() as u16,
344             )
345             .await;
346             return Ok(());
347         }
348         _ => {
349             hdc::info!("other tasks, payload is {:#?}", payload);
350         }
351     }
352     Ok(())
353 }
354 
355 async fn send_to_daemon(task_info: TaskInfo, _cmd: HdcCommand, param_start_idx: usize, async_flag: bool) -> io::Result<()> {
356     let session_id =
357         get_valid_session_id(task_info.connect_key.clone(), task_info.channel_id).await?;
358     hdc::info!("task_info params is {:?}", task_info);
359     transfer::put(
360         session_id,
361         TaskMessage {
362             channel_id: task_info.channel_id,
363             command: _cmd,
364             payload: task_info.params[param_start_idx..].join(" ").into_bytes(),
365         },
366     )
367     .await;
368     if async_flag {
369         transfer::TcpMap::end(task_info.channel_id).await;
370     }
371     Ok(())
372 }
373 
374 async fn channel_unity_task(task_info: TaskInfo) -> io::Result<()> {
375     let session_id = match ConnectMap::get_session_id(task_info.connect_key.clone()).await {
376         Some(seid) => seid,
377         None => return Err(Error::new(ErrorKind::Other, "session not found")),
378     };
379     let cmd = task_info.params[1..]
380         .iter()
381         .map(|s| s.trim_end_matches('\0'))
382         .collect::<Vec<_>>()
383         .join(" ")
384         .into_bytes();
385     transfer::put(
386         session_id,
387         TaskMessage {
388             channel_id: task_info.channel_id,
389             command: task_info.command,
390             payload: cmd,
391         },
392     )
393     .await;
394     Ok(())
395 }
396 
397 async fn channel_shell_task(task_info: TaskInfo) -> io::Result<()> {
398     let session_id =
399         get_valid_session_id(task_info.connect_key.clone(), task_info.channel_id).await?;
400     match task_info.command {
401         HdcCommand::UnityExecute => {
402             let cmd = task_info.params[1..]
403                 .iter()
404                 .map(|s| s.trim_end_matches('\0'))
405                 .collect::<Vec<_>>()
406                 .join(" ")
407                 .into_bytes();
408             transfer::put(
409                 session_id,
410                 TaskMessage {
411                     channel_id: task_info.channel_id,
412                     command: task_info.command,
413                     payload: cmd,
414                 },
415             )
416             .await;
417         }
418         HdcCommand::ShellInit => {
419             transfer::put(
420                 session_id,
421                 TaskMessage {
422                     channel_id: task_info.channel_id,
423                     command: task_info.command,
424                     payload: vec![0],
425                 },
426             )
427             .await;
428         }
429         HdcCommand::ShellData => {
430             let payload = task_info.params.join("").into_bytes();
431             transfer::put(
432                 session_id,
433                 TaskMessage {
434                     channel_id: task_info.channel_id,
435                     command: task_info.command,
436                     payload,
437                 },
438             )
439             .await;
440         }
441         _ => {}
442     }
443 
444     Ok(())
445 }
446 
447 async fn channel_connect_task(task_info: TaskInfo) -> io::Result<()> {
448     let connect_key = task_info.params[1].trim_end_matches('\0').to_string();
449     if ConnectMap::get(connect_key.clone()).await.is_some() {
450         let ret = transfer::send_channel_msg(
451             task_info.channel_id,
452             transfer::EchoLevel::INFO,
453             "Target is connected, repeat operation".to_string(),
454         )
455         .await;
456         transfer::TcpMap::end(task_info.channel_id).await;
457         return ret;
458     }
459     start_tcp_daemon_session(connect_key, &task_info).await
460 }
461 
462 pub async fn usb_handle_deamon(ptr: u64, mut rx: mpsc::BoundedReceiver<(TaskMessage, u32)>, session_id: u32, connect_key: String) -> io::Result<()> {
463     loop {
464         match rx.recv().await {
465             Ok((task_message, _index)) => {
466                 hdc::debug!(
467                     "in usb_handle_deamon, recv cmd: {:#?}, payload len: {}",
468                     task_message.command,
469                     task_message.payload.len(),
470                 );
471                 if let Err(e) = session_task_dispatch(task_message, session_id, connect_key.clone()).await {
472                     hdc::error!("dispatch task failed: {}", e.to_string());
473                 }
474             }
475             Err(e) => {
476                 hdc::warn!("unpack task failed: {}", e.to_string());
477                 ConnectMap::remove(connect_key.clone()).await;
478                 host_usb::on_device_connected(ptr, connect_key, false);
479                 return Err(Error::new(ErrorKind::Other, "recv error"));
480             }
481         };
482     }
483 }
484 
485 pub async fn start_usb_device_loop(ptr: u64, connect_key: String) {
486     let session_id = utils::get_pseudo_random_u32();
487     let wr = host_usb::HostUsbWriter {
488         connect_key: connect_key.clone(),
489         ptr,
490     };
491     host_usb::HostUsbMap::start(session_id, wr).await;
492     let rx = host_usb::start_recv(ptr, connect_key.clone(), session_id);
493     let channel_id = utils::get_pseudo_random_u32();
494     hdc::info!("generate new session {} channel {}", session_id, channel_id);
495     start_handshake_with_daemon(connect_key.clone(), session_id, channel_id, ConnectType::HostUsb(connect_key.clone())).await;
496     let _ = ylong_runtime::spawn(usb_handle_deamon(ptr, rx, session_id, connect_key)).await;
497 }
498 
499 async fn start_tcp_daemon_session(connect_key: String, task_info: &TaskInfo) -> io::Result<()> {
500     match TcpStream::connect(connect_key.clone()).await {
501         Err(_) => {
502             let ret = transfer::send_channel_msg(
503                 task_info.channel_id,
504                 transfer::EchoLevel::FAIL,
505                 "Connect to daemon failed".to_string(),
506             )
507             .await;
508             transfer::TcpMap::end(task_info.channel_id).await;
509             ret
510         }
511         Ok(stream) => {
512             let session_id = utils::get_pseudo_random_u32();
513             let (rd, wr) = stream.into_split();
514             transfer::TcpMap::start(session_id, wr).await;
515 
516             start_handshake_with_daemon(connect_key.clone(), session_id, task_info.channel_id, ConnectType::Tcp).await;
517             ylong_runtime::spawn(tcp_handle_deamon(rd, session_id, connect_key));
518             transfer::send_channel_msg(
519                 task_info.channel_id,
520                 transfer::EchoLevel::INFO,
521                 "Connect OK".to_string(),
522             )
523                 .await?;
524             transfer::TcpMap::end(task_info.channel_id).await;
525             Ok(())
526         }
527     }
528 }
529 
530 async fn channel_list_targets_task(task_info: TaskInfo) -> io::Result<()> {
531     let is_full = task_info.params.contains(&"-v".to_string());
532     let target_list = ConnectMap::get_list(is_full).await;
533     let msg = if target_list.is_empty() {
534         "[Empty]".to_string()
535     } else {
536         target_list.join("\n")
537     };
538     transfer::send_channel_msg(task_info.channel_id, transfer::EchoLevel::RAW, msg).await?;
539     transfer::TcpMap::end(task_info.channel_id).await;
540     Ok(())
541 }
542 
543 // check if any daemon connected and send the message to client for wait
544 async fn channel_wait_for_any(task_info: TaskInfo) -> io::Result<()> {
545     let target_list = ConnectMap::get_list(false).await;
546     if target_list.is_empty() {
547         hdc::info!("No any connected target");
548         let msg = "No connected target".to_string();
549         transfer::send_channel_msg(task_info.channel_id, transfer::EchoLevel::RAW, msg).await?;
550     } else if task_info.connect_key == "any" {
551         hdc::info!("Wait for connected target any");
552         let msg = "Wait for connected target any get ".to_string() + target_list[0].as_str();
553         transfer::send_channel_msg(task_info.channel_id, transfer::EchoLevel::RAW, msg).await?;
554         transfer::TcpMap::end(task_info.channel_id).await;
555     } else {
556         // wait for special connectkey
557         if target_list
558             .iter()
559             .any(|connect_key| connect_key == &task_info.connect_key)
560         {
561             hdc::info!("Wait for connected target is {}", task_info.connect_key);
562             let msg = "Wait for connected target is ".to_string() + task_info.connect_key.as_str();
563             transfer::send_channel_msg(task_info.channel_id, transfer::EchoLevel::RAW, msg).await?;
564             transfer::TcpMap::end(task_info.channel_id).await;
565         } else {
566             hdc::info!("No {} connected target ", task_info.connect_key);
567             let msg = "No connected target".to_string();
568             transfer::send_channel_msg(task_info.channel_id, transfer::EchoLevel::RAW, msg).await?;
569         }
570     }
571     Ok(())
572 }
573 
574 async fn tcp_handle_deamon(
575     mut rd: SplitReadHalf,
576     session_id: u32,
577     connect_key: String,
578 ) -> io::Result<()> {
579     loop {
580         match transfer::tcp::unpack_task_message(&mut rd).await {
581             Ok(task_message) => {
582                 // hdc::info!(
583                 //     "in tcp_handle_deamon, recv cmd: {:#?}, payload len: {}",
584                 //     task_message.command,
585                 //     task_message.payload.len(),
586                 // );
587                 if let Err(e) = session_task_dispatch(task_message, session_id, connect_key.clone()).await {
588                     hdc::error!("dispatch task failed: {}", e.to_string());
589                 }
590             }
591             Err(e) => {
592                 hdc::warn!("unpack task failed: {}", e.to_string());
593                 ConnectMap::remove(connect_key).await;
594                 return Err(e);
595             }
596         };
597     }
598 }
599 
600 async fn session_task_dispatch(task_message: TaskMessage, session_id: u32, connect_key: String) -> io::Result<()> {
601     match task_message.command {
602         HdcCommand::KernelEcho => {
603             let data = task_message.payload[1..].to_vec();
604             let level_result = transfer::EchoLevel::convert_from_message_level(task_message.payload[0]);
605             match level_result {
606                 Ok(level) => {
607                     if let Ok(str) = String::from_utf8(data) {
608                         if let Err(e) = transfer::send_channel_msg(
609                             task_message.channel_id,
610                             level,
611                             str,
612                         ).await {
613                             hdc::error!("echo to client failed: {}", e.to_string());
614                         };
615                     }
616                 }
617                 Err(_) => {
618                     return Err(Error::new(ErrorKind::Other, "message level invalid."));
619                 }
620             }
621         }
622         HdcCommand::KernelEchoRaw | HdcCommand::UnityBugreportData => {
623             transfer::send_channel_data(task_message.channel_id, task_message.payload).await;
624         }
625         HdcCommand::KernelChannelClose => {
626             session_channel_close(task_message, session_id).await?;
627         }
628         HdcCommand::KernelHandshake => {
629             handshake_task(task_message, session_id, connect_key).await?;
630         }
631         HdcCommand::AppBegin
632         | HdcCommand::AppData
633         | HdcCommand::AppFinish
634         | HdcCommand::FileInit
635         | HdcCommand::FileBegin
636         | HdcCommand::FileData
637         | HdcCommand::FileCheck
638         | HdcCommand::FileFinish => {
639             session_file_task(task_message, session_id).await?;
640         }
641         HdcCommand::ForwardCheck
642         | HdcCommand::ForwardActiveMaster
643         | HdcCommand::ForwardActiveSlave
644         | HdcCommand::ForwardCheckResult
645         | HdcCommand::ForwardData => {
646             if HdcCommand::ForwardCheck == task_message.command {
647                 let mut task = HdcForward::new(session_id, task_message.channel_id, true);
648                 task.transfer.server_or_daemon = true;
649                 ForwardTaskMap::update(session_id, task_message.channel_id, task).await;
650             }
651             session_forward_task(task_message, session_id).await?;
652         }
653         HdcCommand::ForwardSuccess => {
654             session_forward_success(task_message, session_id).await?;
655         }
656         _ => {}
657     }
658     Ok(())
659 }
660 
661 async fn session_forward_task(task_message: TaskMessage, session_id: u32) -> io::Result<()> {
662     forward::command_dispatch(
663         session_id,
664         task_message.channel_id,
665         task_message.command,
666         &task_message.payload,
667         task_message.payload.len() as u16,
668     )
669     .await;
670     Ok(())
671 }
672 
673 async fn session_forward_success(task_message: TaskMessage, session_id: u32) -> io::Result<()> {
674     let _ = forward::on_forward_success(task_message.clone(), session_id).await;
675     Ok(())
676 }
677 
678 async fn session_file_task(task_message: TaskMessage, session_id: u32) -> io::Result<()> {
679     match task_message.command {
680         HdcCommand::AppBegin | HdcCommand::AppFinish => {
681             let _ = host_app::command_dispatch(
682                 session_id,
683                 task_message.channel_id,
684                 task_message.command,
685                 &task_message.payload,
686             )
687             .await;
688             return Ok(());
689         }
690         HdcCommand::FileCheck | HdcCommand::FileInit => {
691             if !FileTaskMap::exsit(session_id, task_message.channel_id).await {
692                 let mut task = HdcFile::new(session_id, task_message.channel_id);
693                 task.transfer.server_or_daemon = true;
694                 FileTaskMap::put(session_id, task_message.channel_id, task).await;
695             }
696 
697             hdcfile::command_dispatch(
698                 session_id,
699                 task_message.channel_id,
700                 task_message.command,
701                 &task_message.payload,
702                 task_message.payload.len() as u16,
703             )
704             .await;
705             return Ok(());
706         }
707         HdcCommand::FileBegin | HdcCommand::FileData | HdcCommand::FileFinish => {
708             hdcfile::command_dispatch(
709                 session_id,
710                 task_message.channel_id,
711                 task_message.command,
712                 &task_message.payload,
713                 task_message.payload.len() as u16,
714             )
715             .await;
716             return Ok(());
717         }
718         _ => {
719             hdc::info!("other tasks");
720         }
721     }
722     /* ActionType 未定义,临时屏蔽
723     let channel_id = task_message.channel_id;
724     let command = task_message.command;
725 
726     let opt = admin_session(ActionType::Query(session_id)).await;
727     if opt.is_none() {
728         admin_session(ActionType::Add(HdcSession::new(
729             session_id,
730             String::from(""),
731             NodeType::Server,
732             ConnectType::Tcp,
733         )))
734         .await;
735     }
736     let opt = admin_session(ActionType::Query(session_id)).await;
737 
738     let arc = opt.unwrap();
739     let mut session = arc.lock().await;
740     if let std::collections::hash_map::Entry::Vacant(e) = session.map_tasks.entry(channel_id) {
741         match command {
742             HdcCommand::AppBegin => {
743                 let mut task = HostAppTask::new(session_id, channel_id);
744                 task.transfer.server_or_daemon = true;
745                 e.insert(Arc::new(Mutex::new(task)));
746             }
747             HdcCommand::FileInit => {
748                 let mut task = HdcFile::new(session_id, channel_id);
749                 task.transfer.server_or_daemon = true;
750                 e.insert(Arc::new(Mutex::new(task)));
751             }
752             _ => {
753                 hdc::info!("other tasks");
754             }
755         }
756     }
757     let task = session.map_tasks.get(&channel_id).unwrap();
758     let task_ = &mut task.lock().await;
759     let cmd = task_message.payload;
760     let _ = task_.command_dispatch(command, &cmd[..], cmd.len() as u16);
761     */
762     Ok(())
763 }
764 
765 pub async fn session_channel_close(task_message: TaskMessage, session_id: u32) -> io::Result<()> {
766     if task_message.payload[0] > 0 {
767         let message = TaskMessage {
768             channel_id: task_message.channel_id,
769             command: HdcCommand::KernelChannelClose,
770             payload: vec![task_message.payload[0] - 1],
771         };
772         transfer::put(session_id, message).await;
773     }
774     hdc::info!("recv channel close {}", task_message.channel_id);
775     transfer::TcpMap::end(task_message.channel_id).await;
776     Ok(())
777 }
778 
779 async fn check_server_task(task_info: TaskInfo) -> io::Result<()> {
780     let payload = [
781         u16::to_le_bytes(HdcCommand::KernelCheckServer as u16).as_slice(),
782         get_version().as_bytes(),
783     ]
784     .concat();
785     transfer::send_channel_data(task_info.channel_id, payload).await;
786     Ok(())
787 }
788 
789 #[allow(unused)]
790 #[derive(Default)]
791 pub enum ConnectStatus {
792     #[default]
793     Unknown = 0,
794     Ready,
795     Connected,
796     Offline,
797 }
798 
799 #[allow(unused)]
800 #[derive(Default)]
801 pub struct DaemonInfo {
802     pub session_id: u32,
803     pub conn_type: ConnectType,
804     pub conn_status: ConnectStatus,
805     pub dev_name: String,
806     pub version: String,
807     pub emg_msg: String,
808     pub daemon_auth_status: String,
809 }
810 
811 type DaemonInfo_ = Arc<Mutex<DaemonInfo>>;
812 type ConnectMap_ = Arc<RwLock<HashMap<String, DaemonInfo_>>>;
813 
814 pub struct ConnectMap {}
815 impl ConnectMap {
get_instancenull816     fn get_instance() -> ConnectMap_ {
817         static mut CONNECT_TYPE_MAP: Option<ConnectMap_> = None;
818         unsafe {
819             CONNECT_TYPE_MAP
820                 .get_or_insert_with(|| Arc::new(RwLock::new(HashMap::new())))
821                 .clone()
822         }
823     }
824 
825     async fn remove(connect_key: String) {
826         let instance = Self::get_instance();
827         let mut map = instance.write().await;
828         map.remove(&connect_key);
829     }
830 
831     pub async fn put(connect_key: String, daemon_info: DaemonInfo) {
832         let instance = Self::get_instance();
833         let mut map = instance.write().await;
834         map.insert(connect_key, Arc::new(Mutex::new(daemon_info)));
835     }
836 
837     pub async fn update(connect_key: String,
838                         conn_status: crate::task::ConnectStatus,
839                         version: String,
840                         dev_name: String,
841                         emg_msg: String,
842                         daemon_auth_status: String) -> bool {
843         let instance = Self::get_instance();
844         let mut map = instance.write().await;
845         if let Some(item) = map.get_mut(&connect_key) {
846             let info = &mut *item.lock().await;
847             info.conn_status = conn_status;
848             info.version = version;
849             info.dev_name = dev_name;
850             info.emg_msg = emg_msg;
851             info.daemon_auth_status = daemon_auth_status;
852             true
853         } else {
854             false
855         }
856     }
857 
858     async fn get(connect_key: String) -> Option<DaemonInfo_> {
859         let instance = Self::get_instance();
860         let map = instance.read().await;
861         let key = if connect_key.as_str() == "any" && map.keys().len() == 1 {
862             map.keys().last().unwrap()
863         } else {
864             &connect_key
865         };
866         map.get(key).cloned()
867     }
868 
869     pub async fn get_list(is_full: bool) -> Vec<String> {
870         let instance = Self::get_instance();
871         let map = instance.read().await;
872         let mut list = vec![];
873         for (key, info) in map.iter() {
874             if is_full {
875                 let mut output = vec![key.as_str()];
876                 let guard = info.lock().await;
877                 output.push(match guard.conn_type {
878                     ConnectType::Tcp => "TCP",
879                     ConnectType::Usb(_) => "USB",
880                     ConnectType::Uart => "UART",
881                     ConnectType::Bt => "BT",
882                     ConnectType::HostUsb(_) => "HOSTUSB",
883                     ConnectType::Bridge => "BRIDGE",
884                 });
885                 if guard.daemon_auth_status == DAEOMN_UNAUTHORIZED {
886                     output.push("Unauthorized");
887                 }  else {
888                     output.push(match guard.conn_status {
889                         ConnectStatus::Connected => "Connected",
890                         ConnectStatus::Ready => "Ready",
891                         ConnectStatus::Offline => "Offline",
892                         ConnectStatus::Unknown => "Unknown",
893                     });
894                 }
895                 if guard.dev_name.is_empty() {
896                     output.push("unknown...");
897                 } else {
898                     let dev_name = guard.dev_name.as_str();
899                     output.push(dev_name);
900                 };
901                 output.push("hdc");
902                 list.push(output.join("\t"));
903             } else {
904                 let mut output = vec![key.as_str()];
905                 let guard = info.lock().await;
906                 if guard.daemon_auth_status == DAEOMN_UNAUTHORIZED {
907                     output.push("Unauthorized");
908                 }
909                 list.push(output.join("\t"));
910             }
911         }
912         list
913     }
914 
915     pub async fn get_session_id(connect_key: String) -> Option<u32> {
916         let daemon_info = Self::get(connect_key).await?;
917         let guard = daemon_info.lock().await;
918         Some(guard.session_id)
919     }
920 
921     pub async fn get_connect_key(session_id: u32) -> Option<String> {
922         let instance = Self::get_instance();
923         let map = instance.read().await;
924         for (key, info) in map.iter() {
925             let lock = info.lock().await;
926             if lock.session_id == session_id {
927                 return Some(key.clone());
928             }
929         }
930         None
931     }
932 }
933 
934 async fn get_valid_session_id(connect_key: String, channel_id: u32) -> io::Result<u32> {
935     match ConnectMap::get_session_id(connect_key).await {
936         Some(session_id) => Ok(session_id),
937         None => {
938             transfer::send_channel_msg(
939                 channel_id,
940                 transfer::EchoLevel::FAIL,
941                 "Targets not found, please check the connect-key.".to_string(),
942             )
943             .await?;
944             transfer::TcpMap::end(channel_id).await;
945             Err(Error::new(ErrorKind::Other, "session not found"))
946         }
947     }
948 }
949