openssh_mux_client/
response.rs
1#![forbid(unsafe_code)]
2
3use serde::{
4 de::{Deserializer, EnumAccess, Error, VariantAccess, Visitor},
5 Deserialize,
6};
7use std::{fmt, marker::PhantomData};
8
9use super::constants;
10
11#[derive(Clone, Debug)]
14pub enum Response {
15 Hello { version: u32 },
16
17 Alive { response_id: u32, server_pid: u32 },
18
19 Ok { response_id: u32 },
20 Failure { response_id: u32, reason: Box<str> },
21
22 PermissionDenied { response_id: u32, reason: Box<str> },
23
24 SessionOpened { response_id: u32, session_id: u32 },
25 ExitMessage { session_id: u32, exit_value: u32 },
26 TtyAllocFail { session_id: u32 },
27
28 RemotePort { response_id: u32, remote_port: u32 },
29}
30impl<'de> Deserialize<'de> for Response {
31 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
32 deserializer.deserialize_enum(
33 "Response",
34 &[
35 "Hello",
36 "Alive",
37 "Ok",
38 "Failure",
39 "PermissionDenied",
40 "SessionOpened",
41 "ExitMessage",
42 "TtyAllocFail",
43 "RemotePort",
44 ],
45 ResponseVisitor,
46 )
47 }
48}
49
50struct ResponseVisitor;
51impl<'de> Visitor<'de> for ResponseVisitor {
52 type Value = Response;
53
54 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
55 write!(formatter, "expecting Response")
56 }
57
58 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
59 where
60 A: EnumAccess<'de>,
61 {
62 use constants::*;
63
64 let result: (u32, _) = data.variant()?;
65 let (index, accessor) = result;
66
67 match index {
68 MUX_MSG_HELLO => {
69 let version: u32 = accessor.newtype_variant_seed(PhantomData)?;
70 Ok(Response::Hello { version })
71 }
72 MUX_S_ALIVE => {
73 let tup: (u32, u32) = accessor.newtype_variant_seed(PhantomData)?;
74 Ok(Response::Alive {
75 response_id: tup.0,
76 server_pid: tup.1,
77 })
78 }
79 MUX_S_OK => {
80 let response_id: u32 = accessor.newtype_variant_seed(PhantomData)?;
81 Ok(Response::Ok { response_id })
82 }
83 MUX_S_FAILURE => {
84 let tup: (u32, Box<str>) = accessor.newtype_variant_seed(PhantomData)?;
85 Ok(Response::Failure {
86 response_id: tup.0,
87 reason: tup.1,
88 })
89 }
90 MUX_S_PERMISSION_DENIED => {
91 let tup: (u32, Box<str>) = accessor.newtype_variant_seed(PhantomData)?;
92 Ok(Response::PermissionDenied {
93 response_id: tup.0,
94 reason: tup.1,
95 })
96 }
97 MUX_S_SESSION_OPENED => {
98 let tup: (u32, u32) = accessor.newtype_variant_seed(PhantomData)?;
99 Ok(Response::SessionOpened {
100 response_id: tup.0,
101 session_id: tup.1,
102 })
103 }
104 MUX_S_EXIT_MESSAGE => {
105 let tup: (u32, u32) = accessor.newtype_variant_seed(PhantomData)?;
106 Ok(Response::ExitMessage {
107 session_id: tup.0,
108 exit_value: tup.1,
109 })
110 }
111 MUX_S_TTY_ALLOC_FAIL => {
112 let session_id: u32 = accessor.newtype_variant_seed(PhantomData)?;
113 Ok(Response::TtyAllocFail { session_id })
114 }
115 MUX_S_REMOTE_PORT => {
116 let tup: (u32, u32) = accessor.newtype_variant_seed(PhantomData)?;
117 Ok(Response::RemotePort {
118 response_id: tup.0,
119 remote_port: tup.1,
120 })
121 }
122 _ => Err(A::Error::custom("Unexpected packet type")),
123 }
124 }
125}