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 }