dittolive_ditto/identity/auth/
login_provider.rs1use std::{
2 os::raw::{c_uint, c_void},
3 sync::Arc,
4 time::Duration,
5};
6
7use extern_c::extern_c;
8use ffi_sdk::{ffi_utils::Blocking, BoxedLoginProvider};
9
10use crate::{identity::DittoAuthenticator, utils::prelude::*};
11
12pub trait DittoAuthenticationEventHandler: Send + Sync {
16 fn authentication_required(&self, auth: DittoAuthenticator);
19
20 fn authentication_expiring_soon(&self, auth: DittoAuthenticator, seconds_remaining: Duration);
22}
23
24pub(crate) struct LoginProvider(pub(crate) BoxedLoginProvider);
25
26pub(crate) struct LoginProviderCtx {
29 auth_event_handler: Arc<dyn DittoAuthenticationEventHandler + 'static>,
32 authenticator: DittoAuthenticator,
34}
35
36impl LoginProvider {
37 pub fn new(
38 auth_event_handler: Arc<dyn 'static + DittoAuthenticationEventHandler>,
39 authenticator: DittoAuthenticator,
40 ) -> Self {
41 let login_provider_ctx = Arc::new(LoginProviderCtx {
42 auth_event_handler,
43 authenticator,
44 });
45
46 let c_provider = unsafe {
47 ffi_sdk::ditto_auth_client_make_login_provider(
48 Arc::as_ptr(&login_provider_ctx) as *mut c_void,
50 Some(extern_c(|ctx: *mut c_void, _: Blocking| {
51 Arc::<LoginProviderCtx>::increment_strong_count(ctx.cast())
52 })),
53 Some(extern_c(|ctx: *mut c_void, _: Blocking| {
54 Arc::<LoginProviderCtx>::decrement_strong_count(ctx.cast())
55 })),
56 extern_c(|ctx: *mut c_void, secs_remaining: c_uint, _: Blocking| {
57 let LoginProviderCtx {
58 auth_event_handler,
59 authenticator,
60 }: &LoginProviderCtx = &*ctx.cast();
61 let authenticator = authenticator.retain();
62 if let Some(duration) =
63 (secs_remaining != 0).then(|| Duration::from_secs(secs_remaining.into()))
64 {
65 auth_event_handler.authentication_expiring_soon(authenticator, duration);
66 } else {
67 auth_event_handler.authentication_required(authenticator);
68 }
69 }),
70 )
71 };
72 LoginProvider(c_provider)
73 }
74}