libtelnet_rs/
events.rs

1use crate::Parser;
2use bytes::{BufMut, Bytes, BytesMut};
3
4/// A struct representing a 2 byte IAC sequence.
5#[derive(Clone, Copy)]
6pub struct TelnetIAC {
7  pub command: u8,
8}
9
10impl Into<Bytes> for TelnetIAC {
11  fn into(self) -> Bytes {
12    let mut buf = BytesMut::with_capacity(2);
13    buf.put_u8(255);
14    buf.put_u8(self.command);
15    buf.freeze()
16  }
17}
18
19impl Into<Vec<u8>> for TelnetIAC {
20  fn into(self) -> Vec<u8> {
21    let b: Bytes = self.into();
22    b.to_vec()
23  }
24}
25
26impl TelnetIAC {
27  pub fn new(command: u8) -> Self {
28    Self { command }
29  }
30  /// Consume the sequence struct and return the bytes.
31  pub fn into_bytes(self) -> Vec<u8> {
32    self.into()
33  }
34}
35
36/// A struct representing a 3 byte IAC sequence.
37#[derive(Clone, Copy)]
38pub struct TelnetNegotiation {
39  pub command: u8,
40  pub option: u8,
41}
42
43impl Into<Bytes> for TelnetNegotiation {
44  fn into(self) -> Bytes {
45    let data = [self.command, self.option];
46    let mut buf = BytesMut::with_capacity(3);
47    buf.put_u8(255);
48    buf.put(&data[..]);
49    buf.freeze()
50  }
51}
52
53impl Into<Vec<u8>> for TelnetNegotiation {
54  fn into(self) -> Vec<u8> {
55    let b: Bytes = self.into();
56    b.to_vec()
57  }
58}
59
60impl TelnetNegotiation {
61  pub fn new(command: u8, option: u8) -> Self {
62    Self { command, option }
63  }
64  /// Consume the sequence struct and return the bytes.
65  pub fn into_bytes(self) -> Vec<u8> {
66    self.into()
67  }
68}
69
70/// A struct representing an arbitrary length IAC subnegotiation sequence.
71#[derive(Clone)]
72pub struct TelnetSubnegotiation {
73  pub option: u8,
74  pub buffer: Bytes,
75}
76
77impl Into<Bytes> for TelnetSubnegotiation {
78  fn into(self) -> Bytes {
79    let head: [u8; 3] = [255, 250, self.option];
80    let parsed = &Parser::escape_iac(self.buffer)[..];
81    let tail: [u8; 2] = [255, 240];
82    let mut buf = BytesMut::with_capacity(head.len() + parsed.len() + tail.len());
83    buf.put(&head[..]);
84    buf.put(&parsed[..]);
85    buf.put(&tail[..]);
86    buf.freeze()
87  }
88}
89
90impl Into<Vec<u8>> for TelnetSubnegotiation {
91  fn into(self) -> Vec<u8> {
92    let b: Bytes = self.into();
93    b.to_vec()
94  }
95}
96
97impl TelnetSubnegotiation {
98  pub fn new(option: u8, buffer: Bytes) -> Self {
99    Self { option, buffer }
100  }
101  /// Consume the sequence struct and return the bytes.
102  pub fn into_bytes(self) -> Vec<u8> {
103    self.into()
104  }
105}
106
107/// An enum representing various telnet events.
108#[derive(Clone)]
109pub enum TelnetEvents {
110  /// An IAC command sequence.
111  IAC(TelnetIAC),
112  /// An IAC negotiation sequence.
113  Negotiation(TelnetNegotiation),
114  /// An IAC subnegotiation sequence.
115  Subnegotiation(TelnetSubnegotiation),
116  /// Regular data received from the remote end.
117  DataReceive(Bytes),
118  /// Any data to be sent to the remote end.
119  DataSend(Bytes),
120  /// MCCP2/3 compatibility. MUST DECOMPRESS THIS DATA BEFORE PARSING
121  DecompressImmediate(Bytes),
122}
123
124impl Into<Bytes> for TelnetEvents {
125  fn into(self) -> Bytes {
126    match self {
127      TelnetEvents::IAC(iac) => iac.into(),
128      TelnetEvents::Negotiation(neg) => neg.into(),
129      TelnetEvents::Subnegotiation(sub) => sub.into(),
130      TelnetEvents::DataReceive(data) => data,
131      TelnetEvents::DataSend(data) => data,
132      TelnetEvents::DecompressImmediate(data) => data,
133    }
134  }
135}
136
137impl TelnetEvents {
138  /// Helper method to generate a TelnetEvents::DataSend.
139  pub fn build_send(buffer: Bytes) -> Self {
140    TelnetEvents::DataSend(buffer)
141  }
142  /// Helper method to generate a TelnetEvents::DataReceive.
143  pub fn build_receive(buffer: Bytes) -> Self {
144    TelnetEvents::DataReceive(buffer)
145  }
146  /// Helper method to generate a TelnetEvents::IAC.
147  pub fn build_iac(command: u8) -> TelnetEvents {
148    TelnetEvents::IAC(TelnetIAC::new(command))
149  }
150  /// Helper method to generate a TelnetEvents::Negotiation.
151  pub fn build_negotiation(command: u8, option: u8) -> Self {
152    TelnetEvents::Negotiation(TelnetNegotiation::new(command, option))
153  }
154  /// Helper method to generate a TelnetEvents::Subnegotiation.
155  pub fn build_subnegotiation(option: u8, buffer: Bytes) -> Self {
156    TelnetEvents::Subnegotiation(TelnetSubnegotiation::new(option, buffer))
157  }
158}