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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use std::convert::TryFrom;
use crate::error::rustls_result;
use crate::rslice::rustls_slice_bytes;
use crate::userdata_get;
use libc::{c_int, c_void, size_t};
pub type rustls_session_store_userdata = *mut c_void;
pub type rustls_session_store_get_callback = Option<
unsafe extern "C" fn(
userdata: rustls_session_store_userdata,
key: *const rustls_slice_bytes,
remove_after: c_int,
buf: *mut u8,
count: size_t,
out_n: *mut size_t,
) -> u32,
>;
pub(crate) type SessionStoreGetCallback = unsafe extern "C" fn(
userdata: rustls_session_store_userdata,
key: *const rustls_slice_bytes,
remove_after: c_int,
buf: *mut u8,
count: size_t,
out_n: *mut size_t,
) -> u32;
pub type rustls_session_store_put_callback = Option<
unsafe extern "C" fn(
userdata: rustls_session_store_userdata,
key: *const rustls_slice_bytes,
val: *const rustls_slice_bytes,
) -> u32,
>;
pub(crate) type SessionStorePutCallback = unsafe extern "C" fn(
userdata: rustls_session_store_userdata,
key: *const rustls_slice_bytes,
val: *const rustls_slice_bytes,
) -> u32;
pub(crate) struct SessionStoreBroker {
pub get_cb: SessionStoreGetCallback,
pub put_cb: SessionStorePutCallback,
}
impl SessionStoreBroker {
pub fn new(get_cb: SessionStoreGetCallback, put_cb: SessionStorePutCallback) -> Self {
SessionStoreBroker { get_cb, put_cb }
}
fn retrieve(&self, key: &[u8], remove: bool) -> Option<Vec<u8>> {
let key: rustls_slice_bytes = key.into();
let userdata = userdata_get().ok()?;
let mut data: Vec<u8> = vec![0; 65 * 1024];
let mut out_n: size_t = 0;
unsafe {
let cb = self.get_cb;
let result = cb(
userdata,
&key,
remove as c_int,
data.as_mut_ptr(),
data.len(),
&mut out_n,
);
let result: rustls_result =
rustls_result::try_from(result).unwrap_or(rustls_result::General);
match result {
rustls_result::Ok => {
data.set_len(out_n);
Some(data)
}
_ => None,
}
}
}
fn store(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
let key: rustls_slice_bytes = key.as_slice().into();
let value: rustls_slice_bytes = value.as_slice().into();
let cb = self.put_cb;
let userdata = match userdata_get() {
Ok(u) => u,
Err(_) => return false,
};
let result = unsafe { cb(userdata, &key, &value) };
result == rustls_result::Ok as u32
}
}
impl rustls::server::StoresServerSessions for SessionStoreBroker {
fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
self.store(key, value)
}
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
self.retrieve(key, false)
}
fn take(&self, key: &[u8]) -> Option<Vec<u8>> {
self.retrieve(key, true)
}
fn can_cache(&self) -> bool {
true
}
}
unsafe impl Sync for SessionStoreBroker {}
unsafe impl Send for SessionStoreBroker {}