coolssh/
channelrequest.rs

1use 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}