dittolive_ditto/identity/auth/
login_provider.rsuse std::{
os::raw::{c_uint, c_void},
sync::Arc,
time::Duration,
};
use extern_c::extern_c;
use ffi_sdk::BoxedLoginProvider;
use crate::{identity::DittoAuthenticator, utils::prelude::*};
pub trait DittoAuthenticationEventHandler: Send + Sync {
fn authentication_required(&self, auth: DittoAuthenticator);
fn authentication_expiring_soon(&self, auth: DittoAuthenticator, seconds_remaining: Duration);
}
pub(crate) struct LoginProvider(pub(crate) BoxedLoginProvider);
pub(crate) struct LoginProviderCtx {
auth_event_handler: Arc<dyn DittoAuthenticationEventHandler + 'static>,
authenticator: DittoAuthenticator,
}
impl LoginProvider {
pub fn new(
auth_event_handler: Arc<dyn 'static + DittoAuthenticationEventHandler>,
authenticator: DittoAuthenticator,
) -> Self {
let login_provider_ctx = Arc::new(LoginProviderCtx {
auth_event_handler,
authenticator,
});
let c_provider = unsafe {
ffi_sdk::ditto_auth_client_make_login_provider(
Arc::as_ptr(&login_provider_ctx) as *mut c_void,
Some(extern_c(|ctx: *mut c_void| {
Arc::<LoginProviderCtx>::increment_strong_count(ctx.cast())
})),
Some(extern_c(|ctx: *mut c_void| {
Arc::<LoginProviderCtx>::decrement_strong_count(ctx.cast())
})),
extern_c(|ctx: *mut c_void, secs_remaining: c_uint| {
let LoginProviderCtx {
auth_event_handler,
authenticator,
}: &LoginProviderCtx = &*ctx.cast();
let authenticator = authenticator.retain();
if let Some(duration) =
(secs_remaining != 0).then(|| Duration::from_secs(secs_remaining.into()))
{
auth_event_handler.authentication_expiring_soon(authenticator, duration);
} else {
auth_event_handler.authentication_required(authenticator);
}
}),
)
};
LoginProvider(c_provider)
}
}