diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index eaa565cbf..25a049c87 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -961,6 +961,14 @@ impl Remote { } }); } + + // on connection established client + #[cfg(all(feature = "flutter", feature = "plugin_framework"))] + #[cfg(not(any(target_os = "android", target_os = "ios")))] + crate::plugin::handle_listen_event( + crate::plugin::EVENT_ON_CONN_CLIENT, + &self.handler.id, + ); } if self.handler.is_file_transfer() { diff --git a/src/plugin/desc.rs b/src/plugin/desc.rs index 8308f6f14..5aee35b96 100644 --- a/src/plugin/desc.rs +++ b/src/plugin/desc.rs @@ -60,6 +60,7 @@ pub struct Desc { github: String, location: Location, config: Config, + listen_events: Vec, } impl Desc { @@ -115,4 +116,8 @@ impl Desc { pub fn config(&self) -> &Config { &self.config } + + pub fn listen_events(&self) -> &Vec { + &self.listen_events + } } diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs index ee93c19fd..898630910 100644 --- a/src/plugin/mod.rs +++ b/src/plugin/mod.rs @@ -5,13 +5,13 @@ mod callback_msg; mod config; pub mod desc; mod errno; -mod plog; pub mod ipc; +mod plog; mod plugins; pub use plugins::{ - handle_client_event, handle_server_event, handle_ui_event, load_plugin, load_plugins, - reload_plugin, sync_ui, unload_plugin, unload_plugins, + handle_client_event, handle_listen_event, handle_server_event, handle_ui_event, load_plugin, + load_plugins, reload_plugin, sync_ui, unload_plugin, unload_plugins, }; const MSG_TO_UI_TYPE_PLUGIN_DESC: &str = "plugin_desc"; @@ -19,6 +19,11 @@ const MSG_TO_UI_TYPE_PLUGIN_EVENT: &str = "plugin_event"; const MSG_TO_UI_TYPE_PLUGIN_RELOAD: &str = "plugin_reload"; const MSG_TO_UI_TYPE_PLUGIN_OPTION: &str = "plugin_option"; +pub const EVENT_ON_CONN_CLIENT: &str = "on_conn_client"; +pub const EVENT_ON_CONN_SERVER: &str = "on_conn_server"; +pub const EVENT_ON_CONN_CLOSE_CLIENT: &str = "on_conn_close_client"; +pub const EVENT_ON_CONN_CLOSE_SERVER: &str = "on_conn_close_server"; + pub use config::{ManagerConfig, PeerConfig, SharedConfig}; #[inline] @@ -29,7 +34,7 @@ fn cstr_to_string(cstr: *const c_char) -> ResultType { } #[inline] -pub fn str_to_cstr_ret(s: &str) -> *const c_char { +fn str_to_cstr_ret(s: &str) -> *const c_char { let mut s = s.as_bytes().to_vec(); s.push(0); unsafe { diff --git a/src/plugin/plugins.rs b/src/plugin/plugins.rs index a1a03c4f3..e0918defb 100644 --- a/src/plugin/plugins.rs +++ b/src/plugin/plugins.rs @@ -9,6 +9,7 @@ use hbb_common::{ message_proto::{Message, Misc, PluginFailure, PluginRequest}, ResultType, }; +use serde_derive::Serialize; use std::{ collections::HashMap, ffi::{c_char, c_void}, @@ -18,6 +19,7 @@ use std::{ const METHOD_HANDLE_UI: &[u8; 10] = b"handle_ui\0"; const METHOD_HANDLE_PEER: &[u8; 12] = b"handle_peer\0"; +pub const METHOD_HANDLE_LISTEN_EVENT: &[u8; 20] = b"handle_listen_event\0"; lazy_static::lazy_static! { static ref PLUGIN_INFO: Arc>> = Default::default(); @@ -249,6 +251,11 @@ make_plugin!( server_call: PluginFuncServerCall ); +#[derive(Serialize)] +pub struct MsgListenEvent { + pub event: String, +} + #[cfg(target_os = "windows")] const DYLIB_SUFFIX: &str = ".dll"; #[cfg(target_os = "linux")] @@ -415,6 +422,55 @@ pub fn handle_server_event(id: &str, peer: &str, event: &[u8]) -> ResultType<()> handle_event(METHOD_HANDLE_PEER, id, peer, event) } +#[inline] +pub fn handle_listen_event(event: &str, peer: &str) { + let mut plugins = Vec::new(); + for info in PLUGIN_INFO.read().unwrap().values() { + if info.desc.listen_events().contains(&event.to_string()) { + plugins.push(info.desc.id().to_string()); + } + } + + if plugins.is_empty() { + return; + } + + if let Ok(mut evt) = serde_json::to_string(&MsgListenEvent { + event: event.to_string(), + }) { + let mut evt_bytes = evt.as_bytes().to_vec(); + evt_bytes.push(0); + let mut peer: String = peer.to_owned(); + peer.push('\0'); + for id in plugins { + match PLUGINS.read().unwrap().get(&id) { + Some(plugin) => { + let ret = (plugin.client_call)( + METHOD_HANDLE_LISTEN_EVENT.as_ptr() as _, + peer.as_ptr() as _, + 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 _); + log::error!( + "Failed to handle plugin listen event, id: {}, event: {}, code: {}, msg: {}", + id, + event, + code, + msg + ); + } + } + None => { + log::error!("Plugin {} not found when handle_listen_event", id); + } + } + } + } +} + #[inline] pub fn handle_client_event(id: &str, peer: &str, event: &[u8]) -> Message { let mut peer: String = peer.to_owned(); diff --git a/src/server/connection.rs b/src/server/connection.rs index 4d4165c44..4e33c79bd 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -563,6 +563,12 @@ impl Connection { } else if video_privacy_conn_id == 0 { let _ = privacy_mode::turn_off_privacy(0); } + #[cfg(all(feature = "flutter", feature = "plugin_framework"))] + #[cfg(not(any(target_os = "android", target_os = "ios")))] + crate::plugin::handle_listen_event( + crate::plugin::EVENT_ON_CONN_CLOSE_SERVER, + &conn.lr.my_id, + ); video_service::notify_video_frame_fetched(id, None); scrap::codec::Encoder::update(id, scrap::codec::EncodingUpdate::Remove); video_service::VIDEO_QOS.lock().unwrap().reset();