coolssh/
channelrequest.rs1use super::{Result, Error, U8, Write};
2use super::parsedump::ParseDump;
3use super::messages::MessageType;
4use super::check_msg_type;
5
6#[derive(Copy, Clone, Debug)]
7pub enum ChannelRequest<'a> {
8 Exec {
9 recipient_channel: u32,
10 want_reply: bool,
11 command: &'a str,
12 },
13 EnvironmentVariable {
14 recipient_channel: u32,
15 want_reply: bool,
16 name: &'a str,
17 value: &'a str,
18 },
19 ExitStatus {
20 recipient_channel: u32,
21 exit_status: u32,
22 },
23 Other {
24 recipient_channel: u32,
25 request_type: &'a str,
26 want_reply: bool,
27 },
28}
29
30impl<'a, 'b: 'a> ParseDump<'b> for ChannelRequest<'a> {
31 fn parse(bytes: &'b[u8]) -> Result<(Self, usize)> {
32 check_msg_type!(ChannelRequest, MessageType::ChannelRequest, bytes);
33 let mut i = U8;
34
35 let (recipient_channel, inc) = u32::parse(&bytes[i..])?;
36 i += inc;
37 let (request_type, inc) = <&'a str>::parse(&bytes[i..])?;
38 i += inc;
39 let (want_reply, inc) = <bool>::parse(&bytes[i..])?;
40 i += inc;
41
42 match request_type {
43 "exec" => {
44 let (command, inc) = <&'a str>::parse(&bytes[i..])?;
45 i += inc;
46
47 Ok((Self::Exec {
48 recipient_channel,
49 want_reply,
50 command,
51 }, i))
52 },
53 "env" => {
54 let (name, inc) = <&'a str>::parse(&bytes[i..])?;
55 i += inc;
56
57 let (value, inc) = <&'a str>::parse(&bytes[i..])?;
58 i += inc;
59
60 Ok((Self::EnvironmentVariable {
61 recipient_channel,
62 want_reply,
63 name,
64 value,
65 }, i))
66 },
67 "exit-status" => {
68 if want_reply {
69 log::error!("\"exit-status\" Channel Request with want_reply=true");
70 return Err(Error::InvalidData);
71 }
72
73 let (exit_status, inc) = u32::parse(&bytes[i..])?;
74 i += inc;
75
76 Ok((Self::ExitStatus {
77 recipient_channel,
78 exit_status,
79 }, i))
80 },
81 _ => Ok((Self::Other {
82 recipient_channel,
83 request_type,
84 want_reply,
85 }, i)),
86 }
87 }
88
89 fn dump<W: Write>(&self, sink: &mut W) -> Result<()> {
90 (MessageType::ChannelRequest as u8).dump(sink)?;
91
92 match self {
93 Self::Exec {
94 recipient_channel,
95 want_reply,
96 command,
97 } => {
98 recipient_channel.dump(sink)?;
99 "exec".dump(sink)?;
100 want_reply.dump(sink)?;
101 command.dump(sink)?;
102 },
103 Self::ExitStatus {
104 recipient_channel,
105 exit_status,
106 } => {
107 recipient_channel.dump(sink)?;
108 "exit-status".dump(sink)?;
109 false.dump(sink)?;
110 exit_status.dump(sink)?;
111 },
112 Self::EnvironmentVariable {
113 recipient_channel,
114 want_reply,
115 name,
116 value,
117 } => {
118 recipient_channel.dump(sink)?;
119 "env".dump(sink)?;
120 want_reply.dump(sink)?;
121 name.dump(sink)?;
122 value.dump(sink)?;
123 },
124 Self::Other { .. } => {
125 log::error!("ChannelRequest::Other has no binary representation (coolssh programmer error)");
126 return Err(Error::InvalidData);
127 },
128 }
129
130 Ok(())
131 }
132}