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
use std::{
    os::raw::{c_int, c_void},
    sync::{Arc, RwLock, Weak},
};

use crate::{ditto::DittoHandleWrapper, transport::TransportSync};

// TODO(pub_check)
pub struct ValidityListener(Weak<RwLock<TransportSync>>);

impl ValidityListener {
    // TODO(pub_check)
    pub fn new(
        transport: Weak<RwLock<TransportSync>>,
        ditto: &DittoHandleWrapper,
    ) -> Arc<ValidityListener> {
        let this = Arc::new(ValidityListener(transport));
        let this_ptr = Arc::as_ptr(&this) as *mut c_void;

        extern "C" fn on_validity_update(ctx: *mut c_void, web_valid: c_int, x509_valid: c_int) {
            let ctx_ref: &ValidityListener =
                unsafe { ctx.cast::<ValidityListener>().as_ref().expect("Got Null") }; // only safe if ValidityListener not dropped
            {
                if let Some(transport) = ctx_ref.0.upgrade() {
                    let mut lock = transport.write().expect("Poisoned Transport Lock");
                    lock.validity_updated(web_valid != 0, x509_valid != 0);
                }
            }
        }

        extern "C" fn retain(ctx: *mut c_void) {
            let ptr = ctx.cast::<ValidityListener>();
            unsafe {
                Arc::increment_strong_count(ptr);
            }
        }
        extern "C" fn release(ctx: *mut c_void) {
            let ptr = ctx.cast::<ValidityListener>();
            unsafe {
                Arc::decrement_strong_count(ptr);
            }
        }

        unsafe {
            ffi_sdk::ditto_auth_client_set_validity_listener(
                &*ditto,
                this_ptr,
                Some(retain),
                Some(release),
                Some(on_validity_update),
            );
        }
        this
    }
}