1use libc::c_void;
2use log::Level;
3
4#[cfg(not(feature = "no_log_capture"))]
5use crate::userdata::log_callback_get;
6
7use crate::rslice::rustls_str;
8
9#[cfg(not(feature = "no_log_capture"))]
10struct Logger {}
11
12#[cfg(not(feature = "no_log_capture"))]
13impl log::Log for Logger {
14 fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool {
15 true
16 }
17 fn log(&self, record: &log::Record<'_>) {
18 if let Ok((Some(cb), userdata)) = log_callback_get() {
19 let message = format!("{} {}", record.target(), record.args());
20 if let Ok(message) = message.as_str().try_into() {
21 unsafe {
22 cb(
23 userdata,
24 &rustls_log_params {
25 level: record.level() as rustls_log_level,
26 message,
27 },
28 );
29 }
30 }
31 }
32 }
33 fn flush(&self) {}
34}
35
36#[cfg(feature = "no_log_capture")]
37pub(crate) fn ensure_log_registered() {}
38
39#[cfg(not(feature = "no_log_capture"))]
40pub(crate) fn ensure_log_registered() {
41 log::set_logger(&Logger {}).ok();
42 log::set_max_level(log::LevelFilter::Debug)
43}
44
45pub type rustls_log_level = usize;
50
51#[no_mangle]
53pub extern "C" fn rustls_log_level_str(level: rustls_log_level) -> rustls_str<'static> {
54 let s = match level {
55 1 => Level::Error.as_str(),
56 2 => Level::Warn.as_str(),
57 3 => Level::Info.as_str(),
58 4 => Level::Debug.as_str(),
59 5 => Level::Trace.as_str(),
60 _ => "INVALID",
61 };
62 rustls_str::from_str_unchecked(s)
63}
64
65#[repr(C)]
67pub struct rustls_log_params<'a> {
68 pub level: rustls_log_level,
70 pub message: rustls_str<'a>,
72}
73
74#[allow(non_camel_case_types)]
76pub type rustls_log_callback =
77 Option<unsafe extern "C" fn(userdata: *mut c_void, params: *const rustls_log_params)>;