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::hdctransfer::{self, HdcTransferBase}; 18 use hdc::common::taskbase::TaskBase; 19 use hdc::config; 20 use hdc::config::HdcCommand; 21 use hdc::config::TaskMessage; 22 use hdc::config::TRANSFER_FUNC_NAME; 23 use hdc::serializer::serialize::Serialization; 24 use hdc::transfer; 25 use hdc::transfer::EchoLevel; 26 use hdc::utils; 27 use std::path::PathBuf; 28 29 pub struct HostAppTask { 30 pub transfer: HdcTransferBase, 31 } 32 33 impl HostAppTask { new(_session_id: u32, _channel_id: u32) -> Self34 pub fn new(_session_id: u32, _channel_id: u32) -> Self { 35 Self { 36 transfer: HdcTransferBase::new(_session_id, _channel_id), 37 } 38 } 39 get_sub_app_files_resurively(_path: &String) -> Vec<String>40 pub fn get_sub_app_files_resurively(_path: &String) -> Vec<String> { 41 let mut result = Vec::new(); 42 let dir_path = PathBuf::from(_path); 43 for entry in std::fs::read_dir(dir_path).unwrap() { 44 let path = entry.unwrap().path(); 45 let p = path.display().to_string(); 46 if p.ends_with(".hap") || p.ends_with(".hsp") { 47 result.push(p.clone()); 48 } else { 49 let mut sub_list = Self::get_sub_app_files_resurively(&p); 50 result.append(&mut sub_list); 51 } 52 } 53 result.sort(); 54 result 55 } 56 init_install(&mut self, command: &String) -> bool57 pub fn init_install(&mut self, command: &String) -> bool { 58 let (argv, argc) = Base::split_command_to_args(command); 59 if argc < 1 { 60 return false; 61 } 62 let mut i = 0usize; 63 let mut options = String::from(""); 64 while i < argc as usize { 65 if argv[i] == "-cwd" { 66 if i + 1 < argc as usize { 67 self.transfer.transfer_config.client_cwd = argv[i + 1].clone(); 68 i += 1; 69 } 70 } else if argv[i].starts_with("-") { 71 if !options.is_empty() { 72 options.push(' '); 73 } 74 options.push_str(&mut argv[i].clone()); 75 } else { 76 let mut path = argv[i].clone() as String; 77 path = Base::extract_relative_path( 78 &self.transfer.transfer_config.client_cwd, 79 path.as_str(), 80 ); 81 if path.ends_with(".hap") || path.ends_with(".hsp") { 82 self.transfer.task_queue.push(path.clone()); 83 } else { 84 let mut queue = Self::get_sub_app_files_resurively(&path); 85 self.transfer.task_queue.append(&mut queue); 86 } 87 } 88 i += 1; 89 } 90 91 if self.transfer.task_queue.is_empty() { 92 return false; 93 } 94 95 self.transfer.transfer_config.options = options.clone(); 96 self.transfer.transfer_config.function_name = TRANSFER_FUNC_NAME.to_string(); 97 98 self.transfer.is_master = true; 99 self.install_single(); 100 101 true 102 } 103 install_single(&mut self)104 fn install_single(&mut self) { 105 self.transfer.local_path = self.transfer.task_queue.pop().unwrap(); 106 let local_path = self.transfer.local_path.clone(); 107 let mut file_manager = FileManager::new(local_path.clone()); 108 let open_result = file_manager.open(); 109 if open_result { 110 let config = &mut self.transfer.transfer_config; 111 config.file_size = file_manager.file_size(); 112 self.transfer.file_size = config.file_size; 113 config.optional_name = utils::get_pseudo_random_u32().to_string(); 114 if let Some(index) = local_path.rfind('.') { 115 let str = local_path.as_str(); 116 config.optional_name.push_str(&str[index..]); 117 } 118 if config.hold_timestamp {} 119 config.path = self.transfer.remote_path.clone(); 120 } else { 121 self.task_finish(); 122 } 123 } 124 put_app_check(&mut self)125 fn put_app_check(&mut self) { 126 let file_check_message = TaskMessage { 127 channel_id: self.transfer.channel_id, 128 command: HdcCommand::AppCheck, 129 payload: self.transfer.transfer_config.serialize(), 130 }; 131 let send_msg_task = async { 132 transfer::put(self.transfer.session_id, file_check_message).await; 133 }; 134 ylong_runtime::block_on(send_msg_task); 135 } 136 do_app_finish(&mut self, _payload: &Vec<u8>) -> bool137 fn do_app_finish(&mut self, _payload: &Vec<u8>) -> bool { 138 let mode = config::AppModeType::try_from(_payload[0]); 139 if let Ok(mode_type) = mode { 140 let str = String::from_utf8(_payload[2..].to_vec()).unwrap(); 141 return self.check_install_continue(mode_type, str.clone()); 142 } 143 false 144 } 145 do_app_uninstall(&mut self, _payload: &Vec<u8>)146 fn do_app_uninstall(&mut self, _payload: &Vec<u8>) { 147 let app_uninstall_message = TaskMessage { 148 channel_id: self.transfer.channel_id, 149 command: HdcCommand::AppUninstall, 150 payload: _payload.to_vec(), 151 }; 152 let send_msg_task = async { 153 transfer::put(self.transfer.session_id, app_uninstall_message).await; 154 }; 155 ylong_runtime::block_on(send_msg_task); 156 } 157 check_install_continue(&mut self, mode_type: config::AppModeType, str: String) -> bool158 fn check_install_continue(&mut self, mode_type: config::AppModeType, str: String) -> bool { 159 let mut _mode_desc = String::from(""); 160 match mode_type { 161 config::AppModeType::Install => _mode_desc = String::from("App install"), 162 config::AppModeType::UnInstall => _mode_desc = String::from("App uninstall"), 163 } 164 let message = format!( 165 "{}, path:{}, queuesize:{}, msg:{}", 166 _mode_desc.clone(), 167 self.transfer.local_path.clone(), 168 self.transfer.task_queue.len(), 169 str.clone() 170 ); 171 self.echo_client(message); 172 if self.transfer.task_queue.is_empty() { 173 self.echo_client(String::from("AppMod finish")); 174 self.task_finish(); 175 hdctransfer::close_channel(self.channel_id()); 176 return false; 177 } 178 self.install_single(); 179 true 180 } 181 echo_client(&mut self, message: String)182 fn echo_client(&mut self, message: String) { 183 ylong_runtime::block_on(async { 184 let _ = transfer::send_channel_msg(self.channel_id(), EchoLevel::INFO, message).await; 185 }); 186 } 187 } 188 189 impl TaskBase for HostAppTask { command_dispatch( &mut self, _command: HdcCommand, _payload: &[u8], _payload_size: u16, ) -> bool190 fn command_dispatch( 191 &mut self, 192 _command: HdcCommand, 193 _payload: &[u8], 194 _payload_size: u16, 195 ) -> bool { 196 match _command { 197 HdcCommand::AppInit => { 198 let s = String::from_utf8(_payload.to_vec()); 199 match s { 200 Ok(str) => { 201 if self.init_install(&str) { 202 self.put_app_check(); 203 } 204 } 205 Err(e) => { 206 println!("error {}", e); 207 } 208 } 209 } 210 HdcCommand::AppBegin => { 211 hdctransfer::transfer_begin(&self.transfer, HdcCommand::AppData); 212 } 213 HdcCommand::AppUninstall => { 214 self.do_app_uninstall(&_payload.to_vec()); 215 } 216 HdcCommand::AppFinish => { 217 self.do_app_finish(&_payload.to_vec()); 218 } 219 _ => { 220 println!("other command"); 221 } 222 } 223 true 224 } 225 stop_task(&mut self)226 fn stop_task(&mut self) {} 227 ready_for_release(&mut self) -> bool228 fn ready_for_release(&mut self) -> bool { 229 true 230 } 231 channel_id(&self) -> u32232 fn channel_id(&self) -> u32 { 233 self.transfer.channel_id 234 } 235 task_finish(&self)236 fn task_finish(&self) { 237 hdctransfer::transfer_task_finish(self.transfer.channel_id, self.transfer.session_id); 238 } 239 } 240