varnish_sys/vcl/
probe.rs

1use std::borrow::Cow;
2use std::ffi::{c_char, c_uint, CStr};
3use std::time::Duration;
4
5use serde::{Deserialize, Serialize};
6
7use crate::ffi::{vrt_backend_probe, VCL_DURATION, VCL_PROBE, VRT_BACKEND_PROBE_MAGIC};
8use crate::vcl::{IntoVCL, VclError, Workspace};
9
10#[derive(Debug, Clone, Deserialize, Serialize)]
11pub enum Request<T> {
12    Url(T),
13    Text(T),
14}
15
16#[derive(Debug, Clone, Deserialize, Serialize)]
17pub struct Probe<T = String> {
18    pub request: Request<T>,
19    pub timeout: Duration,
20    pub interval: Duration,
21    pub exp_status: c_uint,
22    pub window: c_uint,
23    pub threshold: c_uint,
24    pub initial: c_uint,
25}
26
27pub type CowProbe<'a> = Probe<Cow<'a, str>>;
28
29impl CowProbe<'_> {
30    pub fn to_owned(&self) -> Probe {
31        Probe {
32            request: match &self.request {
33                Request::Url(cow) => Request::Url(cow.to_string()),
34                Request::Text(cow) => Request::Text(cow.to_string()),
35            },
36            timeout: self.timeout,
37            interval: self.interval,
38            exp_status: self.exp_status,
39            window: self.window,
40            threshold: self.threshold,
41            initial: self.initial,
42        }
43    }
44}
45
46/// Helper to convert a probe into a VCL object
47pub(crate) fn into_vcl_probe<T: AsRef<str>>(
48    src: Probe<T>,
49    ws: &mut Workspace,
50) -> Result<VCL_PROBE, VclError> {
51    let probe = ws.copy_value(vrt_backend_probe {
52        magic: VRT_BACKEND_PROBE_MAGIC,
53        timeout: src.timeout.into(),
54        interval: src.interval.into(),
55        exp_status: src.exp_status,
56        window: src.window,
57        initial: src.initial,
58        ..Default::default()
59    })?;
60
61    match src.request {
62        Request::Url(s) => {
63            probe.url = s.as_ref().into_vcl(ws)?.0;
64        }
65        Request::Text(s) => {
66            probe.request = s.as_ref().into_vcl(ws)?.0;
67        }
68    }
69
70    Ok(VCL_PROBE(probe))
71}
72
73/// Helper to convert a VCL probe into a Rust probe wrapper
74pub(crate) fn from_vcl_probe<'a, T: From<Cow<'a, str>>>(value: VCL_PROBE) -> Option<Probe<T>> {
75    let pr = unsafe { value.0.as_ref()? };
76    assert!(
77        (pr.url.is_null() && !pr.request.is_null()) || pr.request.is_null() && !pr.url.is_null()
78    );
79    Some(Probe {
80        request: if pr.url.is_null() {
81            Request::Text(from_str(pr.request).into())
82        } else {
83            Request::Url(from_str(pr.url).into())
84        },
85        timeout: VCL_DURATION(pr.timeout).into(),
86        interval: VCL_DURATION(pr.interval).into(),
87        exp_status: pr.exp_status,
88        window: pr.window,
89        threshold: pr.threshold,
90        initial: pr.initial,
91    })
92}
93
94/// Helper function to convert a C string into a Rust string
95fn from_str<'a>(value: *const c_char) -> Cow<'a, str> {
96    if value.is_null() {
97        Cow::Borrowed("")
98    } else {
99        // FIXME: this should NOT be lossy IMO
100        unsafe { CStr::from_ptr(value).to_string_lossy() }
101    }
102}