-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FabricClient] Support FabricClient user notification callback (#70)
Support service notification callback and client connection notification callbacks. You can construct FabricClient with callbacks lambda functions like this: ```rs let fc = FabricClientBuilder::new() .with_on_service_notification(move |notification| { Ok(()) }) .with_on_client_connect(move |gw| { Ok(()) }) .with_on_client_disconnect(move |_| { Ok(()) }) .with_client_role(mssf_core::types::ClientRole::User).build() ``` with_on_service_notification callback is configured by register_service_notification_filter API.
- Loading branch information
Showing
10 changed files
with
554 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// ------------------------------------------------------------ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. | ||
// -------------------------------------------------- | ||
|
||
use mssf_com::FabricClient::{ | ||
IFabricClientConnectionEventHandler, IFabricClientConnectionEventHandler_Impl, | ||
IFabricGatewayInformationResult, | ||
}; | ||
|
||
use crate::{strings::HSTRINGWrap, types::NodeId}; | ||
|
||
/// Internal trait that rust code implements that can be bridged into IFabricClientConnectionEventHandler. | ||
/// Not exposed to user. | ||
pub trait ClientConnectionEventHandler: 'static { | ||
fn on_connected(&self, info: &GatewayInformationResult) -> crate::Result<()>; | ||
fn on_disconnected(&self, info: &GatewayInformationResult) -> crate::Result<()>; | ||
} | ||
|
||
/// FabricClient connection information. | ||
/// Traslated from IFabricGatewayInformationResult | ||
#[derive(Debug, Clone)] | ||
pub struct GatewayInformationResult { | ||
pub node_address: crate::HSTRING, | ||
pub node_id: NodeId, | ||
pub node_instance_id: u64, | ||
pub node_name: crate::HSTRING, | ||
} | ||
|
||
impl GatewayInformationResult { | ||
fn from_com(com: &IFabricGatewayInformationResult) -> Self { | ||
let info = unsafe { com.get_GatewayInformation().as_ref().unwrap() }; | ||
Self { | ||
node_address: HSTRINGWrap::from(info.NodeAddress).into(), | ||
node_id: info.NodeId.into(), | ||
node_instance_id: info.NodeInstanceId, | ||
node_name: HSTRINGWrap::from(info.NodeName).into(), | ||
} | ||
} | ||
} | ||
|
||
/// Bridge for IFabricClientConnectionEventHandler. | ||
/// Turn rust trait into SF com object. | ||
#[windows_core::implement(IFabricClientConnectionEventHandler)] | ||
pub struct ClientConnectionEventHandlerBridge<T> | ||
where | ||
T: ClientConnectionEventHandler, | ||
{ | ||
inner: T, | ||
} | ||
|
||
impl<T> ClientConnectionEventHandlerBridge<T> | ||
where | ||
T: ClientConnectionEventHandler, | ||
{ | ||
pub fn new(inner: T) -> Self { | ||
Self { inner } | ||
} | ||
pub fn new_com(inner: T) -> IFabricClientConnectionEventHandler { | ||
Self::new(inner).into() | ||
} | ||
} | ||
|
||
impl<T> IFabricClientConnectionEventHandler_Impl for ClientConnectionEventHandlerBridge<T> | ||
where | ||
T: ClientConnectionEventHandler, | ||
{ | ||
fn OnConnected( | ||
&self, | ||
gw_info: Option<&IFabricGatewayInformationResult>, | ||
) -> windows_core::Result<()> { | ||
let info = GatewayInformationResult::from_com(gw_info.unwrap()); | ||
self.inner.on_connected(&info) | ||
} | ||
|
||
fn OnDisconnected( | ||
&self, | ||
gw_info: Option<&IFabricGatewayInformationResult>, | ||
) -> windows_core::Result<()> { | ||
let info = GatewayInformationResult::from_com(gw_info.unwrap()); | ||
self.inner.on_disconnected(&info) | ||
} | ||
} | ||
|
||
/// Connection notification function signature to avoid code repeatition. | ||
/// Trait alias feature in rust (not yet stable) would eliminate this trait definition. | ||
pub trait ConnectionNotificationFn: | ||
Fn(&GatewayInformationResult) -> crate::Result<()> + 'static | ||
{ | ||
} | ||
impl<T: Fn(&GatewayInformationResult) -> crate::Result<()> + 'static> ConnectionNotificationFn | ||
for T | ||
{ | ||
} | ||
|
||
/// Lambda implementation of the ClientConnectionEventHandler trait. | ||
/// This is used in FabricClientBuilder to build handler from functions. | ||
pub struct LambdaClientConnectionNotificationHandler { | ||
f_conn: Option<Box<dyn ConnectionNotificationFn>>, | ||
f_disconn: Option<Box<dyn ConnectionNotificationFn>>, | ||
} | ||
|
||
impl LambdaClientConnectionNotificationHandler { | ||
pub fn new() -> Self { | ||
Self { | ||
f_conn: None, | ||
f_disconn: None, | ||
} | ||
} | ||
|
||
/// Set the on_connected callback. | ||
pub fn set_f_conn(&mut self, f: impl ConnectionNotificationFn) { | ||
self.f_conn = Some(Box::new(f)); | ||
} | ||
|
||
/// Set the on_disconnected callback. | ||
pub fn set_f_disconn(&mut self, f: impl ConnectionNotificationFn) { | ||
self.f_disconn = Some(Box::new(f)); | ||
} | ||
} | ||
|
||
impl ClientConnectionEventHandler for LambdaClientConnectionNotificationHandler { | ||
fn on_connected(&self, info: &GatewayInformationResult) -> crate::Result<()> { | ||
if let Some(f) = &self.f_conn { | ||
f(info) | ||
} else { | ||
Ok(()) | ||
} | ||
} | ||
|
||
fn on_disconnected(&self, info: &GatewayInformationResult) -> crate::Result<()> { | ||
if let Some(f) = &self.f_disconn { | ||
f(info) | ||
} else { | ||
Ok(()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.