1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::{
os::raw::{c_uint, c_void},
pin::Pin,
sync::{Arc, Mutex},
time::Duration,
};
use ffi_sdk::BoxedLoginProvider;
use crate::{auth::authenticator::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) _provider: BoxedLoginProvider,
pub(crate) ctx: Arc<Mutex<LoginProviderCtx>>,
}
pub(crate) struct LoginProviderCtx {
auth_event_handler: Pin<Box<dyn DittoAuthenticationEventHandler + 'static>>,
authenticator: Option<DittoAuthenticator>,
#[allow(dead_code)] cached_expiry_time: Option<u32>,
}
impl LoginProvider {
pub fn new(handler: Box<dyn DittoAuthenticationEventHandler + 'static>) -> Self {
let ctx = LoginProviderCtx {
auth_event_handler: handler.into(),
authenticator: None,
cached_expiry_time: None,
};
let arc_ctx = Arc::new(Mutex::new(ctx));
let raw_context = Arc::as_ptr(&arc_ctx) as *mut c_void;
let c_provider = unsafe {
ffi_sdk::ditto_auth_client_make_login_provider(
raw_context,
Some(LoginProviderCtx::retain),
Some(LoginProviderCtx::release),
LoginProviderCtx::authentication_expiring,
)
};
LoginProvider {
_provider: c_provider,
ctx: arc_ctx,
}
}
}
impl LoginProviderCtx {
pub(crate) extern "C" fn retain(ctx: *mut c_void) {
let ptr = ctx.cast::<Mutex<LoginProviderCtx>>();
unsafe { Arc::increment_strong_count(ptr) }; }
pub(crate) extern "C" fn release(ctx: *mut c_void) {
let ptr = ctx.cast::<Mutex<LoginProviderCtx>>();
unsafe {
Arc::decrement_strong_count(ptr);
} }
pub(crate) extern "C" fn authentication_expiring(ctx: *mut c_void, seconds_remaining: c_uint) {
let ctx_ptr: *const Mutex<LoginProviderCtx> = ctx.cast();
let arc_ctx: &Mutex<LoginProviderCtx> = unsafe { &*ctx_ptr }; let mut ctx_ref = arc_ctx.lock().expect("LoginProvider Mutex is poisoned"); match &ctx_ref.authenticator {
Some(authn) => {
if seconds_remaining == 0 {
ctx_ref
.auth_event_handler
.authentication_required(authn.retain());
} else {
let duration = Duration::from_secs(seconds_remaining.into());
ctx_ref
.auth_event_handler
.authentication_expiring_soon(authn.retain(), duration);
}
}
None => ctx_ref.cached_expiry_time = Some(seconds_remaining),
}
}
pub(crate) fn set_authenticator(&mut self, authenticator: DittoAuthenticator) {
self.authenticator = Some(authenticator);
if let Some(authn) = &self.authenticator {
if let Some(time) = self.cached_expiry_time {
if time == 0 {
self.auth_event_handler
.authentication_required(authn.retain());
} else {
let duration = Duration::from_secs(time.into());
self.auth_event_handler
.authentication_expiring_soon(authn.retain(), duration);
}
self.cached_expiry_time = None; }
}
}
}