diff --git a/src/lib.rs b/src/lib.rs index ec70d1179..31ad83bca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,13 +48,6 @@ mod license; #[cfg(not(any(target_os = "android", target_os = "ios")))] mod port_forward; -#[cfg(not(any(target_os = "android", target_os = "ios")))] -#[cfg(any(feature = "flutter"))] -pub mod api; -#[cfg(not(any(target_os = "android", target_os = "ios")))] -#[cfg(any(feature = "flutter"))] -pub mod plugins; - #[cfg(all(feature = "flutter", feature = "plugin_framework"))] #[cfg(not(any(target_os = "android", target_os = "ios")))] pub mod plugin; diff --git a/src/plugin/native_handlers/macros.rs b/src/plugin/native_handlers/macros.rs new file mode 100644 index 000000000..82d7e10a6 --- /dev/null +++ b/src/plugin/native_handlers/macros.rs @@ -0,0 +1,27 @@ +#[macro_export] +macro_rules! return_if_not_method { + ($call: ident, $prefix: ident) => { + if $call.starts_with($prefix) { + return None; + } + }; +} + +#[macro_export] +macro_rules! call_if_method { + ($call: ident ,$method: literal, $block: block) => { + if ($call != $method) { + $block + } + }; +} + +#[macro_export] +macro_rules! define_method_prefix { + ($prefix: literal) => { + #[inline] + fn method_prefix(&self) -> &'static str { + $prefix + } + }; +} diff --git a/src/plugin/native_handlers/mod.rs b/src/plugin/native_handlers/mod.rs index 9f7011cb2..36fd2cebe 100644 --- a/src/plugin/native_handlers/mod.rs +++ b/src/plugin/native_handlers/mod.rs @@ -1,24 +1,126 @@ -use std::ffi::{c_void, c_ulonglong, c_ulong}; +use std::{ + ffi::c_void, + sync::{Arc, RwLock}, + vec, +}; +use hbb_common::libc::c_char; +use lazy_static::lazy_static; use serde_json::Map; +use crate::return_if_not_method; + +use self::session::PluginNativeSessionHandler; + +use super::cstr_to_string; + +mod macros; pub mod session; pub type NR = super::native::NativeReturnValue; -pub type PluginNativeHandlerRegistrar = NativeHandlerRegistrar; +pub type PluginNativeHandlerRegistrar = NativeHandlerRegistrar>; -pub struct NativeHandlerRegistrar{ - handlers: Vec +lazy_static! { + static ref NATIVE_HANDLERS_REGISTRAR: Arc = + Arc::new(PluginNativeHandlerRegistrar::default()); } -pub(crate) trait PluginNativeHandler { +#[derive(Clone)] +pub struct NativeHandlerRegistrar { + handlers: Arc>>, +} + +impl Default for PluginNativeHandlerRegistrar { + fn default() -> Self { + Self { + handlers: Arc::new(RwLock::new(vec![Box::new( + PluginNativeSessionHandler::default(), + )])), + } + } +} + +pub(self) trait PluginNativeHandler { + /// The method prefix handled by this handler.s + fn method_prefix(&self) -> &'static str; + /// Try to handle the method with the given data. - /// + /// /// Returns: None for the message does not be handled by this handler. - fn on_message(method: &String, data: &Map) -> Option; + fn on_message(&self, method: &str, data: &Map) -> Option; /// Try to handle the method with the given data and extra void binary data. - /// + /// /// Returns: None for the message does not be handled by this handler. - fn on_message_raw(method: &String, data: &Map, raw: *const c_void, raw_len: usize) -> Option; -} \ No newline at end of file + fn on_message_raw( + &self, + method: &str, + data: &Map, + raw: *const c_void, + raw_len: usize, + ) -> Option; +} + +pub(crate) trait Callable { + fn call( + &self, + method: &String, + json: *const c_char, + raw: *const c_void, + raw_len: usize, + ) -> Option { + None + } +} + +impl Callable for T +where + T: PluginNativeHandler + Send + Sync, +{ + fn call( + &self, + method: &String, + json: *const c_char, + raw: *const c_void, + raw_len: usize, + ) -> Option { + let prefix = self.method_prefix(); + return_if_not_method!(method, prefix); + match cstr_to_string(json) { + Ok(s) => { + if let Ok(json) = serde_json::from_str(s.as_str()) { + let method_suffix = &method[prefix.len()..]; + if raw != std::ptr::null() && raw_len > 0 { + return self.on_message_raw(method_suffix, &json, raw, raw_len); + } else { + return self.on_message(method_suffix, &json); + } + } else { + return None; + } + } + Err(_) => return None, + } + } +} + +impl Callable for NativeHandlerRegistrar +where + C: Callable, +{ + fn call( + &self, + method: &String, + json: *const c_char, + raw: *const c_void, + raw_len: usize, + ) -> Option { + for handler in self.handlers.read().unwrap().iter() { + let ret = handler.call(method, json, raw, raw_len); + if ret.is_some() { + return ret; + } + } + None + } +} diff --git a/src/plugin/native_handlers/session.rs b/src/plugin/native_handlers/session.rs index f8e8baa67..fc6f49014 100644 --- a/src/plugin/native_handlers/session.rs +++ b/src/plugin/native_handlers/session.rs @@ -1,28 +1,35 @@ +use crate::{call_if_method, define_method_prefix, return_if_not_method}; + use super::PluginNativeHandler; - +#[derive(Default)] /// Session related handler for librustdesk core. pub struct PluginNativeSessionHandler; - impl PluginNativeHandler for PluginNativeSessionHandler { - fn on_message(method: &String, data: &serde_json::Map) -> Option { + define_method_prefix!("session_"); + + fn on_message( + &self, + method: &str, + data: &serde_json::Map, + ) -> Option { None } - fn on_message_raw(method: &String, data: &serde_json::Map, raw: *const std::ffi::c_void, raw_len: usize) -> Option { + fn on_message_raw( + &self, + method: &str, + data: &serde_json::Map, + raw: *const std::ffi::c_void, + raw_len: usize, + ) -> Option { None } - } impl PluginNativeSessionHandler { - fn create_session() { + fn create_session() {} - } - - - fn add_session_hook() { - - } -} \ No newline at end of file + fn add_session_hook() {} +}