1use serde::{Deserialize, Serialize};
2
3pub const DEFAULT_TCP_PORT: u16 = 7422;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(tag = "type", content = "data")]
10pub enum Command {
11 Status,
12 Whoami,
13 PairCreate {
14 label: Option<String>,
15 expire_secs: Option<u64>,
17 },
18 PairList,
19 PairRevoke {
20 id: String,
21 },
22 PairRevokeAll,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26#[serde(tag = "type", content = "data")]
27pub enum Response {
28 Pong,
29 Ok,
30 DaemonStatus(DaemonStatus),
31 ClientInfo(ClientInfo),
32 Pair(PairPayload),
34 PairedClient(PairedClient),
35 PairedClients(Vec<PairedClient>),
36 Revoked(u32),
38 Error(VexProtoError),
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct DaemonStatus {
43 pub uptime_secs: u64,
44 pub connected_clients: u32,
45 pub version: String,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct PairPayload {
51 pub token_id: String,
52 pub token_secret: String,
53 pub host: Option<String>,
55}
56
57impl PairPayload {
58 pub fn pairing_string(&self) -> String {
60 format!("{}:{}", self.token_id, self.token_secret)
61 }
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct PairedClient {
66 pub token_id: String,
67 pub label: Option<String>,
68 pub created_at: String,
69 pub expires_at: Option<String>,
70 pub last_seen: Option<String>,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct ClientInfo {
75 pub token_id: Option<String>,
76 pub is_local: bool,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
80#[serde(rename_all = "snake_case")]
81pub enum Transport {
82 Unix,
83 Tcp,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
87#[serde(tag = "code", content = "message")]
88pub enum VexProtoError {
89 Unauthorized,
90 LocalOnly,
91 NotFound,
92 Internal(String),
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct AuthToken {
98 pub token_id: String,
99 pub token_secret: String,
101}
102
103pub mod framing {
106 use serde::{Deserialize, Serialize};
107 use std::io;
108 use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
109
110 #[derive(Debug)]
111 pub enum VexFrameError {
112 Io(io::Error),
113 Json(serde_json::Error),
114 }
115
116 impl std::fmt::Display for VexFrameError {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 match self {
119 VexFrameError::Io(e) => write!(f, "IO error: {e}"),
120 VexFrameError::Json(e) => write!(f, "JSON error: {e}"),
121 }
122 }
123 }
124
125 impl std::error::Error for VexFrameError {}
126
127 impl From<io::Error> for VexFrameError {
128 fn from(e: io::Error) -> Self {
129 VexFrameError::Io(e)
130 }
131 }
132
133 impl From<serde_json::Error> for VexFrameError {
134 fn from(e: serde_json::Error) -> Self {
135 VexFrameError::Json(e)
136 }
137 }
138
139 pub async fn send<W, T>(w: &mut W, msg: &T) -> Result<(), VexFrameError>
141 where
142 W: AsyncWrite + Unpin,
143 T: Serialize,
144 {
145 let body = serde_json::to_vec(msg)?;
146 w.write_u32(body.len() as u32).await?;
147 w.write_all(&body).await?;
148 Ok(())
149 }
150
151 pub async fn recv<R, T>(r: &mut R) -> Result<T, VexFrameError>
153 where
154 R: AsyncRead + Unpin,
155 T: for<'de> Deserialize<'de>,
156 {
157 let len = r.read_u32().await?;
158 let mut buf = vec![0u8; len as usize];
159 r.read_exact(&mut buf).await?;
160 Ok(serde_json::from_slice(&buf)?)
161 }
162}