xref: /base/security/asset/frameworks/ipc/src/lib.rs (revision dfe32fa1)
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
16//! This module defines IPC interfaces and constants.
17
18use ipc::{parcel::MsgParcel, IpcStatusCode};
19
20use asset_definition::{
21    impl_enum_trait, log_throw_error, AssetError, AssetMap, Conversion, DataType, ErrCode, Result, Tag, Value,
22};
23
24/// SA id for Asset service.
25pub const SA_ID: i32 = 8100;
26/// SA name for Asset service.
27pub const SA_NAME: &str = "security_asset_service";
28/// IPC result code.
29pub const IPC_SUCCESS: u32 = 0;
30
31const MAX_MAP_CAPACITY: u32 = 64;
32const MAX_VEC_CAPACITY: u32 = 0x10000;
33
34impl_enum_trait! {
35    /// Code used to identify the function to be called.
36    #[derive(Clone, Copy)]
37    #[derive(Eq, PartialEq)]
38    pub enum IpcCode {
39        /// Code for AddAsset.
40        Add = ipc::FIRST_CALL_TRANSACTION,
41        /// Code for RemoveAsset.
42        Remove,
43        /// Code for UpdateAsset.
44        Update,
45        /// Code for PreQueryAsset.
46        PreQuery,
47        /// Code for QueryAsset.
48        Query,
49        /// Code for PostQueryAsset.
50        PostQuery,
51    }
52}
53
54/// serialize the map to parcel
55pub fn serialize_map(map: &AssetMap, parcel: &mut MsgParcel) -> Result<()> {
56    if map.len() as u32 > MAX_MAP_CAPACITY {
57        return log_throw_error!(ErrCode::InvalidArgument, "[FALTAL][IPC]The map size exceeds the limit.");
58    }
59    parcel.write(&(map.len() as u32)).map_err(ipc_err_handle)?;
60    for (&tag, value) in map.iter() {
61        if tag.data_type() != value.data_type() {
62            return log_throw_error!(
63                ErrCode::InvalidArgument,
64                "[FATAL][IPC]Data type mismatch, key type: {}, value type: {}",
65                tag.data_type(),
66                value.data_type()
67            );
68        }
69        parcel.write(&(tag as u32)).map_err(ipc_err_handle)?;
70        match value {
71            Value::Bool(b) => parcel.write::<bool>(b).map_err(ipc_err_handle)?,
72            Value::Number(n) => parcel.write::<u32>(n).map_err(ipc_err_handle)?,
73            Value::Bytes(a) => parcel.write::<Vec<u8>>(a).map_err(ipc_err_handle)?,
74        }
75    }
76    Ok(())
77}
78
79/// deserialize the map from parcel
80pub fn deserialize_map(parcel: &mut MsgParcel) -> Result<AssetMap> {
81    let len = parcel.read::<u32>().map_err(ipc_err_handle)?;
82    if len > MAX_MAP_CAPACITY {
83        return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][IPC]The map size exceeds the limit.");
84    }
85    let mut map = AssetMap::with_capacity(len as usize);
86    for _ in 0..len {
87        let tag = parcel.read::<u32>().map_err(ipc_err_handle)?;
88        let tag = Tag::try_from(tag)?;
89        match tag.data_type() {
90            DataType::Bool => {
91                let v = parcel.read::<bool>().map_err(ipc_err_handle)?;
92                map.insert(tag, Value::Bool(v));
93            },
94            DataType::Number => {
95                let v = parcel.read::<u32>().map_err(ipc_err_handle)?;
96                map.insert(tag, Value::Number(v));
97            },
98            DataType::Bytes => {
99                let v = parcel.read::<Vec<u8>>().map_err(ipc_err_handle)?;
100                map.insert(tag, Value::Bytes(v));
101            },
102        }
103    }
104    Ok(map)
105}
106
107/// Serialize the collection of map to parcel.
108pub fn serialize_maps(vec: &Vec<AssetMap>, parcel: &mut MsgParcel) -> Result<()> {
109    if vec.len() as u32 > MAX_VEC_CAPACITY {
110        return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][IPC]The vector size exceeds the limit.");
111    }
112    parcel.write::<u32>(&(vec.len() as u32)).map_err(ipc_err_handle)?;
113    for map in vec.iter() {
114        serialize_map(map, parcel)?;
115    }
116    Ok(())
117}
118
119/// Deserialize the collection of map from parcel.
120pub fn deserialize_maps(parcel: &mut MsgParcel) -> Result<Vec<AssetMap>> {
121    let len = parcel.read::<u32>().map_err(ipc_err_handle)?;
122    if len > MAX_VEC_CAPACITY {
123        return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][IPC]The vector size exceeds the limit.");
124    }
125    let mut res_vec = Vec::with_capacity(len as usize);
126    for _i in 0..len {
127        res_vec.push(deserialize_map(parcel)?);
128    }
129    Ok(res_vec)
130}
131
132/// Convert ipc error into Asset error.
133pub fn ipc_err_handle(e: IpcStatusCode) -> AssetError {
134    AssetError::new(ErrCode::IpcError, format!("[FATAL][IPC]Ipc status code = {}", e))
135}
136