1 use crate::error
::ErrorStack
;
2 use foreign_types
::{ForeignType, ForeignTypeRef}
;
3 use libc
::{c_char, c_int, c_void}
;
5 use std
::panic
::{self, AssertUnwindSafe}
;
8 /// Wraps a user-supplied callback and a slot for panics thrown inside the callback (while FFI
9 /// frames are on the stack).
11 /// When dropped, checks if the callback has panicked, and resumes unwinding if so.
12 pub struct CallbackState
<F
> {
13 /// The user callback. Taken out of the `Option` when called.
15 /// If the callback panics, we place the panic object here, to be re-thrown once OpenSSL
17 panic
: Option
<Box
<dyn Any
+ Send
+ '
static>>,
20 impl<F
> CallbackState
<F
> {
21 pub fn new(callback
: F
) -> Self {
29 impl<F
> Drop
for CallbackState
<F
> {
31 if let Some(panic
) = self.panic
.take() {
32 panic
::resume_unwind(panic
);
37 /// Password callback function, passed to private key loading functions.
39 /// `cb_state` is expected to be a pointer to a `CallbackState`.
40 pub unsafe extern "C" fn invoke_passwd_cb
<F
>(
44 cb_state
: *mut c_void
,
47 F
: FnOnce(&mut [u8]) -> Result
<usize, ErrorStack
>,
49 let callback
= &mut *(cb_state
as *mut CallbackState
<F
>);
51 let result
= panic
::catch_unwind(AssertUnwindSafe(|| {
52 let pass_slice
= slice
::from_raw_parts_mut(buf
as *mut u8, size
as usize);
53 callback
.cb
.take().unwrap()(pass_slice
)
57 Ok(Ok(len
)) => len
as c_int
,
59 // FIXME restore error stack
63 callback
.panic
= Some(err
);
69 pub trait ForeignTypeExt
: ForeignType
{
70 unsafe fn from_ptr_opt(ptr
: *mut Self::CType
) -> Option
<Self> {
74 Some(Self::from_ptr(ptr
))
78 impl<FT
: ForeignType
> ForeignTypeExt
for FT {}
80 pub trait ForeignTypeRefExt
: ForeignTypeRef
{
81 unsafe fn from_const_ptr
<'a
>(ptr
: *const Self::CType
) -> &'a
Self {
82 Self::from_ptr(ptr
as *mut Self::CType
)
85 unsafe fn from_const_ptr_opt
<'a
>(ptr
: *const Self::CType
) -> Option
<&'a
Self> {
89 Some(Self::from_const_ptr(ptr
as *mut Self::CType
))
93 impl<FT
: ForeignTypeRef
> ForeignTypeRefExt
for FT {}