openvpn_mgmt_codec/client_event.rs
1use std::str::FromStr;
2
3/// Error returned when a string is not a recognized client event.
4#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
5#[error("unrecognized client event: {0:?}")]
6pub struct ParseClientEventError(pub String);
7
8/// The sub-type of a `>CLIENT:` notification.
9#[derive(Debug, Clone, PartialEq, Eq, strum::Display)]
10#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
11pub enum ClientEvent {
12 /// A new client is connecting (`>CLIENT:CONNECT`).
13 Connect,
14
15 /// An existing client is re-authenticating (`>CLIENT:REAUTH`).
16 Reauth,
17
18 /// A client connection has been fully established (`>CLIENT:ESTABLISHED`).
19 Established,
20
21 /// A client has disconnected (`>CLIENT:DISCONNECT`).
22 Disconnect,
23
24 /// A client challenge-response (`>CLIENT:CR_RESPONSE,{CID},{KID},{base64}`).
25 ///
26 /// The base64-encoded response is carried inline because it appears as
27 /// the third comma-separated field on the header line (after CID and KID),
28 /// not in the ENV block. Both cedws/openvpn-mgmt-go and
29 /// jkroepke/openvpn-auth-oauth2 handle this as a distinct event type.
30 CrResponse(String),
31
32 /// An unrecognized event type (forward compatibility).
33 #[strum(default)]
34 Unknown(String),
35}
36
37impl FromStr for ClientEvent {
38 type Err = ParseClientEventError;
39
40 /// Parse a recognized client event string.
41 ///
42 /// Recognized values: `CONNECT`, `REAUTH`, `ESTABLISHED`, `DISCONNECT`.
43 /// Returns `Err` for anything else — use [`ClientEvent::Unknown`]
44 /// explicitly if forward-compatible fallback is desired.
45 ///
46 /// Note: `CR_RESPONSE` is handled separately in the codec because it
47 /// carries an inline base64 field; it is not recognized by `FromStr`.
48 fn from_str(s: &str) -> Result<Self, Self::Err> {
49 match s {
50 "CONNECT" => Ok(Self::Connect),
51 "REAUTH" => Ok(Self::Reauth),
52 "ESTABLISHED" => Ok(Self::Established),
53 "DISCONNECT" => Ok(Self::Disconnect),
54 other => Err(ParseClientEventError(other.to_string())),
55 }
56 }
57}