1 // Copyright (C) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 use std::collections::HashMap; 15 use std::fs::File; 16 use std::os::fd::{IntoRawFd, RawFd}; 17 18 use ipc::parcel::MsgParcel; 19 use ipc::{IpcResult, IpcStatusCode}; 20 21 use crate::error::ErrorCode; 22 use crate::manage::account::GetOhosAccountUid; 23 use crate::manage::events::TaskManagerEvent; 24 use crate::service::permission::PermissionChecker; 25 use crate::service::RequestServiceStub; 26 use crate::task::config::{Action, CommonTaskConfig, Mode, NetworkConfig, TaskConfig, Version}; 27 use crate::task::ATOMIC_SERVICE; 28 use crate::utils::form_item::{FileSpec, FormItem}; 29 use crate::utils::query_calling_bundle; 30 31 impl RequestServiceStub { construct(&self, data: &mut MsgParcel, reply: &mut MsgParcel) -> IpcResult<()>32 pub(crate) fn construct(&self, data: &mut MsgParcel, reply: &mut MsgParcel) -> IpcResult<()> { 33 info!("Service construct"); 34 35 if !PermissionChecker::check_internet() { 36 error!("End Service construct, failed: no INTERNET permission"); 37 reply.write(&(ErrorCode::Permission as i32))?; 38 return Err(IpcStatusCode::Failed); 39 } 40 41 let action: u32 = data.read()?; 42 let action: Action = Action::from(action as u8); 43 44 let version: u32 = data.read()?; 45 let version: Version = Version::from(version as u8); 46 47 let mode: u32 = data.read()?; 48 let mode: Mode = Mode::from(mode as u8); 49 50 let bundle_type: u32 = data.read()?; 51 52 let cover: bool = data.read()?; 53 54 let network: u32 = data.read()?; 55 let network_config = NetworkConfig::from(network as u8); 56 57 let metered: bool = data.read()?; 58 59 let roaming: bool = data.read()?; 60 61 let retry: bool = data.read()?; 62 63 let redirect: bool = data.read()?; 64 65 let background: bool = data.read()?; 66 67 let index: u32 = data.read()?; 68 69 let begins: i64 = data.read()?; 70 71 let ends: i64 = data.read()?; 72 73 let gauge: bool = data.read()?; 74 75 let precise: bool = data.read()?; 76 77 let priority: u32 = data.read()?; 78 79 let url: String = data.read()?; 80 81 let title: String = data.read()?; 82 83 let method: String = data.read()?; 84 85 let token: String = data.read()?; 86 87 let description: String = data.read()?; 88 89 let data_base: String = data.read()?; 90 91 let proxy: String = data.read()?; 92 93 let certificate_pins: String = data.read()?; 94 95 let bundle = query_calling_bundle(); 96 97 let uid = ipc::Skeleton::calling_uid(); 98 let token_id = ipc::Skeleton::calling_full_token_id(); 99 let pid = ipc::Skeleton::calling_pid(); 100 101 let certs_path_size: u32 = data.read()?; 102 if certs_path_size > data.readable() as u32 { 103 error!("End Service construct, failed: certs_path_size too large"); 104 reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?; 105 return Err(IpcStatusCode::Failed); 106 } 107 let mut certs_path = Vec::new(); 108 for _ in 0..certs_path_size { 109 let cert_path: String = data.read()?; 110 certs_path.push(cert_path); 111 } 112 113 let form_size: u32 = data.read()?; 114 if form_size > data.readable() as u32 { 115 error!("End Service construct, failed: form_size too large"); 116 reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?; 117 return Err(IpcStatusCode::Failed); 118 } 119 let mut form_items = Vec::new(); 120 for _ in 0..form_size { 121 let name: String = data.read()?; 122 let value: String = data.read()?; 123 form_items.push(FormItem { name, value }); 124 } 125 126 let file_size: u32 = data.read()?; 127 if file_size > data.readable() as u32 { 128 error!("End Service construct, failed: file_specs size too large"); 129 reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?; 130 return Err(IpcStatusCode::Failed); 131 } 132 let mut file_specs: Vec<FileSpec> = Vec::new(); 133 for _ in 0..file_size { 134 let name: String = data.read()?; 135 let path: String = data.read()?; 136 let file_name: String = data.read()?; 137 let mime_type: String = data.read()?; 138 let is_user_file: bool = data.read()?; 139 let mut fd: Option<RawFd> = None; 140 if is_user_file { 141 let ipc_fd: File = data.read_file()?; 142 fd = Some(ipc_fd.into_raw_fd()); 143 } 144 file_specs.push(FileSpec { 145 name, 146 path, 147 file_name, 148 mime_type, 149 is_user_file, 150 fd, 151 }); 152 } 153 154 // Response bodies fd. 155 let body_file_size: u32 = data.read()?; 156 if body_file_size > data.readable() as u32 { 157 error!("End Service construct, failed: body_file size too large"); 158 reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?; 159 return Err(IpcStatusCode::Failed); 160 } 161 162 let mut body_file_paths: Vec<String> = Vec::new(); 163 for _ in 0..body_file_size { 164 let file_name: String = data.read()?; 165 body_file_paths.push(file_name); 166 } 167 168 let header_size: u32 = data.read()?; 169 if header_size > data.readable() as u32 { 170 error!("End Service construct, failed: header size too large"); 171 reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?; 172 return Err(IpcStatusCode::Failed); 173 } 174 let mut headers: HashMap<String, String> = HashMap::new(); 175 for _ in 0..header_size { 176 let key: String = data.read()?; 177 let value: String = data.read()?; 178 headers.insert(key, value); 179 } 180 181 let extras_size: u32 = data.read()?; 182 if extras_size > data.readable() as u32 { 183 error!("End Service construct, failed: extras size too large"); 184 reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?; 185 return Err(IpcStatusCode::Failed); 186 } 187 let mut extras: HashMap<String, String> = HashMap::new(); 188 for _ in 0..extras_size { 189 let key: String = data.read()?; 190 let value: String = data.read()?; 191 extras.insert(key, value); 192 } 193 194 let atomic_account = if bundle_type == ATOMIC_SERVICE { 195 GetOhosAccountUid() 196 } else { 197 "".to_string() 198 }; 199 200 let task_config = TaskConfig { 201 bundle, 202 bundle_type, 203 atomic_account, 204 url, 205 title, 206 description, 207 method, 208 headers, 209 data: data_base, 210 token, 211 proxy, 212 certificate_pins, 213 extras, 214 version, 215 form_items, 216 file_specs, 217 body_file_paths, 218 certs_path, 219 common_data: CommonTaskConfig { 220 task_id: 0, 221 uid, 222 token_id, 223 action, 224 mode, 225 cover, 226 network_config, 227 metered, 228 roaming, 229 retry, 230 redirect, 231 index, 232 begins: begins as u64, 233 ends, 234 gauge, 235 precise, 236 priority, 237 background, 238 }, 239 }; 240 241 debug!("Service construct: task_config constructed"); 242 243 let (event, rx) = TaskManagerEvent::construct(task_config); 244 if !self.task_manager.lock().unwrap().send_event(event) { 245 return Err(IpcStatusCode::Failed); 246 } 247 let ret = match rx.get() { 248 Some(ret) => ret, 249 None => { 250 error!("End Service construct, failed: receives ret failed"); 251 return Err(IpcStatusCode::Failed); 252 } 253 }; 254 255 let task_id = match ret { 256 Ok(id) => id, 257 Err(err_code) => { 258 error!("End Service construct, failed: {:?}", err_code); 259 reply.write(&(err_code as i32))?; 260 return Err(IpcStatusCode::Failed); 261 } 262 }; 263 264 debug!("Service construct: construct event sent to manager"); 265 266 let ret = self.client_manager.subscribe(task_id, pid, uid, token_id); 267 if ret != ErrorCode::ErrOk { 268 error!("End Service subscribe, tid: {}, failed: {:?}", task_id, ret); 269 reply.write(&(ret as i32))?; 270 reply.write(&(task_id as i32))?; 271 return Ok(()); 272 } 273 274 reply.write(&(ErrorCode::ErrOk as i32))?; 275 debug!("End Service construct, succeed with tid: {}", task_id); 276 reply.write(&(task_id as i32))?; 277 Ok(()) 278 } 279 } 280