Skip to main content

pb_mapper_client/sdk/
types.rs

1//! Small value types shared across the SDK surface, and their conversions from
2//! the wire types in `pb-mapper-protocol`.
3//!
4//! Keeping owned mirrors here is what lets a caller depend on the SDK alone: the
5//! protocol crate stays an implementation detail.
6
7use pb_mapper_auth::LegacyProtocolPolicy;
8use pb_mapper_protocol::command::{PbConnStatusResp, PbServiceConnStatus};
9
10/// Transport used by a registered service or a local subscriber.
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub enum Transport {
13    Tcp,
14    Udp,
15}
16
17impl Transport {
18    pub(crate) fn is_datagram(self) -> bool {
19        matches!(self, Self::Udp)
20    }
21}
22
23/// Observed lifecycle of a [`super::Registration`] or [`super::Connection`].
24#[derive(Clone, Debug, Eq, PartialEq)]
25pub enum TunnelStatus {
26    Starting,
27    Connected,
28    Retrying,
29    Stopped,
30    Failed(String),
31}
32
33impl TunnelStatus {
34    pub(crate) fn from_callback(status: &str) -> Self {
35        match status {
36            "connected" => return Self::Connected,
37            "retrying" => return Self::Retrying,
38            "failed" => return Self::Failed("failed".into()),
39            _ => {}
40        }
41        // A permanent rejection arrives as `failed: <reason>`; the reason is the
42        // only description of it the caller ever gets, so it has to survive here
43        // rather than collapsing into `Retrying` and hanging `wait_ready`.
44        match status.strip_prefix("failed:") {
45            Some(reason) => Self::Failed(reason.trim().to_string()),
46            None => Self::Retrying,
47        }
48    }
49}
50
51/// Relay mapping dump from `status remote-id`.
52#[derive(Clone, Debug, Eq, PartialEq)]
53pub struct RemoteId {
54    pub server_map: String,
55    pub active: String,
56    pub idle: String,
57}
58
59impl RemoteId {
60    pub(crate) fn from_status(status: PbConnStatusResp) -> super::Result<Self> {
61        match status {
62            PbConnStatusResp::RemoteId {
63                server_map,
64                active,
65                idle,
66            } => Ok(Self {
67                server_map,
68                active,
69                idle,
70            }),
71            other => Err(super::Error::protocol(format!(
72                "expected remote-id status, got {other:?}"
73            ))),
74        }
75    }
76}
77
78/// One control connection the relay is holding for a service key.
79#[derive(Clone, Debug, Eq, PartialEq)]
80pub struct ServiceConnection {
81    pub conn_id: u32,
82    pub generation: u64,
83    pub protocol_version: u16,
84    pub healthy: bool,
85    pub last_rx_age_ms: u64,
86}
87
88impl From<PbServiceConnStatus> for ServiceConnection {
89    fn from(value: PbServiceConnStatus) -> Self {
90        Self {
91            conn_id: value.conn_id,
92            generation: value.generation,
93            protocol_version: value.protocol_version,
94            healthy: value.healthy,
95            last_rx_age_ms: value.last_rx_age_ms,
96        }
97    }
98}
99
100/// Legacy framing policy, matching `pb-mapper admin legacy-protocol`.
101#[derive(Clone, Copy, Debug, Eq, PartialEq)]
102pub enum LegacyProtocol {
103    Allow,
104    Deny,
105}
106
107impl From<LegacyProtocol> for LegacyProtocolPolicy {
108    fn from(value: LegacyProtocol) -> Self {
109        match value {
110            LegacyProtocol::Allow => Self::Allow,
111            LegacyProtocol::Deny => Self::Deny,
112        }
113    }
114}
115
116impl From<LegacyProtocolPolicy> for LegacyProtocol {
117    fn from(value: LegacyProtocolPolicy) -> Self {
118        match value {
119            LegacyProtocolPolicy::Allow => Self::Allow,
120            LegacyProtocolPolicy::Deny => Self::Deny,
121        }
122    }
123}