plugin_framework, change return type
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
		
							parent
							
								
									6dc02084c2
								
							
						
					
					
						commit
						9c6b303fa2
					
				| @ -3,7 +3,6 @@ | ||||
| // -----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| use super::*; | ||||
| use std::{ffi::c_void, ptr::null}; | ||||
| 
 | ||||
| const EXT_SUPPORT_BLOCK_INPUT: &str = "block-input"; | ||||
| 
 | ||||
| @ -11,7 +10,7 @@ pub(super) fn ext_support_callback( | ||||
|     id: &str, | ||||
|     peer: &str, | ||||
|     msg: &super::callback_msg::MsgToExtSupport, | ||||
| ) -> *const c_void { | ||||
| ) -> PluginReturn { | ||||
|     match &msg.r#type as _ { | ||||
|         EXT_SUPPORT_BLOCK_INPUT => { | ||||
|             // let supported_plugins = [];
 | ||||
| @ -19,25 +18,25 @@ pub(super) fn ext_support_callback( | ||||
|             let supported = true; | ||||
|             if supported { | ||||
|                 if msg.data.len() != 1 { | ||||
|                     return make_return_code_msg( | ||||
|                     return PluginReturn::new( | ||||
|                         errno::ERR_CALLBACK_INVALID_ARGS, | ||||
|                         "Invalid data length", | ||||
|                     ); | ||||
|                 } | ||||
|                 let block = msg.data[0] != 0; | ||||
|                 if crate::server::plugin_block_input(peer, block) == block { | ||||
|                     null() | ||||
|                     PluginReturn::success() | ||||
|                 } else { | ||||
|                     make_return_code_msg(errno::ERR_CALLBACK_FAILED, "") | ||||
|                     PluginReturn::new(errno::ERR_CALLBACK_FAILED, "") | ||||
|                 } | ||||
|             } else { | ||||
|                 make_return_code_msg( | ||||
|                 PluginReturn::new( | ||||
|                     errno::ERR_CALLBACK_PLUGIN_ID, | ||||
|                     &format!("This operation is not supported for plugin '{}', please contact the RustDesk team for support.", id), | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|         _ => make_return_code_msg( | ||||
|         _ => PluginReturn::new( | ||||
|             errno::ERR_CALLBACK_TARGET_TYPE, | ||||
|             &format!("Unknown target type '{}'", &msg.r#type), | ||||
|         ), | ||||
|  | ||||
| @ -6,7 +6,6 @@ use serde_json; | ||||
| use std::{ | ||||
|     collections::HashMap, | ||||
|     ffi::{c_char, c_void}, | ||||
|     ptr::null, | ||||
|     sync::Arc, | ||||
| }; | ||||
| 
 | ||||
| @ -63,11 +62,9 @@ macro_rules! cb_msg_field { | ||||
|     ($field: ident) => { | ||||
|         let $field = match cstr_to_string($field) { | ||||
|             Err(e) => { | ||||
|                 log::error!("Failed to convert {} to string, {}", stringify!($field), e); | ||||
|                 return make_return_code_msg( | ||||
|                     errno::ERR_CALLBACK_INVALID_ARGS, | ||||
|                     &format!("Failed to convert {} to string, {}", stringify!($field), e), | ||||
|                 ); | ||||
|                 let msg = format!("Failed to convert {} to string, {}", stringify!($field), e); | ||||
|                 log::error!("{}", &msg); | ||||
|                 return PluginReturn::new(errno::ERR_CALLBACK_INVALID_ARGS, &msg); | ||||
|             } | ||||
|             Ok(v) => v, | ||||
|         }; | ||||
| @ -77,7 +74,7 @@ macro_rules! cb_msg_field { | ||||
| macro_rules! early_return_value { | ||||
|     ($e:expr, $code: ident, $($arg:tt)*) => { | ||||
|         match $e { | ||||
|             Err(e) => return make_return_code_msg( | ||||
|             Err(e) => return PluginReturn::new( | ||||
|                 errno::$code, | ||||
|                 &format!("Failed to {} '{}'", format_args!($($arg)*), e), | ||||
|             ), | ||||
| @ -105,7 +102,7 @@ pub(super) extern "C" fn cb_msg( | ||||
|     id: *const c_char, | ||||
|     content: *const c_void, | ||||
|     len: usize, | ||||
| ) -> *const c_void { | ||||
| ) -> PluginReturn { | ||||
|     cb_msg_field!(peer); | ||||
|     cb_msg_field!(target); | ||||
|     cb_msg_field!(id); | ||||
| @ -122,9 +119,9 @@ pub(super) extern "C" fn cb_msg( | ||||
|                     ..Default::default() | ||||
|                 }; | ||||
|                 session.send_plugin_request(request); | ||||
|                 null() | ||||
|                 PluginReturn::success() | ||||
|             } else { | ||||
|                 make_return_code_msg( | ||||
|                 PluginReturn::new( | ||||
|                     errno::ERR_CALLBACK_PEER_NOT_FOUND, | ||||
|                     &format!("Failed to find session for peer '{}'", peer), | ||||
|                 ) | ||||
| @ -136,7 +133,7 @@ pub(super) extern "C" fn cb_msg( | ||||
|             let content = std::string::String::from_utf8(content_slice[2..].to_vec()) | ||||
|                 .unwrap_or("".to_string()); | ||||
|             push_event_to_ui(channel, &peer, &content); | ||||
|             null() | ||||
|             PluginReturn::success() | ||||
|         } | ||||
|         MSG_TO_CONFIG_TARGET => { | ||||
|             let s = early_return_value!( | ||||
| @ -162,7 +159,7 @@ pub(super) extern "C" fn cb_msg( | ||||
|                         // No need to set the peer id for location config.
 | ||||
|                         push_option_to_ui(ui.channel, &id, "", &msg, ui); | ||||
|                     } | ||||
|                     null() | ||||
|                     PluginReturn::success() | ||||
|                 } | ||||
|                 config::CONFIG_TYPE_PEER => { | ||||
|                     let _r = early_return_value!( | ||||
| @ -173,9 +170,9 @@ pub(super) extern "C" fn cb_msg( | ||||
|                     if let Some(ui) = &msg.ui { | ||||
|                         push_option_to_ui(ui.channel, &id, &peer, &msg, ui); | ||||
|                     } | ||||
|                     null() | ||||
|                     PluginReturn::success() | ||||
|                 } | ||||
|                 _ => make_return_code_msg( | ||||
|                 _ => PluginReturn::new( | ||||
|                     errno::ERR_CALLBACK_TARGET_TYPE, | ||||
|                     &format!("Unknown target type '{}'", &msg.r#type), | ||||
|                 ), | ||||
| @ -195,7 +192,7 @@ pub(super) extern "C" fn cb_msg( | ||||
|             ); | ||||
|             super::callback_ext::ext_support_callback(&id, &peer, &msg) | ||||
|         } | ||||
|         _ => make_return_code_msg( | ||||
|         _ => PluginReturn::new( | ||||
|             errno::ERR_CALLBACK_TARGET, | ||||
|             &format!("Unknown target '{}'", target), | ||||
|         ), | ||||
|  | ||||
| @ -1,16 +1,19 @@ | ||||
| use hbb_common::{libc, ResultType}; | ||||
| use std::ffi::{c_char, c_void, CStr}; | ||||
| use std::{ | ||||
|     ffi::{c_char, c_void, CStr}, | ||||
|     ptr::null, | ||||
| }; | ||||
| 
 | ||||
| mod callback_msg; | ||||
| mod callback_ext; | ||||
| mod callback_msg; | ||||
| mod config; | ||||
| pub mod desc; | ||||
| mod errno; | ||||
| pub mod ipc; | ||||
| mod plog; | ||||
| mod plugins; | ||||
| pub mod native; | ||||
| pub mod native_handlers; | ||||
| mod plog; | ||||
| mod plugins; | ||||
| 
 | ||||
| pub use plugins::{ | ||||
|     handle_client_event, handle_listen_event, handle_server_event, handle_ui_event, load_plugin, | ||||
| @ -29,6 +32,46 @@ pub const EVENT_ON_CONN_CLOSE_SERVER: &str = "on_conn_close_server"; | ||||
| 
 | ||||
| pub use config::{ManagerConfig, PeerConfig, SharedConfig}; | ||||
| 
 | ||||
| /// The common return of plugin.
 | ||||
| ///
 | ||||
| /// [Note]
 | ||||
| /// msg must be null if code is ERR_SUCCESS.
 | ||||
| /// The msg must be freed by caller if it is not null.
 | ||||
| #[repr(C)] | ||||
| pub struct PluginReturn { | ||||
|     pub code: i32, | ||||
|     pub msg: *const c_char, | ||||
| } | ||||
| 
 | ||||
| impl PluginReturn { | ||||
|     pub fn success() -> Self { | ||||
|         PluginReturn { | ||||
|             code: errno::ERR_SUCCESS, | ||||
|             msg: null(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn new(code: i32, msg: &str) -> Self { | ||||
|         let mut msg = msg.as_bytes().to_vec(); | ||||
|         msg.push(0); | ||||
|         let p = unsafe { | ||||
|             let p = libc::malloc(msg.len()) as *mut c_char; | ||||
|             libc::memcpy( | ||||
|                 p as *mut libc::c_void, | ||||
|                 msg.as_ptr() as *const libc::c_void, | ||||
|                 msg.len(), | ||||
|             ); | ||||
|             p as *const c_char | ||||
|         }; | ||||
|         Self { code, msg: p } | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub fn is_success(&self) -> bool { | ||||
|         self.code == errno::ERR_SUCCESS | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[inline] | ||||
| fn cstr_to_string(cstr: *const c_char) -> ResultType<String> { | ||||
|     Ok(String::from_utf8(unsafe { | ||||
| @ -51,34 +94,6 @@ fn str_to_cstr_ret(s: &str) -> *const c_char { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[inline] | ||||
| pub fn make_return_code_msg(code: i32, msg: &str) -> *const c_void { | ||||
|     let mut out = code.to_le_bytes().to_vec(); | ||||
|     out.extend(msg.as_bytes()); | ||||
|     out.push(0); | ||||
|     unsafe { | ||||
|         let r = libc::malloc(out.len()) as *mut c_char; | ||||
|         libc::memcpy( | ||||
|             r as *mut libc::c_void, | ||||
|             out.as_ptr() as *const libc::c_void, | ||||
|             out.len(), | ||||
|         ); | ||||
|         r as *const c_void | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[inline] | ||||
| fn get_code_msg_from_ret(ret: *const c_void) -> (i32, String) { | ||||
|     assert!(ret.is_null() == false); | ||||
|     let code_bytes = unsafe { std::slice::from_raw_parts(ret as *const u8, 4) }; | ||||
|     let code = i32::from_le_bytes([code_bytes[0], code_bytes[1], code_bytes[2], code_bytes[3]]); | ||||
|     let msg = unsafe { CStr::from_ptr((ret as *const u8).add(4) as _) } | ||||
|         .to_str() | ||||
|         .unwrap_or("") | ||||
|         .to_string(); | ||||
|     (code, msg) | ||||
| } | ||||
| 
 | ||||
| #[inline] | ||||
| fn free_c_ptr(ret: *mut c_void) { | ||||
|     if !ret.is_null() { | ||||
|  | ||||
| @ -38,7 +38,7 @@ struct PluginInfo { | ||||
| /// Return null ptr if success.
 | ||||
| /// Return the error message if failed.  `i32-String` without dash, i32 is a signed little-endian number, the String is utf8 string.
 | ||||
| /// The plugin allocate memory with `libc::malloc` and return the pointer.
 | ||||
| type PluginFuncInit = extern "C" fn(data: *const InitData) -> *const c_void; | ||||
| type PluginFuncInit = extern "C" fn(data: *const InitData) -> PluginReturn; | ||||
| /// Reset the plugin.
 | ||||
| ///
 | ||||
| /// data: The initialize data.
 | ||||
| @ -46,13 +46,13 @@ type PluginFuncInit = extern "C" fn(data: *const InitData) -> *const c_void; | ||||
| /// Return null ptr if success.
 | ||||
| /// Return the error message if failed.  `i32-String` without dash, i32 is a signed little-endian number, the String is utf8 string.
 | ||||
| /// The plugin allocate memory with `libc::malloc` and return the pointer.
 | ||||
| type PluginFuncReset = extern "C" fn(data: *const InitData) -> *const c_void; | ||||
| type PluginFuncReset = extern "C" fn(data: *const InitData) -> PluginReturn; | ||||
| /// Clear the plugin.
 | ||||
| ///
 | ||||
| /// Return null ptr if success.
 | ||||
| /// Return the error message if failed.  `i32-String` without dash, i32 is a signed little-endian number, the String is utf8 string.
 | ||||
| /// The plugin allocate memory with `libc::malloc` and return the pointer.
 | ||||
| type PluginFuncClear = extern "C" fn() -> *const c_void; | ||||
| type PluginFuncClear = extern "C" fn() -> PluginReturn; | ||||
| /// Get the description of the plugin.
 | ||||
| /// Return the description. The plugin allocate memory with `libc::malloc` and return the pointer.
 | ||||
| type PluginFuncDesc = extern "C" fn() -> *const c_char; | ||||
| @ -74,7 +74,7 @@ type CallbackMsg = extern "C" fn( | ||||
|     id: *const c_char, | ||||
|     content: *const c_void, | ||||
|     len: usize, | ||||
| ) -> *const c_void; | ||||
| ) -> PluginReturn; | ||||
| /// Callback to get the config.
 | ||||
| /// peer, key are utf8 strings(null terminated).
 | ||||
| ///
 | ||||
| @ -123,7 +123,7 @@ type PluginFuncClientCall = extern "C" fn( | ||||
|     peer: *const c_char, | ||||
|     args: *const c_void, | ||||
|     len: usize, | ||||
| ) -> *const c_void; | ||||
| ) -> PluginReturn; | ||||
| /// The main function of the plugin on the server(remote) side.
 | ||||
| ///
 | ||||
| /// method: The method. "handle_ui" or "handle_peer"
 | ||||
| @ -144,7 +144,7 @@ type PluginFuncServerCall = extern "C" fn( | ||||
|     len: usize, | ||||
|     out: *mut *mut c_void, | ||||
|     out_len: *mut usize, | ||||
| ) -> *const c_void; | ||||
| ) -> PluginReturn; | ||||
| 
 | ||||
| /// The plugin callbacks.
 | ||||
| /// msg: The callback to send message to peer or ui.
 | ||||
| @ -223,13 +223,13 @@ macro_rules! make_plugin { | ||||
| 
 | ||||
|             fn init(&self, data: &InitData, path: &str) -> ResultType<()> { | ||||
|                 let init_ret = (self.init)(data as _); | ||||
|                 if !init_ret.is_null() { | ||||
|                     let (code, msg) = get_code_msg_from_ret(init_ret); | ||||
|                     free_c_ptr(init_ret as _); | ||||
|                 if !init_ret.is_success() { | ||||
|                     let msg = cstr_to_string(init_ret.msg).unwrap_or_default(); | ||||
|                     free_c_ptr(init_ret.msg as _); | ||||
|                     bail!( | ||||
|                         "Failed to init plugin {}, code: {}, msg: {}", | ||||
|                         path, | ||||
|                         code, | ||||
|                         init_ret.code, | ||||
|                         msg | ||||
|                     ); | ||||
|                 } | ||||
| @ -238,13 +238,13 @@ macro_rules! make_plugin { | ||||
| 
 | ||||
|             fn clear(&self, id: &str) { | ||||
|                 let clear_ret = (self.clear)(); | ||||
|                 if !clear_ret.is_null() { | ||||
|                     let (code, msg) = get_code_msg_from_ret(clear_ret); | ||||
|                     free_c_ptr(clear_ret as _); | ||||
|                 if !clear_ret.is_success() { | ||||
|                     let msg = cstr_to_string(clear_ret.msg).unwrap_or_default(); | ||||
|                     free_c_ptr(clear_ret.msg as _); | ||||
|                     log::error!( | ||||
|                         "Failed to clear plugin {}, code: {}, msg: {}", | ||||
|                         id, | ||||
|                         code, | ||||
|                         clear_ret.code, | ||||
|                         msg | ||||
|                     ); | ||||
|                 } | ||||
| @ -413,16 +413,16 @@ fn handle_event(method: &[u8], id: &str, peer: &str, event: &[u8]) -> ResultType | ||||
|                 event.as_ptr() as _, | ||||
|                 event.len(), | ||||
|             ); | ||||
|             if ret.is_null() { | ||||
|             if ret.is_success() { | ||||
|                 Ok(()) | ||||
|             } else { | ||||
|                 let (code, msg) = get_code_msg_from_ret(ret); | ||||
|                 free_c_ptr(ret as _); | ||||
|                 let msg = cstr_to_string(ret.msg).unwrap_or_default(); | ||||
|                 free_c_ptr(ret.msg as _); | ||||
|                 bail!( | ||||
|                     "Failed to handle plugin event, id: {}, method: {}, code: {}, msg: {}", | ||||
|                     id, | ||||
|                     std::string::String::from_utf8(method.to_vec()).unwrap_or_default(), | ||||
|                     code, | ||||
|                     ret.code, | ||||
|                     msg | ||||
|                 ); | ||||
|             } | ||||
| @ -469,14 +469,14 @@ fn _handle_listen_event(event: String, peer: String) { | ||||
|                         evt_bytes.as_ptr() as _, | ||||
|                         evt_bytes.len(), | ||||
|                     ); | ||||
|                     if !ret.is_null() { | ||||
|                         let (code, msg) = get_code_msg_from_ret(ret); | ||||
|                         free_c_ptr(ret as _); | ||||
|                     if !ret.is_success() { | ||||
|                         let msg = cstr_to_string(ret.msg).unwrap_or_default(); | ||||
|                         free_c_ptr(ret.msg as _); | ||||
|                         log::error!( | ||||
|                             "Failed to handle plugin listen event, id: {}, event: {}, code: {}, msg: {}", | ||||
|                             id, | ||||
|                             event, | ||||
|                             code, | ||||
|                             ret.code, | ||||
|                             msg | ||||
|                         ); | ||||
|                     } | ||||
| @ -510,18 +510,18 @@ pub fn handle_client_event(id: &str, peer: &str, event: &[u8]) -> Message { | ||||
|                 &mut out as _, | ||||
|                 &mut out_len as _, | ||||
|             ); | ||||
|             if ret.is_null() { | ||||
|             if ret.is_success() { | ||||
|                 let msg = make_plugin_request(id, out, out_len); | ||||
|                 free_c_ptr(out as _); | ||||
|                 msg | ||||
|             } else { | ||||
|                 let (code, msg) = get_code_msg_from_ret(ret); | ||||
|                 free_c_ptr(ret as _); | ||||
|                 if code > ERR_RUSTDESK_HANDLE_BASE && code < ERR_PLUGIN_HANDLE_BASE { | ||||
|                 let msg = cstr_to_string(ret.msg).unwrap_or_default(); | ||||
|                 free_c_ptr(ret.msg as _); | ||||
|                 if ret.code > ERR_RUSTDESK_HANDLE_BASE && ret.code < ERR_PLUGIN_HANDLE_BASE { | ||||
|                     log::debug!( | ||||
|                         "Plugin {} failed to handle client event, code: {}, msg: {}", | ||||
|                         id, | ||||
|                         code, | ||||
|                         ret.code, | ||||
|                         msg | ||||
|                     ); | ||||
|                     let name = match PLUGIN_INFO.read().unwrap().get(id) { | ||||
| @ -529,7 +529,7 @@ pub fn handle_client_event(id: &str, peer: &str, event: &[u8]) -> Message { | ||||
|                         None => "???", | ||||
|                     } | ||||
|                     .to_owned(); | ||||
|                     match code { | ||||
|                     match ret.code { | ||||
|                         ERR_CALL_NOT_SUPPORTED_METHOD => { | ||||
|                             make_plugin_failure(id, &name, "Plugin method is not supported") | ||||
|                         } | ||||
| @ -542,7 +542,7 @@ pub fn handle_client_event(id: &str, peer: &str, event: &[u8]) -> Message { | ||||
|                     log::error!( | ||||
|                         "Plugin {} failed to handle client event, code: {}, msg: {}", | ||||
|                         id, | ||||
|                         code, | ||||
|                         ret.code, | ||||
|                         msg | ||||
|                     ); | ||||
|                     let msg = make_plugin_request(id, out, out_len); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user