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 //! rust dsoftbus sys.
17 
18 #![allow(dead_code)]
19 #![allow(unused_variables)]
20 
21 use std::ffi::{c_void, c_char, CString, CStr};
22 use std::sync::{Once, Mutex, Arc, Condvar};
23 use std::collections::{HashMap, HashSet};
24 use std::time::Duration;
25 use std::hash::{Hash, Hasher};
26 use std::vec::Vec;
27 use std::ptr;
28 use fusion_utils_rust::{ call_debug_enter, FusionResult, FusionErrorCode};
29 use hilog_rust::{ error, info, hilog, HiLogLabel, LogType };
30 use crate::binding::{
31     INTERCEPT_STRING_LENGTH,
32     DINPUT_LINK_TYPE_MAX,
33     DEVICE_ID_SIZE_MAX,
34     SESSION_SIDE_SERVER,
35     LINK_TYPE_WIFI_WLAN_5G,
36     LINK_TYPE_WIFI_WLAN_2G,
37     LINK_TYPE_WIFI_P2P,
38     LINK_TYPE_BR,
39     TYPE_BYTES,
40     NETWORK_ID_BUF_LEN,
41     DEVICE_NAME_BUF_LEN,
42     RET_OK,
43     RET_ERROR,
44     C_CHAR_SIZE,
45     ISessionListener,
46     StreamData,
47     StreamFrameInfo,
48     SessionAttribute,
49     NodeBasicInfo,
50     GetPeerDeviceId,
51     GetSessionSide,
52     OpenSession,
53     CloseSession,
54     CreateSessionServer,
55     RemoveSessionServer,
56     GetLocalNodeDeviceInfo,
57     SendBytes,
58 };
59 
60 const LOG_LABEL: HiLogLabel = HiLogLabel {
61     log_type: LogType::LogCore,
62     domain: 0xD002220,
63     tag: "DSoftbus"
64 };
65 
66 /// Provide for C lib to call
on_session_opened(session_id: i32, result: i32) -> i3267 extern "C" fn on_session_opened(session_id: i32, result: i32) -> i32 {
68     if let Some(dsoftbus) = DSoftbus::get_instance() {
69         if let Err(err) = dsoftbus.on_session_opened(session_id, result) {
70             RET_ERROR
71         } else {
72             RET_OK
73         }
74     } else {
75         error!(LOG_LABEL, "DSoftbus is none");
76         FusionErrorCode::Fail.into()
77     }
78 }
79 
80 /// Provide for C lib to call
on_session_closed(session_id: i32)81 extern "C" fn on_session_closed(session_id: i32) {
82     if let Some(dsoftbus) = DSoftbus::get_instance() {
83         dsoftbus.on_session_closed(session_id);
84         } else {
85         error!(LOG_LABEL, "DSoftbus is none");
86     }
87 }
88 
89 /// Provide for C lib to call
on_bytes_received(session_id: i32, data: *const c_void, data_len: u32)90 extern "C" fn on_bytes_received(session_id: i32, data: *const c_void, data_len: u32) {
91     if let Some(dsoftbus) = DSoftbus::get_instance() {
92         dsoftbus.on_bytes_received(session_id, data, data_len);
93     } else {
94         error!(LOG_LABEL, "DSoftbus is none");
95     }
96 }
97 
98 /// Provide for C lib to call
on_message_received(session_id: i32, byte_data: *const c_void, data_len: u32)99 extern "C" fn on_message_received(session_id: i32, byte_data: *const c_void, data_len: u32) {
100 }
101 
102 /// Provide for C lib to call
on_stream_received(session_id: i32, byte_data: *const StreamData, ext_data: *const StreamData, param_data: *const StreamFrameInfo)103 extern "C" fn on_stream_received(session_id: i32, byte_data: *const StreamData,
104     ext_data: *const StreamData, param_data: *const StreamFrameInfo) {
105 }
106 
107 /// Callback trait used for handling events in the DSoftbus instance.
108 pub trait IDSoftbufCallback {
109     /// Handles the event when a session is closed.
on_session_closed(&self, device_id: &str)110     fn on_session_closed(&self, device_id: &str);
111 
112     /// Handles some things when messages are received from a session.
on_handle_msg(&self, session_id: i32, data: &str)113     fn on_handle_msg(&self, session_id: i32, data: &str);
114 }
115 
116 impl Hash for Box<dyn IDSoftbufCallback> {
hash<H: Hasher>(&self, state: &mut H)117     fn hash<H: Hasher>(&self, state: &mut H) {
118         let raw_ptr = self.as_ref() as *const dyn IDSoftbufCallback;
119         raw_ptr.hash(state);
120     }
121 }
122 
123 impl PartialEq for Box<dyn IDSoftbufCallback> {
eq(&self, other: &Self) -> bool124     fn eq(&self, other: &Self) -> bool {
125         let self_data_ptr = self.as_ref() as *const dyn IDSoftbufCallback as *const ();
126         let other_data_ptr = other.as_ref() as *const dyn IDSoftbufCallback as *const ();
127         ptr::eq(self_data_ptr, other_data_ptr)
128     }
129 }
130 
131 impl Eq for Box<dyn IDSoftbufCallback> {}
132 
133 /// Inner is a struct that represents inner data.
134 #[derive(Default)]
135 struct Inner {
136     /// The session ID.
137     session_id: i32,
138     /// The session listener.
139     session_listener: ISessionListener,
140     /// The local session name.
141     local_session_name: String,
142     /// The session device map.
143     session_dev_map: HashMap<String, i32>,
144     /// The channel status map.
145     channel_status_map: HashMap<String, bool>,
146     /// The operation mutex.
147     operation_mutex: Mutex<HashMap<String, i32>>,
148     /// The wait condition.
149     wait_cond: Arc<(Mutex<bool>, Condvar)>,
150     /// The set of callback functions.
151     callback: HashSet<Box<dyn IDSoftbufCallback>>,
152 }
153 
154 impl Inner {
155     /// Initializes the `DSoftbus` instance.
156     ///
157     /// # Returns
158     ///
159     /// A `FusionResult` which can either be `Ok(())` if the operation was successful or an error wrapped in a
160     /// `FusionErrorCode`.
161     ///
162     /// # Example
163     ///
164     /// ```
165     /// let mut softbus = DSoftbus::default();
166     /// softbus.init();
167     /// ```
init(&mut self) -> FusionResult<()>168     fn init(&mut self) -> FusionResult<()> {
169         call_debug_enter!("DSoftbus::init");
170         let session_name = self.get_session_name()?;
171 
172         if self.local_session_name.eq(&session_name) {
173             info!(LOG_LABEL, "Session server has already created");
174             return Ok(());
175         }
176 
177         let fi_pkg_name: String = String::from("ohos.msdp.fusioninteraction");
178         if !self.local_session_name.is_empty() {
179             error!(LOG_LABEL, "Remove last sesison server, sessionName:{}", @public(self.local_session_name));
180             // SAFETY: no `None` here, cause `fi_pkg_name` and `local_session_name` is valid.
181             let ret: i32 = unsafe { RemoveSessionServer(fi_pkg_name.as_ptr(), self.local_session_name.as_ptr()) };
182             if ret != RET_OK {
183                 error!(LOG_LABEL, "Remove session server failed, error code:{}", @public(ret));
184             }
185         }
186 
187         self.local_session_name = session_name;
188         let session_listener = self.create_session_listener(
189             Some(on_session_opened),
190             Some(on_session_closed),
191             Some(on_bytes_received),
192             Some(on_message_received),
193             Some(on_stream_received),
194         ).map_err (|_| {
195             error!(LOG_LABEL, "Create session_listener failed");
196             FusionErrorCode::Fail
197         })?;
198 
199         // SAFETY: no `None` here, cause `fi_pkg_name`、`local_session_name` and `session_listener` is valid.
200         let ret: i32 = unsafe { CreateSessionServer(fi_pkg_name.as_ptr(), self.local_session_name.as_ptr(),
201             &self.session_listener) };
202         if ret != RET_OK {
203             error!(LOG_LABEL, "Create session server failed, error code:{}", @public(ret));
204             return Err(FusionErrorCode::Fail);
205         }
206         Ok(())
207     }
208 
209     /// Create a session listener object with the given callback functions.
210     ///
211     /// # Arguments
212     ///
213     /// * `on_session_opened` - Callback function for session opened event.
214     /// * `on_session_closed` - Callback function for session closed event.
215     /// * `on_bytes_received` - Callback function for bytes received event.
216     /// * `on_message_received` - Callback function for message received event.
217     /// * `on_stream_received` - Callback function for stream received event.
218     ///
219     /// # Returns
220     ///
221     /// Returns a `Result` containing the created `ISessionListener` object if successful,
222     /// or an error code if any of the callback functions are NULL.
create_session_listener(&mut self, on_session_opened_ptr: Option<extern "C" fn(i32, i32) -> i32>, on_session_closed_ptr: Option<extern "C" fn(i32)>, on_bytes_received_ptr: Option<extern "C" fn(i32, *const c_void, u32)>, on_message_received_ptr: Option<extern "C" fn(i32, *const c_void, u32)>, on_stream_received_ptr: Option<extern "C" fn(i32, *const StreamData, *const StreamData, *const StreamFrameInfo)> ) -> FusionResult<ISessionListener>223     fn create_session_listener(&mut self,
224         on_session_opened_ptr: Option<extern "C" fn(i32, i32) -> i32>,
225         on_session_closed_ptr: Option<extern "C" fn(i32)>,
226         on_bytes_received_ptr: Option<extern "C" fn(i32, *const c_void, u32)>,
227         on_message_received_ptr: Option<extern "C" fn(i32, *const c_void, u32)>,
228         on_stream_received_ptr: Option<extern "C" fn(i32, *const StreamData, *const StreamData, *const StreamFrameInfo)>
229     ) -> FusionResult<ISessionListener> {
230         let session_listener = ISessionListener {
231             on_session_opened: on_session_opened_ptr.ok_or(FusionErrorCode::Fail)?,
232             on_session_closed: on_session_closed_ptr.ok_or(FusionErrorCode::Fail)?,
233             on_bytes_received: on_bytes_received_ptr.ok_or(FusionErrorCode::Fail)?,
234             on_message_received: on_message_received_ptr.ok_or(FusionErrorCode::Fail)?,
235             on_stream_received: on_stream_received_ptr.ok_or(FusionErrorCode::Fail)?,
236         };
237 
238         Ok(session_listener)
239     }
240 
241     /// This function is used to generate a session name by concatenating a fixed prefix `ohos.msdp.device_status` and
242     /// local network ID. The function returns the session name as a `String`.
243     ///
244     /// # Arguments
245     ///
246     /// * `&mut self` - A mutable reference to the current instance of the struct that holds this function.
247     ///
248     /// # Returns
249     ///
250     /// * `FusionResult<String>` - The generated session name, wrapped in a `FusionResult` indicating whether the
251     /// operation was successful or not.
252     ///
253     /// # Errors
254     ///
255     /// This function could fail if there is no local network ID available, in which case a `FusionErrorCode::Fail`
256     /// error code is returned.
257     ///
get_session_name(&mut self) -> FusionResult<String>258     fn get_session_name(&mut self) -> FusionResult<String> {
259         let session_name_head = String::from("ohos.msdp.device_status");
260 
261         let local_network_id = self.local_network_id().map_err(|_| {
262             error!(LOG_LABEL, "Local_network_id is empty");
263             FusionErrorCode::Fail
264         })?;
265         println!("local_network_id= {}", local_network_id);
266         if local_network_id.len() >= INTERCEPT_STRING_LENGTH {
267             let local_network_id_slice = local_network_id[0..INTERCEPT_STRING_LENGTH].to_string();
268             Ok(session_name_head + &local_network_id_slice)
269         } else {
270             error!(LOG_LABEL, "Length of local_network_id less than 20");
271             Err(FusionErrorCode::Fail)
272         }
273     }
274 
275     /// Retrieves the local network ID.
276     ///
277     /// # Returns
278     ///
279     /// A `FusionResult` which can either be `Ok(String)` containing the local network ID if the operation was
280     /// successful or an error wrapped in a `FusionErrorCode`.
281     ///
282     /// # Example
283     ///
284     /// ```
285     /// let mut softbus = DSoftbus::default();
286     /// let local_network_id = softbus.local_network_id();
287     /// ```
local_network_id(&mut self) -> FusionResult<String>288     fn local_network_id(&mut self) -> FusionResult<String> {
289         call_debug_enter!("DSoftbus::local_network_id");
290         let mut local_node = NodeBasicInfo {
291             network_id: [0; NETWORK_ID_BUF_LEN],
292             device_name: [0; DEVICE_NAME_BUF_LEN],
293             device_type_id: 0,
294         };
295 
296         let fi_pkg_name: String = String::from("ohos.msdp.fusioninteraction");
297         // SAFETY: no `None` here, cause `fi_pkg_name`、`local_node` is valid.
298         let ret: i32 = unsafe { GetLocalNodeDeviceInfo(fi_pkg_name.as_ptr() as *const c_char,
299             &mut local_node as *mut NodeBasicInfo) };
300         if ret != RET_OK {
301             error!(LOG_LABEL, "GetLocalNodeDeviceInfo result:{}", @public(ret));
302             return Err(FusionErrorCode::Fail);
303         }
304 
305         // let network_id_ptr: *const c_char =  local_node.network_id.as_ptr() as *const c_char;
306         // // SAFETY: no `None` here, cause `network_id_ptr` is valid.
307         // let network_id_str = unsafe {CStr::from_ptr(network_id_ptr)};
308         // let network_id_slice: &str = network_id_str.to_str().unwrap();
309         // let network_id = network_id_slice.to_owned();
310         // if network_id.is_empty() {
311         //     error!(LOG_LABEL, "Local network id is empty");
312         //     return Err(FusionErrorCode::Fail.into());
313         // }
314         let network_id = self.convert_i8_array_to_string(&local_node.network_id);
315         Ok(network_id)
316     }
317 
318     /// Converts an array of signed 8-bit integers to a String.
319     ///
320     /// # Arguments
321     ///
322     /// * `arr` - The input array containing i8 values.
323     ///
324     /// # Returns
325     ///
326     /// A new String containing the UTF-8 encoded characters from the input array.
327     ///
328     /// # Examples
329     ///
330     /// ```
331     /// let arr: [i8; 5] = [72, 101, 108, 108, 111];
332     /// let result = convert_i8_array_to_string(&arr);
333     /// assert_eq!(result, "Hello");
334     /// ```
convert_i8_array_to_string(&self, arr: &[i8]) -> String335     fn convert_i8_array_to_string(&self, arr: &[i8]) -> String {
336         let u8_arr: Vec<u8> = arr.iter().map(|&x| x as u8).collect();
337         String::from_utf8_lossy(&u8_arr).to_string()
338     }
339 
340     /// Releases all resources associated with the `DSoftbus` instance.
341     ///
342     /// # Example
343     ///
344     /// ```
345     /// let mut softbus = DSoftbus::default();
346     /// softbus.release();
347     /// ```
release(&mut self)348     fn release(&mut self) {
349         call_debug_enter!("DSoftbus::release");
350         for (_key, value) in self.session_dev_map.iter() {
351             // SAFETY: no `None` here, if `session_dev_map` is empty, the function will not be called.
352             unsafe { CloseSession(*value) };
353         }
354         let fi_pkg_name: String = String::from("ohos.msdp.fusioninteraction");
355         // SAFETY: no `None` here, cause `fi_pkg_name` and `local_session_name` is valid.
356         unsafe { RemoveSessionServer(fi_pkg_name.as_ptr(), self.local_session_name.as_ptr()) };
357 
358         self.session_dev_map.clear();
359         self.channel_status_map.clear();
360     }
361 
362     /// Generates a peer session name based on the provided remote network ID.
363     /// The generated session name is a concatenation of a fixed session name and the sliced remote network ID.
364     /// If the length of the remote network ID is less than INTERCEPT_STRING_LENGTH, an error is returned.
365     ///
366     /// # Arguments
367     ///
368     /// * `remote_network_id` - A reference to a String representing the remote network ID.
369     ///
370     /// # Returns
371     ///
372     /// - `Ok(peer_session_name)` if the peer session name is successfully generated.
373     /// - `Err(FusionErrorCode::Fail)` if the length of the remote network ID is less than INTERCEPT_STRING_LENGTH.
get_peer_session_name(&mut self, remote_network_id: &String) -> FusionResult<String>374     fn get_peer_session_name(&mut self, remote_network_id: &String) -> FusionResult<String>{
375         if remote_network_id.len() >= INTERCEPT_STRING_LENGTH {
376             let session_name = String::from("ohos.msdp.device_status");
377             let remote_network_id_slice = remote_network_id[0..INTERCEPT_STRING_LENGTH].to_string();
378             Ok(session_name + &remote_network_id_slice)
379         } else {
380             error!(LOG_LABEL, "Length of remote_network_id less than 20");
381             Err(FusionErrorCode::Fail)
382         }
383     }
384     /// Opens the input softbus connection for the specified remote network ID.
385     ///
386     /// # Arguments
387     ///
388     /// * `remote_network_id` - A `String` representing the ID of the remote network.
389     ///
390     /// # Returns
391     ///
392     /// A `FusionResult` which can either be `Ok(())` if the operation was successful or an error wrapped in a
393     /// `FusionErrorCode`.
394     ///
395     /// # Example
396     ///
397     /// ```
398     /// let mut softbus = DSoftbus::default();
399     /// softbus.open_input_softbus(&"network_id".to_string());
400     /// ```
open_input_softbus(&mut self, remote_network_id: &String) -> FusionResult<()>401     fn open_input_softbus(&mut self, remote_network_id: &String) -> FusionResult<()> {
402         call_debug_enter!("DSoftbus::open_input_softbus");
403         if self.check_device_session_state(remote_network_id) {
404             error!(LOG_LABEL, "Softbus session has already opened");
405             return Ok(());
406         }
407 
408         self.init()?;
409 
410         let data: u8 = 0;
411         let session_attr =  SessionAttribute {
412             data_type: TYPE_BYTES,
413             link_type_num: DINPUT_LINK_TYPE_MAX,
414             link_type: [LINK_TYPE_WIFI_WLAN_2G, LINK_TYPE_WIFI_WLAN_5G, LINK_TYPE_WIFI_P2P,
415                         LINK_TYPE_BR, 0, 0, 0, 0, 0],
416             stream_attr: 0,
417             fast_trans_data:data as *const u8,
418             fast_trans_data_size: 0,
419         };
420 
421         let peer_session_name = self.get_peer_session_name(remote_network_id)?;
422         let group_id = String::from("fi_softbus_group_id");
423         // SAFETY: no `None` here, `local_session_name` is initialized in `init()`, `peer_session_name`,
424         // `remote_network_id`, `group_id` and `session_attr` is valid.
425         let session_id = unsafe { OpenSession(self.local_session_name.as_ptr() as *const c_char,
426             peer_session_name.as_ptr() as *const c_char, remote_network_id.as_ptr() as *const c_char,
427             group_id.as_ptr() as *const c_char, &session_attr as *const SessionAttribute) };
428         if session_id < 0 {
429             error!(LOG_LABEL, "OpenSession failed, session_id:{}", @public(session_id));
430             return Err(FusionErrorCode::Fail);
431         }
432 
433         self.wait_session_opend(remote_network_id, session_id)
434     }
435 
436     /// Closes the input softbus connection for the specified remote network ID.
437     ///
438     /// # Arguments
439     ///
440     /// * `remote_network_id` - A `String` representing the ID of the remote network.
441     ///
442     /// # Example
443     ///
444     /// ```
445     /// let mut softbus = DSoftbus::default();
446     /// softbus.close_input_softbus(&"network_id".to_string());
447     /// ```
close_input_softbus(&mut self, remote_network_id: &String)448     fn close_input_softbus(&mut self, remote_network_id: &String) {
449         call_debug_enter!("DSoftbus::close_input_softbus");
450         if let Some(session_id) = self.session_dev_map.get(remote_network_id) {
451             // SAFETY: no `None` here, `session_id` is valid.
452             unsafe { CloseSession(*session_id) };
453         } else {
454             error!(LOG_LABEL, "SessionDevIdMap not found");
455             return;
456         }
457         self.session_dev_map.remove(remote_network_id);
458         self.channel_status_map.remove(remote_network_id);
459         self.session_id = -1;
460     }
461 
462     /// Waits for a session to be opened with the given remote network ID and session ID.
463     ///
464     /// # Arguments
465     ///
466     /// * `remote_network_id` - A `String` representing the ID of the remote network.
467     /// * `session_id` - An integer representing the ID of the session.
468     ///
469     /// # Returns
470     ///
471     /// A `FusionResult` which can either be `Ok(())` if the operation was successful or an error wrapped in a
472     /// `FusionErrorCode`.
473     ///
474     /// # Example
475     ///
476     /// ```
477     /// let mut softbus = DSoftbus::default();
478     /// softbus.wait_session_opend(&"network_id".to_string(), 1);
479     /// ```
wait_session_opend(&mut self, remote_network_id: &String, session_id_: i32) -> FusionResult<()>480     fn wait_session_opend(&mut self, remote_network_id: &String, session_id_: i32) -> FusionResult<()> {
481         call_debug_enter!("DSoftbus::wait_session_opend");
482         self.session_dev_map.insert(remote_network_id.to_string(), session_id_);
483         self.wait_cond = Arc::new((Mutex::new(false), Condvar::new()));
484         let pair = Arc::clone(&self.wait_cond);
485         let (lock, cvar) = &*pair;
486         let result = (cvar.wait_timeout(self.operation_mutex.lock().unwrap(), Duration::from_secs(5))).unwrap();
487 
488         let get_result = self.channel_status_map.get(remote_network_id);
489         if get_result.is_some() && !get_result.copied().unwrap() {
490             error!(LOG_LABEL, "OpenSession timeout");
491             return Err(FusionErrorCode::Fail);
492         }
493         self.channel_status_map.insert(remote_network_id.to_string(), false);
494         Ok(())
495     }
496 
497     /// Handles the event when a session is opened.
498     ///
499     /// # Arguments
500     ///
501     /// * `session_id` - An integer representing the ID of the session.
502     /// * `result` - An integer indicating the result of the session opening.
503     ///
504     /// # Returns
505     ///
506     /// A `FusionResult` which can either be `Ok(())` if the operation was successful or an error wrapped in a
507     /// `FusionErrorCode`.
508     ///
509     /// # Example
510     ///
511     /// ```
512     /// let mut softbus = DSoftbus::default();
513     /// let session_id: i32 = 1;
514     /// softbus.on_session_opened(1, RET_OK);
515     /// ```
on_session_opened(&mut self, session_id: i32, result: i32) -> FusionResult<()>516     fn on_session_opened(&mut self, session_id: i32, result: i32) -> FusionResult<()> {
517         call_debug_enter!("DSoftbus::on_session_opened");
518         self.session_id = session_id;
519         let mut peer_dev_id: Vec<c_char> = Vec::with_capacity(65);
520         peer_dev_id.extend(vec![0; 65]);
521         let peer_dev_id_ptr = peer_dev_id.as_mut_ptr() as *mut c_char;
522         let len: u32 = (C_CHAR_SIZE * DEVICE_ID_SIZE_MAX) as u32;
523 
524         // SAFETY: Assumes valid input arguments and that `peer_dev_id_ptr` points to a memory block of at least `len`
525         // bytes. Caller must ensure these conditions for correct behavior and to prevent memory issues or security
526         // vulnerabilities.
527         let get_peer_device_id_result: i32 = unsafe { GetPeerDeviceId(session_id, peer_dev_id_ptr, len) };
528 
529         let peer_dev_id_str = unsafe { CStr::from_ptr(peer_dev_id_ptr) };
530         let peer_dev_id: String = peer_dev_id_str.to_string_lossy().into_owned();
531 
532         if result != RET_OK {
533             let device_id = self.find_device(session_id).map_err(|_|{
534                 error!(LOG_LABEL, "find_device error");
535                 FusionErrorCode::Fail
536             })?;
537 
538             if let Some(value) = self.session_dev_map.get(&device_id) {
539                 self.session_dev_map.remove(&device_id);
540             }
541 
542             if get_peer_device_id_result == RET_OK {
543                 self.channel_status_map.insert(peer_dev_id, true);
544             }
545             self.wait_cond.1.notify_all();
546             return Ok(());
547         }
548         // SAFETY: This function does not care about the boundary value of the input.
549         let session_side: i32 = unsafe { GetSessionSide(session_id) };
550         if session_side == SESSION_SIDE_SERVER {
551             if get_peer_device_id_result == RET_OK {
552                 self.session_dev_map.insert(peer_dev_id, session_id);
553             }
554         }
555         else if get_peer_device_id_result == RET_OK {
556             self.channel_status_map.insert(peer_dev_id, true);
557             self.wait_cond.1.notify_all();
558         }
559         Ok(())
560     }
561 
562     /// Finds the device ID associated with a session ID.
563     ///
564     /// # Arguments
565     ///
566     /// * `session_id` - The ID of the session.
567     ///
568     /// # Returns
569     ///
570     /// The device ID associated with the session ID, wrapped in a `Result`. If the device ID is found, it is returned
571     /// as an `Ok` variant. If the device ID is not found, an error is returned as an `Err` variant.
572     ///
573     /// # Example
574     ///
575     /// ```rust
576     /// let dsoftbus = DSoftbus::default();
577     /// let session_id = 123;
578     /// match dsoftbus.find_device(session_id) {
579     ///     Ok(device_id) => {
580     ///         println!("Device ID: {}", device_id);
581     ///     },
582     ///     Err(err) => {
583     ///         println!("Error finding device: {:?}", err);
584     ///     }
585     /// }
586     /// ```
find_device(&self, session_id: i32) -> FusionResult<String>587     fn find_device(&self, session_id: i32) -> FusionResult<String> {
588         call_debug_enter!("DSoftbus::find_device");
589         for (key, value) in self.session_dev_map.iter() {
590             if *value == session_id {
591                 return Ok(key.to_string());
592             }
593         }
594         error!(LOG_LABEL, "find_device error");
595         Err(FusionErrorCode::Fail)
596     }
597 
598     /// Handles the event when a session is closed.
599     ///
600     /// # Arguments
601     ///
602     /// * `session_id` - The ID of the session that was closed.
603     ///
604     /// # Example
605     ///
606     /// ```rust
607     /// let mut dsoftbus = DSoftbus::default();
608     /// let session_id = 123;
609     /// dsoftbus.on_session_closed(session_id);
610     /// ```
on_session_closed(&mut self, session_id: i32)611     fn on_session_closed(&mut self, session_id: i32) {
612         call_debug_enter!("DSoftbus::on_session_closed");
613         let device_id = match self.find_device(session_id) {
614             Ok(device_id) => device_id,
615             Err(err) => {
616                 error!(LOG_LABEL, "find_device error");
617                 return;
618             }
619         };
620         if let Some(value) = self.session_dev_map.get(&device_id) {
621             self.session_dev_map.remove(&device_id);
622         }
623         // SAFETY: This function does not care about the boundary value of the input.
624         if unsafe { GetSessionSide(session_id) } != RET_OK {
625             self.channel_status_map.remove(&device_id);
626         }
627 
628         for callback in &self.callback {
629             callback.on_session_closed(&device_id);
630         }
631 
632         self.session_id = -1;
633     }
634 
635     /// Handles received bytes when bytes are received from a session.
636     ///
637     /// # Arguments
638     ///
639     /// * `session_id` - The ID of the session.
640     /// * `data` - A pointer to the received data.
641     /// * `data_len` - The length of the received data in bytes.
642     ///
643     /// # Safety
644     ///
645     /// This function is marked as unsafe because it accesses and interprets raw pointers and assumes the validity of
646     /// the `data` parameter. The caller needs to ensure that `session_id` is a valid session ID, and `data` is a valid
647     /// pointer to the received data.
648     ///
649     /// # Example
650     ///
651     /// ```rust
652     /// let dsoftbus = DSoftbus::default();
653     /// let session_id = 123;
654     /// let data: *const c_void = ...; // Initialize the data pointer
655     /// let data_len = 10;
656     /// dsoftbus.on_bytes_received(session_id, data, data_len);
657     /// ```
on_bytes_received(&self, session_id: i32, data: *const c_void, data_len: u32)658     fn on_bytes_received(&self, session_id: i32, data: *const c_void, data_len: u32) {
659         call_debug_enter!("DSoftbus::on_bytes_received");
660         if session_id < 0 || data.is_null() || data_len == 0 {
661            error!(LOG_LABEL, "Param check failed");
662         }
663 
664         // SAFETY: no `None` here, cause `network_id_ptr` is valid.
665         let data_str = unsafe {CStr::from_ptr(data as *const c_char)};
666         let data_slice: &str = data_str.to_str().unwrap();
667         let data: String = data_slice.to_owned();
668 
669         for callback in &self.callback {
670             callback.on_handle_msg(session_id, &data);
671         }
672     }
673 
674     /// Checks the session state of a remote device.
675     ///
676     /// # Arguments
677     ///
678     /// * `remote_network_id` - A reference to a String representing the network ID of the remote device.
679     ///
680     /// # Returns
681     ///
682     /// Returns `true` if the session state of the remote device exists in the session device map, or `false` otherwise.
683     ///
684     /// # Example
685     ///
686     /// ```rust
687     /// let dsoftbus = DSoftbus::default();
688     /// let remote_network_id = "target_network".to_string();
689     /// let session_state = dsoftbus.check_device_session_state(&remote_network_id);
690     /// if session_state {
691     ///     println!("The session state of the remote device exists.");
692     /// } else {
693     ///     println!("The session state of the remote device does not exist.");
694     /// }
695     /// ```
check_device_session_state(&self, remote_network_id: &String) -> bool696     fn check_device_session_state(&self, remote_network_id: &String) -> bool {
697         call_debug_enter!("DSoftbus::check_device_session_state");
698         if let Some(value) = self.session_dev_map.get(remote_network_id) {
699             true
700         } else {
701             error!(LOG_LABEL, "Check session state error");
702             false
703         }
704     }
705 
706     /// Sends a message to a specified device.
707     ///
708     /// # Arguments
709     ///
710     /// * `device_id` - A reference to a String representing the ID of the target device.
711     /// * `data` - A pointer to the data to be sent.
712     /// * `data_len` - The length of the data in bytes.
713     ///
714     /// # Returns
715     ///
716     /// Returns `Ok(())` if the message was sent successfully, or an error of type `FusionResult<()>` if sending the
717     /// message failed.
718     ///
719     /// # Example
720     ///
721     /// ```rust
722     /// let dsoftbus = DSoftbus::default();
723     /// let device_id = "target_device".to_string();
724     /// let data: *const c_void = ...; // Initialize the data pointer
725     /// let data_len = 10;
726     /// dsoftbus.send_msg(&device_id, data, data_len).unwrap();
727     /// ```
send_msg(&self, device_id: &String, data: *const c_void, data_len: u32) -> FusionResult<()>728     fn send_msg(&self, device_id: &String, data: *const c_void, data_len: u32) -> FusionResult<()> {
729         call_debug_enter!("DSoftbus::send_msg");
730         if let Some(session_id) = self.session_dev_map.get(device_id) {
731             // SAFETY: no `None` here, `session_id`, `data` and `data_len` is valid.
732             let result: i32 = unsafe {SendBytes(*session_id, data, data_len) };
733             if result != RET_OK {
734                 error!(LOG_LABEL, "Send bytes failed, result:{}", @public(result));
735                 return Err(FusionErrorCode::Fail);
736             }
737             Ok(())
738         } else {
739             error!(LOG_LABEL, "Check session state error");
740             Err(FusionErrorCode::Fail)
741         }
742     }
743 
744     /// Returns a clone of the session device map.
745     ///
746     /// The session device map is a HashMap that maps session IDs to device IDs. Each session ID is represented as a
747     /// String, and each device ID is represented as an i32.
748     ///
749     /// # Returns
750     ///
751     /// Returns a clone of the session device map.
752     ///
753     /// # Example
754     ///
755     /// ```rust
756     /// let dsoftbus = DSoftbus::default();
757     /// let session_dev_map = dsoftbus.get_session_dev_map();
758     /// // Use the session_dev_map here...
759     /// ```
get_session_dev_map(&self) -> HashMap<String, i32>760     fn get_session_dev_map(&self) -> HashMap<String, i32> {
761         self.session_dev_map.clone()
762     }
763 
764     /// Registers a callback to receive SoftBus events.
765     ///
766     /// # Arguments
767     ///
768     /// * `callback` - A Boxed trait object implementing the IDSoftbufCallback trait. This callback will be called when
769     /// SoftBus events occur.
770     ///
771     /// # Example
772     ///
773     /// ```rust
774     /// let mut dsoftbus = DSoftbus::default();
775     /// let callback = Box::new(MyCallback {});
776     /// dsoftbus.register_callback(callback);
777     /// ```
register_callback(&mut self, callback: Box<dyn IDSoftbufCallback>)778     fn register_callback(&mut self, callback: Box<dyn IDSoftbufCallback>) {
779         call_debug_enter!("DeviceProfileAdapter::register_callback");
780         self.callback.insert(callback);
781     }
782 }
783 
784 /// DSoftbus is a struct that represents the DSoftbus object.
785 #[derive(Default)]
786 pub struct DSoftbus {
787     /// The implementation of DSoftbus.
788     dsoftbus_impl: Mutex<Inner>,
789 }
790 
791 impl DSoftbus {
792     /// Returns a reference to the SoftBus singleton instance.
793     ///
794     /// # Returns
795     ///
796     /// Returns an `Option<&'static Self>` containing a reference to the SoftBus singleton instance, or `None` if the
797     /// singleton has not yet been initialized.
798     ///
799     /// # Safety
800     ///
801     /// This function is marked as unsafe because it modifies static variables. It is expected that the caller is aware
802     /// of the risks and takes appropriate measures to ensure safety.
803     ///
804     /// # Example
805     ///
806     /// ```rust
807     /// match DSoftbus::get_instance() {
808     ///     Some(instance) => {
809     ///         println!("SoftBus singleton instance found.");
810     ///         // Use the instance here...
811     ///     }
812     ///     None => {
813     ///         println!("SoftBus singleton instance not yet initialized.");
814     ///     }
815     /// }
816     /// ```
get_instance() -> Option<&'static Self>817     pub fn get_instance() -> Option<&'static Self> {
818         static mut G_DSOFTBUS: Option<DSoftbus> = None;
819         static INIT_ONCE: Once = Once::new();
820         // SAFETY: no `None` here. just Modifying the Static Variables
821         unsafe {
822             INIT_ONCE.call_once(|| {
823                 G_DSOFTBUS = Some(DSoftbus::default());
824             });
825             G_DSOFTBUS.as_ref()
826         }
827     }
828 
829     /// Initializes the SoftBus instance.
830     ///
831     /// # Returns
832     ///
833     /// Returns `Result<(), FusionError>` indicating the success or failure of the initialization. An `Err` value is
834     /// returned if there was a lock error during the execution.
835     ///
836     /// # Note
837     ///
838     /// This function initializes the SoftBus instance. It should be called before using any SoftBus functionality to
839     /// ensure proper setup and initialization.
840     ///
841     /// # Example
842     ///
843     /// ```rust
844     /// match my_instance.init() {
845     ///     Ok(()) => {
846     ///         println!("SoftBus initialized successfully");
847     ///     }
848     ///     Err(err) => {
849     ///         eprintln!("Failed to initialize SoftBus: {:?}", err);
850     ///     }
851     /// }
852     /// ```
init(&self) -> FusionResult<()>853     pub fn init(&self) -> FusionResult<()> {
854         match self.dsoftbus_impl.lock() {
855             Ok(mut guard) => {
856                 guard.init()
857             }
858             Err(err) => {
859                 error!(LOG_LABEL, "lock error: {:?}", err);
860                 Err(FusionErrorCode::Fail)
861             }
862         }
863     }
864 
865     /// Releases the resources held by the SoftBus instance.
866     ///
867     /// # Note
868     ///
869     /// This function releases the resources held by the SoftBus instance. It should be called when you no longer need
870     /// to use the SoftBus functionality and want to free up any associated resources.
871     ///
872     /// # Example
873     ///
874     /// ```rust
875     /// my_instance.release();
876     /// ```
release(&self)877     pub fn release(&self) {
878         match self.dsoftbus_impl.lock() {
879             Ok(mut guard) => {
880                 guard.release();
881             }
882             Err(err) => {
883                 error!(LOG_LABEL, "lock error: {:?}", err);
884             }
885         }
886     }
887 
888     /// Opens an input SoftBus connection for a specified remote network ID.
889     ///
890     /// # Arguments
891     ///
892     /// * `remote_network_id` - The remote network ID for which to open the input SoftBus connection.
893     ///
894     /// # Returns
895     ///
896     /// Returns `Result<(), FusionError>` indicating the success or failure of the operation. An `Err` value is
897     /// returned if there was a lock error during the execution.
898     ///
899     /// # Note
900     ///
901     /// This function opens an input SoftBus connection for the specified remote network ID. It should be called when
902     /// you want to establish communication with the remote network.
903     ///
904     /// # Example
905     ///
906     /// ```rust
907     /// let remote_network_id = String::from("example_network_id");
908     ///
909     /// match my_instance.open_input_softbus(&remote_network_id) {
910     ///     Ok(()) => {
911     ///         println!("Input SoftBus connection opened successfully");
912     ///     }
913     ///     Err(err) => {
914     ///         eprintln!("Failed to open input SoftBus connection: {:?}", err);
915     ///     }
916     /// }
917     /// ```
open_input_softbus(&self, remote_network_id: &String) -> FusionResult<()>918     pub fn open_input_softbus(&self, remote_network_id: &String) -> FusionResult<()> {
919         match self.dsoftbus_impl.lock() {
920             Ok(mut guard) => {
921                 guard.open_input_softbus(remote_network_id)
922             }
923             Err(err) => {
924                 error!(LOG_LABEL, "lock error: {:?}", err);
925                 Err(FusionErrorCode::Fail)
926             }
927         }
928     }
929 
930     /// Closes the input SoftBus connection for a specified remote network ID.
931     ///
932     /// # Arguments
933     ///
934     /// * `remote_network_id` - The remote network ID for which to close the input SoftBus connection.
935     ///
936     /// # Note
937     ///
938     /// This function closes the input SoftBus connection for the specified remote network ID. It should be called when
939     /// you want to terminate the communication with the remote network.
940     ///
941     /// # Example
942     ///
943     /// ```rust
944     /// let remote_network_id = String::from("example_network_id");
945     /// my_instance.close_input_softbus(&remote_network_id);
946     /// ```
close_input_softbus(&self, remote_network_id: &String)947     pub fn close_input_softbus(&self, remote_network_id: &String) {
948         match self.dsoftbus_impl.lock() {
949             Ok(mut guard) => {
950                 guard.close_input_softbus(remote_network_id);
951             }
952             Err(err) => {
953                 error!(LOG_LABEL, "lock error: {:?}", err);
954             }
955         }
956     }
957 
958     /// Callback function triggered when a session is opened.
959     ///
960     /// # Arguments
961     ///
962     /// * `session_id` - The ID of the opened session.
963     /// * `result` - The result of the session opening operation.
964     ///
965     /// # Returns
966     ///
967     /// Returns `Result<(), FusionError>` indicating the success or failure of the operation. An `Err` value is
968     /// returned if there was a lock error during the callback execution.
969     ///
970     /// # Note
971     ///
972     /// This function is called when a session is opened, allowing you to perform any necessary handling or operations
973     /// related to the opened session. The `result` parameter provides the outcome of the session opening operation.
974     ///
975     /// # Example
976     ///
977     /// ```rust
978     /// let session_id = 123;
979     /// let result = 0; // Assume the session opening was successful
980     ///
981     /// match callback.on_session_opened(session_id, result) {
982     ///     Ok(()) => {
983     ///         println!("Session opened successfully");
984     ///     }
985     ///     Err(err) => {
986     ///         eprintln!("Failed to open session: {:?}", err);
987     ///     }
988     /// }
989     /// ```
on_session_opened(&self, session_id: i32, result: i32) -> FusionResult<()>990     fn on_session_opened(&self, session_id: i32, result: i32) -> FusionResult<()> {
991         match self.dsoftbus_impl.lock() {
992             Ok(mut guard) => {
993                 guard.on_session_opened(session_id, result)
994             }
995             Err(err) => {
996                 error!(LOG_LABEL, "lock error: {:?}", err);
997                 Err(FusionErrorCode::Fail)
998             }
999         }
1000     }
1001 
1002     /// Callback function triggered when a session is closed.
1003     ///
1004     /// # Arguments
1005     ///
1006     /// * `session_id` - The ID of the closed session.
1007     ///
1008     /// # Note
1009     ///
1010     /// This function is called when a session is closed, allowing you to perform any necessary cleanup or handling
1011     /// related to the closed session.
1012     ///
1013     /// # Example
1014     ///
1015     /// ```rust
1016     /// let session_id = 123;
1017     ///
1018     /// callback.on_session_closed(session_id);
1019     /// ```
on_session_closed(&self, session_id: i32)1020     fn on_session_closed(&self, session_id: i32) {
1021         match self.dsoftbus_impl.lock() {
1022             Ok(mut guard) => {
1023                 guard.on_session_closed(session_id);
1024             }
1025             Err(err) => {
1026                 error!(LOG_LABEL, "lock error: {:?}", err);
1027             }
1028         }
1029     }
1030 
1031     /// Callback function triggered when bytes are received.
1032     ///
1033     /// # Arguments
1034     ///
1035     /// * `session_id` - The ID of the session related to the received bytes.
1036     /// * `data` - The pointer to the received bytes data.
1037     /// * `data_len` - The length of the received bytes data in bytes.
1038     ///
1039     /// # Note
1040     ///
1041     /// This function is called when bytes are received, allowing you to handle and process the received data.
1042     /// Please note that the pointer `data` is a raw pointer that needs to be handled carefully to avoid memory safety
1043     /// issues and undefined behavior.
1044     /// Make sure to properly dereference and manipulate the data using appropriate safe Rust code.
1045     ///
1046     /// # Example
1047     ///
1048     /// ```rust
1049     /// let session_id = 123;
1050     /// let data_ptr: *const c_void = ...; // Obtain the actual pointer to the received bytes data
1051     /// let data_len = ...; // Obtain the length of the received bytes data
1052     ///
1053     /// callback.on_bytes_received(session_id, data_ptr, data_len);
1054     /// ```
on_bytes_received(&self, session_id: i32, data: *const c_void, data_len: u32)1055     fn on_bytes_received(&self, session_id: i32, data: *const c_void, data_len: u32) {
1056         match self.dsoftbus_impl.lock() {
1057             Ok(guard) => {
1058                 guard.on_bytes_received(session_id, data, data_len);
1059             }
1060             Err(err) => {
1061                 error!(LOG_LABEL, "lock error: {:?}", err);
1062             }
1063         }
1064     }
1065 
1066     /// Sends a message to the specified device.
1067     ///
1068     /// # Arguments
1069     ///
1070     /// * `device_id` - The ID of the target device to send the message to.
1071     /// * `data` - The pointer to the message data.
1072     /// * `data_len` - The length of the message data in bytes.
1073     ///
1074     /// # Returns
1075     ///
1076     /// Returns `Ok(())` if the message is successfully sent, otherwise returns an `Err` containing an error code.
1077     ///
1078     /// # Note
1079     ///
1080     /// This function sends the message to the specified device using the internal `dsoftbus_impl` instance.
1081     /// The pointer `data` is a raw pointer that needs to be handled carefully to avoid memory safety issues and
1082     /// undefined behavior.
1083     /// Make sure to properly dereference and manipulate the data using appropriate safe Rust code.
1084     ///
1085     /// # Example
1086     ///
1087     /// ```rust
1088     /// let device_id = String::from("example_device");
1089     /// let data_ptr: *const c_void = ...; // Obtain the actual pointer to the message data
1090     /// let data_len = ...; // Obtain the length of the message data
1091     ///
1092     /// match my_instance.send_msg(&device_id, data_ptr, data_len) {
1093     ///     Ok(()) => println!("Message sent successfully"),
1094     ///     Err(err) => eprintln!("Failed to send message: {:?}", err),
1095     /// }
1096     /// ```
send_msg(&self, device_id: &String, data: *const c_void, data_len: u32) -> FusionResult<()>1097     pub fn send_msg(&self, device_id: &String, data: *const c_void,
1098         data_len: u32) -> FusionResult<()> {
1099         match self.dsoftbus_impl.lock() {
1100             Ok(guard) => {
1101                 guard.send_msg(device_id, data, data_len)
1102             }
1103             Err(err) => {
1104                 error!(LOG_LABEL, "lock error: {:?}", err);
1105                 Err(FusionErrorCode::Fail)
1106             }
1107         }
1108     }
1109 
1110     /// Callback function triggered when a message is received.
1111     ///
1112     /// # Arguments
1113     ///
1114     /// * `session_id` - The ID of the session related to the received message.
1115     /// * `data` - The pointer to the message data.
1116     /// * `data_len` - The length of the message data in bytes.
1117     ///
1118     /// # Note
1119     ///
1120     /// This function is called when a message is received, allowing you to handle and process the received message
1121     /// data.
1122     /// Please note that the pointer `data` is a raw pointer that needs to be handled carefully to avoid memory safety
1123     /// issues and undefined behavior.
1124     /// Make sure to properly dereference and manipulate the data using appropriate safe Rust code.
1125     ///
1126     /// # Example
1127     ///
1128     /// ```rust
1129     /// let session_id = 123;
1130     /// let data_ptr: *const c_void = ...; // Obtain the actual pointer to the message data
1131     /// let data_len = ...; // Obtain the length of the message data
1132     ///
1133     /// callback.on_message_received(session_id, data_ptr, data_len);
1134     /// ```
on_message_received(&self, session_id: i32, data: *const c_void, data_len: u32)1135     fn on_message_received(&self, session_id: i32, data: *const c_void, data_len: u32) {
1136     }
1137 
1138     /// Callback function triggered when a stream is received.
1139     ///
1140     /// # Arguments
1141     ///
1142     /// * `session_id` - The ID of the session related to the received stream.
1143     /// * `data` - The pointer to the stream data.
1144     /// * `ext` - The pointer to the extended stream data.
1145     /// * `param` - The pointer to the stream frame information.
1146     ///
1147     /// # Note
1148     ///
1149     /// This function is called when a stream is received, allowing you to handle and process the received stream data.
1150     /// Please note that the pointers `data`, `ext`, and `param` are raw pointers that need to be handled carefully to
1151     /// avoid memory safety issues and undefined behavior.
1152     /// Make sure to properly dereference and manipulate the data using appropriate safe Rust code.
1153     ///
1154     /// # Example
1155     ///
1156     /// ```rust
1157     /// let session_id = 123;
1158     /// let data_ptr: *const StreamData = ...; // Obtain the actual pointer to the stream data
1159     /// let ext_ptr: *const StreamData = ...; // Obtain the actual pointer to the extended stream data
1160     /// let param_ptr: *const StreamFrameInfo = ...; // Obtain the actual pointer to the stream frame information
1161     ///
1162     /// callback.on_stream_received(session_id, data_ptr, ext_ptr, param_ptr);
1163     /// ```
on_stream_received(&self, session_id: i32, data: *const StreamData, ext: *const StreamData, param: *const StreamFrameInfo)1164     fn on_stream_received(&self, session_id: i32, data: *const StreamData,
1165         ext: *const StreamData, param: *const StreamFrameInfo) {
1166     }
1167 
1168     /// Get the session device mapping from the DSoftbus instance.
1169     ///
1170     /// # Returns
1171     /// Returns a `HashMap` that maps session IDs to device IDs.
1172     ///
1173     /// # Errors
1174     /// Returns an error of type `FusionError` if the lock cannot be acquired.
1175     ///
1176     /// # Example
1177     /// ```rust
1178     /// match my_instance.get_session_dev_map() {
1179     ///     Ok(map) => {
1180     ///         // Process the session device map
1181     ///         for (session_id, device_id) in map {
1182     ///             println!("Session ID: {}, Device ID: {}", session_id, device_id);
1183     ///         }
1184     ///     }
1185     ///     Err(err) => {
1186     ///         eprintln!("Error: {:?}", err);
1187     ///     }
1188     /// }
1189     /// ```
get_session_dev_map(&self) -> FusionResult<HashMap<String, i32>>1190     pub fn get_session_dev_map(&self) -> FusionResult<HashMap<String, i32>> {
1191         match self.dsoftbus_impl.lock() {
1192             Ok(guard) => {
1193                 Ok(guard.get_session_dev_map())
1194             }
1195             Err(err) => {
1196                 error!(LOG_LABEL, "lock error: {:?}", err);
1197                 Err(FusionErrorCode::Fail)
1198             }
1199         }
1200     }
1201 
1202     /// Register a callback function to the DSoftbus instance.
1203     ///
1204     /// # Arguments
1205     /// - `callback`: A callback function that implements the `IDSoftbufCallback` trait.
1206     ///
1207     /// # Returns
1208     /// This function does not return anything.
1209     ///
1210     /// # Example
1211     /// ```rust
1212     /// let callback = Box::new(MyCallback {});
1213     /// my_instance.register_callback(callback);
1214     /// ```
register_callback(&self, callback: Box<dyn IDSoftbufCallback>)1215     pub fn register_callback(&self, callback: Box<dyn IDSoftbufCallback>) {
1216         match self.dsoftbus_impl.lock() {
1217             Ok(mut guard) => {
1218                 guard.register_callback(callback);
1219             }
1220             Err(err) => {
1221                 error!(LOG_LABEL, "lock error: {:?}", err);
1222             }
1223         }
1224     }
1225 }