diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 1f323b7a9..0b0de28a1 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -605,7 +605,7 @@ message PluginRequest { bytes content = 2; } -message PluginResponse { +message PluginFailure { string id = 1; string name = 2; string msg = 3; @@ -633,7 +633,7 @@ message Misc { SwitchBack switch_back = 22; Resolution change_resolution = 24; PluginRequest plugin_request = 25; - PluginResponse plugin_response = 26; + PluginFailure plugin_failure = 26; } } diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 856c20c3f..eaa565cbf 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -1301,12 +1301,16 @@ impl Remote { #[cfg(all(feature = "flutter", feature = "plugin_framework"))] #[cfg(not(any(target_os = "android", target_os = "ios")))] Some(misc::Union::PluginRequest(p)) => { - allow_err!(crate::plugin::handle_server_event(&p.id, &self.handler.id, &p.content)); + allow_err!(crate::plugin::handle_server_event( + &p.id, + &self.handler.id, + &p.content + )); // to-do: show message box on UI when error occurs? } #[cfg(all(feature = "flutter", feature = "plugin_framework"))] #[cfg(not(any(target_os = "android", target_os = "ios")))] - Some(misc::Union::PluginResponse(p)) => { + Some(misc::Union::PluginFailure(p)) => { let name = if p.name.is_empty() { "plugin".to_string() } else { diff --git a/src/plugin/callback_msg.rs b/src/plugin/callback_msg.rs index 7c0109688..df4b21c73 100644 --- a/src/plugin/callback_msg.rs +++ b/src/plugin/callback_msg.rs @@ -36,13 +36,13 @@ lazy_static::lazy_static! { }; } -#[derive(Deserialize)] +#[derive(Debug, Deserialize)] struct ConfigToUi { channel: u16, location: String, } -#[derive(Deserialize)] +#[derive(Debug, Deserialize)] struct MsgToConfig { id: String, r#type: String, @@ -83,6 +83,8 @@ pub(super) extern "C" fn cb_msg( cb_msg_field!(target); cb_msg_field!(id); + println!("REMOVE ME ========================== cb_msg peer: {}, target: {}", peer, target); + match &target as _ { MSG_TO_PEER_TARGET => { if let Some(session) = SESSIONS.write().unwrap().get_mut(&peer) { @@ -102,6 +104,7 @@ pub(super) extern "C" fn cb_msg( let channel = u16::from_be_bytes([content_slice[0], content_slice[1]]); let content = std::string::String::from_utf8(content_slice[2..].to_vec()) .unwrap_or("".to_string()); + println!("REMOVE ME ========================== cb_msg peer: {}, to ui: {}", peer, &content); push_event_to_ui(channel, &peer, &content); } MSG_TO_CONFIG_TARGET => { @@ -110,6 +113,7 @@ pub(super) extern "C" fn cb_msg( { // No need to merge the msgs. Handling the msg one by one is ok. if let Ok(msg) = serde_json::from_str::(s) { + println!("REMOVE ME ========================== cb_msg peer: {}, config: {:?}", peer, &msg); match &msg.r#type as _ { config::CONFIG_TYPE_SHARED => { match config::SharedConfig::set(&msg.id, &msg.key, &msg.value) { diff --git a/src/plugin/plugins.rs b/src/plugin/plugins.rs index 4fb69a943..a1a03c4f3 100644 --- a/src/plugin/plugins.rs +++ b/src/plugin/plugins.rs @@ -6,7 +6,7 @@ use hbb_common::{ allow_err, bail, dlopen::symbor::Library, lazy_static, log, - message_proto::{Message, Misc, PluginResponse}, + message_proto::{Message, Misc, PluginFailure, PluginRequest}, ResultType, }; use std::{ @@ -89,20 +89,43 @@ type CallbackGetId = extern "C" fn() -> *const c_char; /// level: "error", "warn", "info", "debug", "trace". /// msg: The message. type CallbackLog = extern "C" fn(level: *const c_char, msg: *const c_char); -/// The main function of the plugin. +/// The main function of the plugin on the client(self) side. +/// /// method: The method. "handle_ui" or "handle_peer" /// peer: The peer id. /// args: The arguments. +/// len: The length of the arguments. /// /// 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 PluginFuncCall = extern "C" fn( +type PluginFuncClientCall = extern "C" fn( method: *const c_char, peer: *const c_char, args: *const c_void, len: usize, ) -> *const c_void; +/// The main function of the plugin on the server(remote) side. +/// +/// method: The method. "handle_ui" or "handle_peer" +/// peer: The peer id. +/// args: The arguments. +/// len: The length of the arguments. +/// out: The output. +/// The plugin allocate memory with `libc::malloc` and return the pointer. +/// out_len: The length of the output. +/// +/// 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 PluginFuncServerCall = extern "C" fn( + method: *const c_char, + peer: *const c_char, + args: *const c_void, + len: usize, + out: *mut *mut c_void, + out_len: *mut usize, +) -> *const c_void; /// The plugin callbacks. /// msg: The callback to send message to peer or ui. @@ -222,7 +245,8 @@ make_plugin!( reset: PluginFuncReset, clear: PluginFuncClear, desc: PluginFuncDesc, - call: PluginFuncCall + client_call: PluginFuncClientCall, + server_call: PluginFuncServerCall ); #[cfg(target_os = "windows")] @@ -357,7 +381,7 @@ fn handle_event(method: &[u8], id: &str, peer: &str, event: &[u8]) -> ResultType peer.push('\0'); match PLUGINS.read().unwrap().get(id) { Some(plugin) => { - let ret = (plugin.call)( + let ret = (plugin.client_call)( method.as_ptr() as _, peer.as_ptr() as _, event.as_ptr() as _, @@ -392,19 +416,25 @@ pub fn handle_server_event(id: &str, peer: &str, event: &[u8]) -> ResultType<()> } #[inline] -pub fn handle_client_event(id: &str, peer: &str, event: &[u8]) -> Option { +pub fn handle_client_event(id: &str, peer: &str, event: &[u8]) -> Message { let mut peer: String = peer.to_owned(); peer.push('\0'); match PLUGINS.read().unwrap().get(id) { Some(plugin) => { - let ret = (plugin.call)( + let mut out = std::ptr::null_mut(); + let mut out_len: usize = 0; + let ret = (plugin.server_call)( METHOD_HANDLE_PEER.as_ptr() as _, peer.as_ptr() as _, event.as_ptr() as _, event.len(), + &mut out as _, + &mut out_len as _, ); if ret.is_null() { - None + 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 _); @@ -421,17 +451,13 @@ pub fn handle_client_event(id: &str, peer: &str, event: &[u8]) -> Option Some(make_plugin_response( - id, - &name, - "plugin method is not supported", - )), - ERR_CALL_INVALID_ARGS => Some(make_plugin_response( - id, - &name, - "plugin arguments is invalid", - )), - _ => Some(make_plugin_response(id, &name, &msg)), + ERR_CALL_NOT_SUPPORTED_METHOD => { + make_plugin_failure(id, &name, "Plugin method is not supported") + } + ERR_CALL_INVALID_ARGS => { + make_plugin_failure(id, &name, "Plugin arguments is invalid") + } + _ => make_plugin_failure(id, &name, &msg), } } else { log::error!( @@ -440,17 +466,33 @@ pub fn handle_client_event(id: &str, peer: &str, event: &[u8]) -> Option Some(make_plugin_response(id, "", "plugin not found")), + None => make_plugin_failure(id, "", "Plugin not found"), } } -fn make_plugin_response(id: &str, name: &str, msg: &str) -> Message { +fn make_plugin_request(id: &str, content: *const c_void, len: usize) -> Message { let mut misc = Misc::new(); - misc.set_plugin_response(PluginResponse { + misc.set_plugin_request(PluginRequest { + id: id.to_owned(), + content: unsafe { std::slice::from_raw_parts(content as *const u8, len) } + .clone() + .into(), + ..Default::default() + }); + let mut msg_out = Message::new(); + msg_out.set_misc(misc); + msg_out +} + +fn make_plugin_failure(id: &str, name: &str, msg: &str) -> Message { + let mut misc = Misc::new(); + misc.set_plugin_failure(PluginFailure { id: id.to_owned(), name: name.to_owned(), msg: msg.to_owned(), diff --git a/src/server/connection.rs b/src/server/connection.rs index e128f511a..4d4165c44 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1813,11 +1813,9 @@ impl Connection { #[cfg(all(feature = "flutter", feature = "plugin_framework"))] #[cfg(not(any(target_os = "android", target_os = "ios")))] Some(misc::Union::PluginRequest(p)) => { - if let Some(msg) = - crate::plugin::handle_client_event(&p.id, &self.lr.my_id, &p.content) - { - self.send(msg).await; - } + let msg = + crate::plugin::handle_client_event(&p.id, &self.lr.my_id, &p.content); + self.send(msg).await; } _ => {} },