• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 hdc::common::base::Base;
16 use hdc::common::filemanager::FileManager;
17 use hdc::common::hdcfile;
18 use hdc::common::hdctransfer::{self, HdcTransferBase};
19 use hdc::config::HdcCommand;
20 use hdc::config::TaskMessage;
21 use hdc::config::TRANSFER_FUNC_NAME;
22 use hdc::config::{self, INSTALL_TAR_MAX_CNT};
23 use hdc::serializer::serialize::Serialization;
24 use hdc::transfer;
25 use hdc::transfer::EchoLevel;
26 use hdc::utils;
27 use std::collections::HashMap;
28 use std::io;
29 use std::path::PathBuf;
30 use std::sync::Arc;
31 use ylong_runtime::sync::Mutex;
32 #[cfg(feature = "host")]
33 extern crate ylong_runtime_static as ylong_runtime;
34 use hdc::tar::compress::Compress;
35 
36 pub struct HostAppTask {
37     pub transfer: HdcTransferBase,
38     pub printed_msg_len: usize,
39 }
40 
41 impl HostAppTask {
42     ///  complie failed ,associated function `new` is never used
new(_session_id: u32, _channel_id: u32) -> Self43     pub fn new(_session_id: u32, _channel_id: u32) -> Self {
44         Self {
45             transfer: HdcTransferBase::new(_session_id, _channel_id),
46             printed_msg_len: 0,
47         }
48     }
49 }
50 
51 type HostAppTask_ = Arc<Mutex<HostAppTask>>;
52 type HostAppTaskMap_ = Arc<Mutex<HashMap<(u32, u32), HostAppTask_>>>;
53 
54 pub struct HostAppTaskMap {}
55 impl HostAppTaskMap {
get_instance() -> HostAppTaskMap_56     fn get_instance() -> HostAppTaskMap_ {
57         static mut HOSTAPPTASKMAP: Option<HostAppTaskMap_> = None;
58         unsafe {
59             HOSTAPPTASKMAP
60                 .get_or_insert_with(|| Arc::new(Mutex::new(HashMap::new())))
61                 .clone()
62         }
63     }
64 
put(session_id: u32, channel_id: u32, host_app_task: HostAppTask)65     pub async fn put(session_id: u32, channel_id: u32, host_app_task: HostAppTask) {
66         let arc_map = Self::get_instance();
67         let mut map = arc_map.lock().await;
68         map.insert(
69             (session_id, channel_id),
70             Arc::new(Mutex::new(host_app_task)),
71         );
72     }
73 
exist(session_id: u32, channel_id: u32) -> Result<bool, ()>74     pub async fn exist(session_id: u32, channel_id: u32) -> Result<bool, ()> {
75         let arc_map = Self::get_instance();
76         let map = arc_map.lock().await;
77         Ok(map.contains_key(&(session_id, channel_id)))
78     }
79 
remove(session_id: u32, channel_id: u32) -> Option<HostAppTask_>80     pub async fn remove(session_id: u32, channel_id: u32) -> Option<HostAppTask_> {
81         let arc_map = Self::get_instance();
82         let mut map = arc_map.lock().await;
83         map.remove(&(session_id, channel_id))
84     }
85 
get(session_id: u32, channel_id: u32) -> Option<HostAppTask_>86     pub async fn get(session_id: u32, channel_id: u32) -> Option<HostAppTask_> {
87         let arc_map = Self::get_instance();
88         let map = arc_map.lock().await;
89         let Some(arc_task) = map.get(&(session_id, channel_id)) else {
90             return None;
91         };
92         Some(arc_task.clone())
93     }
94 }
95 
send_to_client(channel_id: u32, level: EchoLevel, message: String) -> io::Result<()>96 pub async fn send_to_client(channel_id: u32, level: EchoLevel, message: String) -> io::Result<()> {
97     transfer::send_channel_msg(channel_id, level, message).await
98 }
99 
echo_client(channel_id: u32, message: String) -> io::Result<()>100 pub async fn echo_client(channel_id: u32, message: String) -> io::Result<()> {
101     send_to_client(channel_id, EchoLevel::INFO, message).await
102 }
103 
check_install_continue( session_id: u32, channel_id: u32, mode_type: config::AppModeType, str: String, ) -> bool104 async fn check_install_continue(
105     session_id: u32,
106     channel_id: u32,
107     mode_type: config::AppModeType,
108     str: String,
109 ) -> bool {
110     let mut _mode_desc = String::from("");
111     match mode_type {
112         config::AppModeType::Install => _mode_desc = String::from("App install"),
113         config::AppModeType::UnInstall => _mode_desc = String::from("App uninstall"),
114     }
115     let Some(arc_task) = HostAppTaskMap::get(session_id, channel_id).await else {
116         hdc::error!("Get host app task failed");
117         return false;
118     };
119     let mut task = arc_task.lock().await;
120     let msg = str[task.printed_msg_len..].to_owned();
121     let message = format!(
122         "{} path:{}, queuesize:{}, msg:{}",
123         _mode_desc,
124         task.transfer.local_path.clone(),
125         task.transfer.task_queue.len(),
126         msg
127     );
128     task.printed_msg_len = str.len();
129     let _ = echo_client(channel_id, message).await;
130     if task.transfer.task_queue.is_empty() {
131         let _ = echo_client(channel_id, String::from("AppMod finish")).await;
132         task_finish(session_id, channel_id).await;
133         hdctransfer::close_channel(channel_id).await;
134         return false;
135     }
136     drop(task);
137     install_single(session_id, channel_id).await;
138     put_app_check(session_id, channel_id).await;
139     true
140 }
141 
do_app_uninstall(session_id: u32, channel_id: u32, _payload: &[u8])142 async fn do_app_uninstall(session_id: u32, channel_id: u32, _payload: &[u8]) {
143     let app_uninstall_message = TaskMessage {
144         channel_id,
145         command: HdcCommand::AppUninstall,
146         payload: _payload.to_vec(),
147     };
148     transfer::put(session_id, app_uninstall_message).await;
149 }
150 
do_app_finish(session_id: u32, channel_id: u32, _payload: &[u8]) -> bool151 async fn do_app_finish(session_id: u32, channel_id: u32, _payload: &[u8]) -> bool {
152     let mode = config::AppModeType::try_from(_payload[0]);
153     if let Ok(mode_type) = mode {
154         let str = match String::from_utf8(_payload[2..].to_vec()) {
155             Ok(str) => str,
156             Err(err) => {
157                 hdc::error!("do_app_finish from_utf8 error, {err}");
158                 return false;
159             }
160         };
161         return check_install_continue(session_id, channel_id, mode_type, str).await;
162     }
163     false
164 }
165 
dir_to_tar(dir_path: PathBuf) -> Result<String, String>166 fn dir_to_tar(dir_path: PathBuf) -> Result<String, String> {
167     let mut compress = Compress::new();
168     compress.updata_prefix(dir_path.clone());
169     if let Err(err) = compress.add_path(&dir_path) {
170         return Err(format!("add path fail, {err}"));
171     }
172     compress.updata_max_count(INSTALL_TAR_MAX_CNT);
173 
174     let tar_name = utils::get_pseudo_random_u32().to_string() + ".tar";
175     let tar_path = std::env::temp_dir().join(tar_name);
176     match compress.compress(tar_path.clone()) {
177         Ok(_) => Ok(tar_path.display().to_string()),
178         Err(err) => Err(format!("compress {} fial, {}", tar_path.display(), err)),
179     }
180 }
181 
task_finish(session_id: u32, channel_id: u32)182 async fn task_finish(session_id: u32, channel_id: u32) {
183     hdctransfer::transfer_task_finish(channel_id, session_id).await
184 }
185 
put_app_check(session_id: u32, channel_id: u32)186 async fn put_app_check(session_id: u32, channel_id: u32) {
187     let Some(arc_task) = HostAppTaskMap::get(session_id, channel_id).await else {
188         hdc::error!("Get host app task failed");
189         return;
190     };
191     let task = arc_task.lock().await;
192     let file_check_message = TaskMessage {
193         channel_id,
194         command: HdcCommand::AppCheck,
195         payload: task.transfer.transfer_config.serialize(),
196     };
197     transfer::put(session_id, file_check_message).await
198 }
199 
install_single(session_id: u32, channel_id: u32)200 async fn install_single(session_id: u32, channel_id: u32) {
201     let Some(arc_task) = HostAppTaskMap::get(session_id, channel_id).await else {
202         hdc::error!("Get host app task failed");
203         return;
204     };
205     let mut task = arc_task.lock().await;
206     match task.transfer.task_queue.pop() {
207         Some(loc_path) => task.transfer.local_path = loc_path,
208         None => {
209             hdc::error!("Get local path is None");
210             task_finish(session_id, channel_id).await;
211             return;
212         }
213     }
214     let local_path = task.transfer.local_path.clone();
215     let mut file_manager = FileManager::new(local_path.clone());
216     let (open_result, error_msg) = file_manager.open();
217     if open_result {
218         let file_size = file_manager.file_size();
219         task.transfer.transfer_config.file_size = file_size;
220         task.transfer.file_size = file_size;
221         task.transfer.transfer_config.optional_name = utils::get_pseudo_random_u32().to_string();
222         if let Some(index) = local_path.rfind('.') {
223             let str = local_path.as_str();
224             task.transfer
225                 .transfer_config
226                 .optional_name
227                 .push_str(&str[index..]);
228         }
229         // if config.hold_timestamp {}
230         task.transfer.transfer_config.path = task.transfer.remote_path.clone();
231     } else {
232         println!("other command {:#?}", error_msg);
233         task_finish(session_id, channel_id).await;
234     }
235 }
236 
init_install(session_id: u32, channel_id: u32, command: &String) -> bool237 async fn init_install(session_id: u32, channel_id: u32, command: &String) -> bool {
238     let (argv, argc) = Base::split_command_to_args(command);
239     if argc < 1 {
240         return false;
241     }
242 
243     let Some(arc_task) = HostAppTaskMap::get(session_id, channel_id).await else {
244         hdc::error!("Get host app task failed");
245         return false;
246     };
247     let mut task = arc_task.lock().await;
248     let mut i = 1usize;
249     let mut options = String::from("");
250     while i < argc as usize {
251         if argv[i] == "-cwd" {
252             if i + 1 < argc as usize {
253                 task.transfer.transfer_config.client_cwd = argv[i + 1].clone();
254                 i += 1;
255             }
256         } else if argv[i].starts_with('-') {
257             if !options.is_empty() {
258                 options.push(' ');
259             }
260             options.push_str(&argv[i].clone());
261         } else {
262             let mut path = argv[i].clone() as String;
263             path = Base::extract_relative_path(
264                 &task.transfer.transfer_config.client_cwd,
265                 path.as_str(),
266             );
267             if path.ends_with(".hap") || path.ends_with(".hsp") {
268                 task.transfer.task_queue.push(path.clone());
269             } else {
270                 match dir_to_tar(PathBuf::from(path)) {
271                     Ok(tar_file) => {
272                         hdc::info!("dir_to_tar success, path = {}", tar_file);
273                         task.transfer.task_queue.push(tar_file)
274                     }
275                     Err(err) => {
276                         hdc::error!("{}", err);
277                         return false;
278                     }
279                 }
280             }
281         }
282         i += 1;
283     }
284 
285     if task.transfer.task_queue.is_empty() {
286         return false;
287     }
288 
289     task.transfer.transfer_config.options = options.clone();
290     task.transfer.transfer_config.function_name = TRANSFER_FUNC_NAME.to_string();
291     task.transfer.is_master = true;
292     drop(task);
293     install_single(session_id, channel_id).await;
294 
295     true
296 }
297 
command_dispatch( session_id: u32, channel_id: u32, _command: HdcCommand, _payload: &[u8], _payload_size: u16, ) -> Result<bool, &str>298 pub async fn command_dispatch(
299     session_id: u32,
300     channel_id: u32,
301     _command: HdcCommand,
302     _payload: &[u8],
303     _payload_size: u16,
304 ) -> Result<bool, &str> {
305     match _command {
306         HdcCommand::AppInit => {
307             let s = String::from_utf8(_payload.to_vec());
308             match s {
309                 Ok(str) => {
310                     if !init_install(session_id, channel_id, &str).await {
311                         let message = "Not any installation package was found";
312                         let _ =
313                             send_to_client(channel_id, EchoLevel::FAIL, message.to_owned()).await;
314                         transfer::TcpMap::end(channel_id).await;
315                         return Ok(false);
316                     }
317                     hdcfile::wake_up_slaver(session_id, channel_id).await;
318                     put_app_check(session_id, channel_id).await
319                 }
320                 Err(e) => {
321                     println!("error {}", e);
322                 }
323             }
324         }
325         HdcCommand::AppBegin => {
326             let Some(arc_task) = HostAppTaskMap::get(session_id, channel_id).await else {
327                 hdc::error!("Get host app task failed");
328                 return Ok(false);
329             };
330             let task = arc_task.lock().await;
331             hdctransfer::transfer_begin(&task.transfer, HdcCommand::AppData).await;
332         }
333         HdcCommand::AppUninstall => {
334             let s = String::from_utf8(_payload.to_vec());
335             let mut options = String::from("");
336             match s {
337                 Ok(str) => {
338                     let (argv, argc) = Base::split_command_to_args(&str);
339                     if argc < 1 {
340                         return Ok(false);
341                     }
342                     options = argv[1..].join(" ");
343                 }
344                 Err(e) => {
345                     println!("error {}", e);
346                 }
347             }
348             do_app_uninstall(session_id, channel_id, options.as_bytes()).await;
349         }
350         HdcCommand::AppFinish => {
351             do_app_finish(session_id, channel_id, _payload).await;
352         }
353         _ => {
354             println!("other command");
355         }
356     }
357     Ok(true)
358 }
359