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 //! Delegator of IPC service.
17 //!
18 //! This is part of implementation of IPC service as required by IPC framework.
19 //! As IPC request will first be delegated to this [`delegator`]. [`delegator`]
20 //! will check user token, and then redirect request to business module.
21 
22 #![allow(unused_variables)]
23 
24 use std::cell::Cell;
25 use std::sync::Mutex;
26 use std::ffi::{ c_char, CString };
27 use hilog_rust::{ debug, info, error, hilog, HiLogLabel, LogType };
28 use ipc_rust::{ BorrowedMsgParcel, Deserialize, InterfaceToken, IRemoteBroker, IRemoteStub };
29 use fusion_data_rust::{ Intention, IPlugin, CallingContext };
30 use fusion_utils_rust::{ call_debug_enter, FusionResult, FusionErrorCode };
31 use fusion_ipc_service_rust::{ IDeviceStatus, FusionIpcStub };
32 use fusion_plugin_manager_rust::PluginManager;
33 
34 const LOG_LABEL: HiLogLabel = HiLogLabel {
35     log_type: LogType::LogCore,
36     domain: 0xD002220,
37     tag: "FusionIpcDelegator"
38 };
39 
40 pub struct FusionIpcDelegator {
41     plugin_mgr: Mutex<Cell<PluginManager>>,
42 }
43 
44 impl FusionIpcDelegator {
new() -> Self45     pub fn new() -> Self {
46         Self {
47             plugin_mgr: Mutex::new(Cell::new(PluginManager::default()))
48         }
49     }
50 
check_interface_token(&self, data: &BorrowedMsgParcel) -> FusionResult<()>51     fn check_interface_token(&self, data: &BorrowedMsgParcel) -> FusionResult<()> {
52         call_debug_enter!("FusionIpcDelegator::check_interface_token");
53         match InterfaceToken::deserialize(data) {
54             Ok(token) => {
55                 debug!(LOG_LABEL, "check interface token");
56                 if token.get_token() != FusionIpcStub::get_descriptor() {
57                     error!(LOG_LABEL, "Unexpected token");
58                     Err(FusionErrorCode::Fail)
59                 } else {
60                     Ok(())
61                 }
62             }
63             Err(_) => {
64                 error!(LOG_LABEL, "Deserialization of interface token failed");
65                 Err(FusionErrorCode::Fail)
66             }
67         }
68     }
69 
load_plugin(&self, intention: Intention) -> FusionResult<Box<dyn IPlugin>>70     fn load_plugin(&self, intention: Intention) -> FusionResult<Box<dyn IPlugin>> {
71         call_debug_enter!("FusionIpcDelegator::load_plugin");
72         match self.plugin_mgr.lock() {
73             Ok(mut guard) => {
74                 let plugin = guard.get_mut().load_plugin(intention);
75                 match plugin {
76                     Some(plugin) => {
77                         debug!(LOG_LABEL, "Plugin loaded");
78                         Ok(plugin)
79                     }
80                     None => {
81                         error!(LOG_LABEL, "Failed to load intention module");
82                         Err(FusionErrorCode::Fail)
83                     }
84                 }
85             }
86             Err(_) => {
87                 error!(LOG_LABEL, "Error locking");
88                 Err(FusionErrorCode::Fail)
89             }
90         }
91     }
92 }
93 
94 impl IDeviceStatus for FusionIpcDelegator {
enable(&self, intention: Intention, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>95     fn enable(&self, intention: Intention, data: &BorrowedMsgParcel,
96         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
97         call_debug_enter!("FusionIpcDelegator::enable");
98         self.check_interface_token(data)?;
99 
100         let plugin = self.load_plugin(intention)?;
101         let context = CallingContext::current();
102         info!(LOG_LABEL, "Call plugin.enable()");
103         plugin.enable(&context, data, reply)
104     }
105 
disable(&self, intention: Intention, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>106     fn disable(&self, intention: Intention, data: &BorrowedMsgParcel,
107         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
108         call_debug_enter!("FusionIpcDelegator::disable");
109         self.check_interface_token(data)?;
110 
111         let plugin = self.load_plugin(intention)?;
112         let context = CallingContext::current();
113         info!(LOG_LABEL, "Call plugin.disable()");
114         plugin.disable(&context, data, reply)
115     }
116 
start(&self, intention: Intention, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>117     fn start(&self, intention: Intention, data: &BorrowedMsgParcel,
118         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
119         call_debug_enter!("FusionIpcDelegator::start");
120         self.check_interface_token(data)?;
121 
122         let plugin = self.load_plugin(intention)?;
123         let context = CallingContext::current();
124         info!(LOG_LABEL, "Call plugin.start()");
125         plugin.start(&context, data, reply)
126     }
127 
stop(&self, intention: Intention, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>128     fn stop(&self, intention: Intention, data: &BorrowedMsgParcel,
129         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
130         call_debug_enter!("FusionIpcDelegator::stop");
131         self.check_interface_token(data)?;
132 
133         let plugin = self.load_plugin(intention)?;
134         let context = CallingContext::current();
135         info!(LOG_LABEL, "Call plugin.stop()");
136         plugin.stop(&context, data, reply)
137     }
138 
add_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>139     fn add_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel,
140         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
141         call_debug_enter!("FusionIpcDelegator::add_watch");
142         self.check_interface_token(data)?;
143 
144         let plugin = self.load_plugin(intention)?;
145         let context = CallingContext::current();
146         info!(LOG_LABEL, "Call plugin.add_watch()");
147         plugin.add_watch(&context, id, data, reply)
148     }
149 
remove_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>150     fn remove_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel,
151         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
152         call_debug_enter!("FusionIpcDelegator::remove_watch");
153         self.check_interface_token(data)?;
154 
155         let plugin = self.load_plugin(intention)?;
156         let context = CallingContext::current();
157         info!(LOG_LABEL, "Call plugin.remove_watch()");
158         plugin.remove_watch(&context, id, data, reply)
159     }
160 
set_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>161     fn set_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel,
162         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
163         call_debug_enter!("FusionIpcDelegator::set_param");
164         self.check_interface_token(data)?;
165 
166         let plugin = self.load_plugin(intention)?;
167         let context = CallingContext::current();
168         info!(LOG_LABEL, "Call plugin.set_param()");
169         plugin.set_param(&context, id, data, reply)
170     }
171 
get_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>172     fn get_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel,
173         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
174         call_debug_enter!("FusionIpcDelegator::get_param");
175         self.check_interface_token(data)?;
176 
177         let plugin = self.load_plugin(intention)?;
178         let context = CallingContext::current();
179         info!(LOG_LABEL, "Call plugin.get_param()");
180         plugin.get_param(&context, id, data, reply)
181     }
182 
control(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> FusionResult<()>183     fn control(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel,
184         reply: &mut BorrowedMsgParcel) -> FusionResult<()> {
185         call_debug_enter!("FusionIpcDelegator::control");
186         self.check_interface_token(data)?;
187 
188         let plugin = self.load_plugin(intention)?;
189         let context = CallingContext::current();
190         info!(LOG_LABEL, "Call plugin.control()");
191         plugin.control(&context, id, data, reply)
192     }
193 }
194 
195 impl IRemoteBroker for FusionIpcDelegator {}
196