libtelnet_rs/
lib.rs

1pub mod compatibility;
2pub mod events;
3pub mod telnet;
4
5pub use bytes;
6
7use crate::telnet::op_command::*;
8
9#[cfg(test)]
10mod tests;
11
12use bytes::{BufMut, Bytes, BytesMut};
13use compatibility::*;
14
15pub enum EventType {
16  None(Bytes),
17  IAC(Bytes),
18  SubNegotiation(Bytes, Option<Bytes>),
19  Neg(Bytes),
20}
21
22#[macro_export]
23/// Macro for calling `Bytes::copy_from_slice()`
24macro_rules! vbytes {
25  ($slice:expr) => {
26    Bytes::copy_from_slice($slice)
27  };
28}
29
30/// A telnet parser that handles the main parts of the protocol.
31pub struct Parser {
32  pub options: CompatibilityTable,
33  buffer: BytesMut,
34}
35
36impl Default for Parser {
37  fn default() -> Parser {
38    Parser {
39      options: CompatibilityTable::new(),
40      buffer: BytesMut::with_capacity(128),
41    }
42  }
43}
44
45impl Parser {
46  /// Create a default, empty Parser with an internal buffer capacity of 128 bytes.
47  pub fn new() -> Self {
48    Self::default()
49  }
50  /// Create an empty parser, setting the initial internal buffer capcity.
51  pub fn with_capacity(size: usize) -> Self {
52    Self {
53      options: CompatibilityTable::new(),
54      buffer: BytesMut::with_capacity(size),
55    }
56  }
57  /// Create an parser, setting the initial internal buffer capacity and directly supplying a CompatibilityTable.
58  pub fn with_support_and_capacity(size: usize, table: CompatibilityTable) -> Self {
59    Self {
60      options: table,
61      buffer: BytesMut::with_capacity(size),
62    }
63  }
64  /// Create a parser, directly supplying a CompatibilityTable.
65  ///
66  /// Uses the default initial buffer capacity of 128 bytes.
67  pub fn with_support(table: CompatibilityTable) -> Self {
68    Self {
69      options: table,
70      buffer: BytesMut::with_capacity(128),
71    }
72  }
73  /// Receive bytes into the internal buffer.
74  ///
75  /// # Arguments
76  ///
77  /// * `data` - The bytes to be received. This should be sourced from the remote side of a connection.
78  ///
79  /// # Returns
80  ///
81  /// `Vec<events::TelnetEvents>` - Any events parsed from the internal buffer with the new bytes.
82  ///
83  pub fn receive(&mut self, data: &[u8]) -> Vec<events::TelnetEvents> {
84    self.buffer.put(data);
85    self.process()
86  }
87  /// Get whether the remote end supports and is using linemode.
88  pub fn linemode_enabled(&mut self) -> bool {
89    let opt = self.options.get_option(telnet::op_option::LINEMODE);
90    opt.remote && opt.remote_state
91  }
92  /// Escape IAC bytes in data that is to be transmitted and treated as a non-IAC sequence.
93  ///
94  /// # Example
95  /// `[255, 1, 6, 2]` -> `[255, 255, 1, 6, 2]`
96  pub fn escape_iac<T>(data: T) -> Bytes
97  where
98    Bytes: From<T>,
99  {
100    let data = Bytes::from(data);
101    let mut t = BytesMut::with_capacity(data.len());
102    for byte in data.iter() {
103      t.put_u8(*byte);
104      if *byte == 255 {
105        t.put_u8(255);
106      }
107    }
108    t.freeze()
109  }
110  /// Reverse escaped IAC bytes for non-IAC sequences and data.
111  ///
112  /// # Example
113  /// `[255, 255, 1, 6, 2]` -> `[255, 1, 6, 2]`
114  pub fn unescape_iac<T>(data: T) -> Bytes
115  where
116    Bytes: From<T>,
117  {
118    let data = Bytes::from(data);
119    let mut t = BytesMut::with_capacity(data.len());
120    let mut last = 0u8;
121    for val in data.iter() {
122      if *val == 255 && last == 255 {
123        continue;
124      }
125      last = *val;
126      t.put_u8(*val);
127    }
128    t.freeze()
129  }
130  /// Negotiate an option.
131  ///
132  /// # Arguments
133  ///
134  /// `command` - A `u8` representing the telnet command code to be negotiated with. Example: WILL (251), WONT (252), DO (253), DONT (254)
135  ///
136  /// `option` - A `u8` representing the telnet option code that is being negotiated.
137  ///
138  /// # Returns
139  ///
140  /// `events::TelnetEvents::DataSend` - A DataSend event to be processed.
141  ///
142  /// # Usage
143  ///
144  /// This and other methods meant for sending data to the remote end will generate a `TelnetEvents::Send(DataEvent)` event.
145  ///
146  /// These Send events contain a buffer that should be sent directly to the remote end, as it will have already been encoded properly.
147  pub fn negotiate(&mut self, command: u8, option: u8) -> events::TelnetEvents {
148    events::TelnetEvents::build_send(events::TelnetNegotiation::new(command, option).into())
149  }
150  /// Indicate to the other side that you are able and wanting to utilize an option.
151  ///
152  /// # Arguments
153  ///
154  /// `option` - A `u8` representing the telnet option code that you want to enable locally.
155  ///
156  /// # Returns
157  ///
158  /// `Option<events::TelnetEvents::DataSend>` - The DataSend event to be processed, or None if not supported.
159  ///
160  /// # Notes
161  ///
162  /// This method will do nothing if the option is not "supported" locally via the `CompatibilityTable`.
163  pub fn _will(&mut self, option: u8) -> Option<events::TelnetEvents> {
164    let mut opt = self.options.get_option(option);
165    if opt.local && !opt.local_state {
166      opt.local_state = true;
167      self.options.set_option(option, opt);
168      Some(self.negotiate(251, option))
169    } else {
170      None
171    }
172  }
173  /// Indicate to the other side that you are not wanting to utilize an option.
174  ///
175  /// # Arguments
176  ///
177  /// `option` - A `u8` representing the telnet option code that you want to disable locally.
178  ///
179  /// # Returns
180  ///
181  /// `Option<events::TelnetEvents::DataSend>` - A DataSend event to be processed, or None if the option is already disabled.
182  ///
183  pub fn _wont(&mut self, option: u8) -> Option<events::TelnetEvents> {
184    let mut opt = self.options.get_option(option);
185    if opt.local_state {
186      opt.local_state = false;
187      self.options.set_option(option, opt);
188      Some(self.negotiate(252, option))
189    } else {
190      None
191    }
192  }
193  /// Indicate to the other side that you would like them to utilize an option.
194  ///
195  /// # Arguments
196  ///
197  /// `option` - A `u8` representing the telnet option code that you want to enable remotely.
198  ///
199  /// # Returns
200  ///
201  /// `Option<events::TelnetEvents::DataSend>` - A DataSend event to be processed, or None if the option is not supported or already enabled.
202  ///
203  /// # Notes
204  ///
205  /// This method will do nothing if the option is not "supported" remotely via the `CompatibilityTable`.
206  pub fn _do(&mut self, option: u8) -> Option<events::TelnetEvents> {
207    let opt = self.options.get_option(option);
208    if opt.remote && !opt.remote_state {
209      Some(self.negotiate(253, option))
210    } else {
211      None
212    }
213  }
214  /// Indicate to the other side that you would like them to stop utilizing an option.
215  ///
216  /// # Arguments
217  ///
218  /// `option` - A `u8` representing the telnet option code that you want to disable remotely.
219  ///
220  /// # Returns
221  ///
222  /// `Option<events::TelnetEvents::DataSend>` - A DataSend event to be processed, or None if the option is already disabled.
223  ///
224  pub fn _dont(&mut self, option: u8) -> Option<events::TelnetEvents> {
225    let opt = self.options.get_option(option);
226    if opt.remote_state {
227      Some(self.negotiate(254, option))
228    } else {
229      None
230    }
231  }
232  /// Send a subnegotiation for a locally supported option.
233  ///
234  /// # Arguments
235  ///
236  /// `option` - A `u8` representing the telnet option code for the negotiation.
237  ///
238  /// `data` - A `Bytes` containing the data to be sent in the subnegotiation. This data will have all IAC (255) byte values escaped.
239  ///
240  /// # Returns
241  ///
242  /// `Option<events::TelnetEvents::DataSend>` - A DataSend event to be processed, or None if the option is not supported or is currently disabled.
243  ///
244  /// # Notes
245  ///
246  /// This method will do nothing if the option is not "supported" locally via the `CompatibilityTable`.
247  pub fn subnegotiation<T>(&mut self, option: u8, data: T) -> Option<events::TelnetEvents>
248  where
249    Bytes: From<T>,
250  {
251    let opt = self.options.get_option(option);
252    if opt.local && opt.local_state {
253      Some(events::TelnetEvents::build_send(
254        events::TelnetSubnegotiation::new(option, Bytes::from(data)).into(),
255      ))
256    } else {
257      None
258    }
259  }
260  /// Send a subnegotiation for a locally supported option, using a string instead of raw byte values.
261  ///
262  /// # Arguments
263  ///
264  /// `option` - A `u8` representing the telnet option code for the negotiation.
265  ///
266  /// `text` - A `&str` representing the text to be sent in the subnegotation. This data will have all IAC (255) byte values escaped.
267  ///
268  /// # Returns
269  ///
270  /// `Option<events::TelnetEvents::DataSend>` - A DataSend event to be processed, or None if the option is not supported or is currently disabled.
271  ///
272  /// # Notes
273  ///
274  /// This method will do nothing if the option is not "supported" locally via the `CompatibilityTable`.
275  pub fn subnegotiation_text(&mut self, option: u8, text: &str) -> Option<events::TelnetEvents> {
276    self.subnegotiation(option, Bytes::copy_from_slice(&text.as_bytes()))
277  }
278  /// Directly send a string, with appended `\r\n`, to the remote end, along with an `IAC (255) GOAHEAD (249)` sequence.
279  ///
280  /// # Returns
281  ///
282  /// `events::TelnetEvents::DataSend` - A DataSend event to be processed.
283  ///
284  /// # Notes
285  ///
286  /// The string will have IAC (255) bytes escaped before being sent.
287  pub fn send_text(&mut self, text: &str) -> events::TelnetEvents {
288    events::TelnetEvents::build_send(Bytes::copy_from_slice(&Parser::escape_iac(
289      format!("{}\r\n", text).into_bytes(),
290    )))
291  }
292
293  /// Extract sub-buffers from the current buffer
294  fn extract_event_data(&mut self) -> Vec<EventType> {
295    enum State {
296      Normal,
297      IAC,
298      Neg,
299      Sub,
300    }
301    let mut iter_state = State::Normal;
302
303    let mut events: Vec<EventType> = Vec::with_capacity(4);
304    let iter = self.buffer.iter().enumerate();
305    let mut cmd_begin: usize = 0;
306
307    for (index, &val) in iter {
308      match iter_state {
309        State::Normal => {
310          if val == IAC {
311            if cmd_begin < index {
312              events.push(EventType::None(vbytes!(&self.buffer[cmd_begin..index])));
313            }
314            cmd_begin = index;
315            iter_state = State::IAC;
316          }
317        }
318        State::IAC => {
319          match val {
320            IAC => iter_state = State::Normal, // Double IAC, ignore
321            GA | EOR | NOP => {
322              events.push(EventType::IAC(vbytes!(&self.buffer[cmd_begin..index + 1])));
323              cmd_begin = index + 1;
324              iter_state = State::Normal;
325            }
326            SB => iter_state = State::Sub,
327            _ => iter_state = State::Neg, // WILL | WONT | DO | DONT | IS | SEND
328          }
329        }
330        State::Neg => {
331          events.push(EventType::Neg(vbytes!(&self.buffer[cmd_begin..index + 1])));
332          cmd_begin = index + 1;
333          iter_state = State::Normal;
334        }
335        State::Sub => {
336          if val == SE {
337            let opt = &self.buffer[cmd_begin + 2];
338            if *opt == telnet::op_option::MCCP2 || *opt == telnet::op_option::MCCP3 {
339              // MCCP2/MCCP3 MUST DECOMPRESS DATA AFTER THIS!
340              events.push(EventType::SubNegotiation(
341                vbytes!(&self.buffer[cmd_begin..index + 1]),
342                Some(vbytes!(&self.buffer[index + 1..])),
343              ));
344              cmd_begin = self.buffer.len();
345              break;
346            } else {
347              events.push(EventType::SubNegotiation(
348                vbytes!(&self.buffer[cmd_begin..index + 1]),
349                None,
350              ));
351              cmd_begin = index + 1;
352              iter_state = State::Normal;
353            }
354          }
355        }
356      }
357    }
358    if cmd_begin < self.buffer.len() {
359      match iter_state {
360        State::Sub => events.push(EventType::SubNegotiation(
361          vbytes!(&self.buffer[cmd_begin..]),
362          None,
363        )),
364        _ => events.push(EventType::None(vbytes!(&self.buffer[cmd_begin..]))),
365      }
366    }
367
368    // Empty the buffer when we are done
369    self.buffer.clear();
370    events
371  }
372
373  /// The internal parser method that takes the current buffer and generates the corresponding events.
374  fn process(&mut self) -> Vec<events::TelnetEvents> {
375    let mut event_list: Vec<events::TelnetEvents> = Vec::with_capacity(2);
376    for event in self.extract_event_data() {
377      match event {
378        EventType::None(buffer) | EventType::IAC(buffer) | EventType::Neg(buffer) => {
379          if buffer.is_empty() {
380            continue;
381          }
382          if buffer[0] == IAC {
383            match buffer.len() {
384              2 => {
385                if buffer[1] != SE {
386                  // IAC command
387                  event_list.push(events::TelnetEvents::build_iac(buffer[1]));
388                }
389              }
390              3 => {
391                // Negotiation
392                let mut opt = self.options.get_option(buffer[2]);
393                let event = events::TelnetNegotiation::new(buffer[1], buffer[2]);
394                match buffer[1] {
395                  WILL => {
396                    if opt.remote && !opt.remote_state {
397                      opt.remote_state = true;
398                      event_list.push(events::TelnetEvents::build_send(vbytes!(&[
399                        IAC, DO, buffer[2]
400                      ])));
401                      self.options.set_option(buffer[2], opt);
402                      event_list.push(events::TelnetEvents::Negotiation(event));
403                    } else if !opt.remote {
404                      event_list.push(events::TelnetEvents::build_send(vbytes!(&[
405                        IAC, DONT, buffer[2]
406                      ])));
407                    }
408                  }
409                  WONT => {
410                    if opt.remote_state {
411                      opt.remote_state = false;
412                      self.options.set_option(buffer[2], opt);
413                      event_list.push(events::TelnetEvents::build_send(vbytes!(&[
414                        IAC, DONT, buffer[2]
415                      ])));
416                    }
417                    event_list.push(events::TelnetEvents::Negotiation(event));
418                  }
419                  DO => {
420                    if opt.local && !opt.local_state {
421                      opt.local_state = true;
422                      opt.remote_state = true;
423                      event_list.push(events::TelnetEvents::build_send(vbytes!(&[
424                        IAC, WILL, buffer[2]
425                      ])));
426                      self.options.set_option(buffer[2], opt);
427                      event_list.push(events::TelnetEvents::Negotiation(event));
428                    } else if !opt.local {
429                      event_list.push(events::TelnetEvents::build_send(vbytes!(&[
430                        IAC, WONT, buffer[2]
431                      ])));
432                    }
433                  }
434                  DONT => {
435                    if opt.local_state {
436                      opt.local_state = false;
437                      self.options.set_option(buffer[2], opt);
438                      event_list.push(events::TelnetEvents::build_send(vbytes!(&[
439                        IAC, WONT, buffer[2]
440                      ])));
441                    }
442                    event_list.push(events::TelnetEvents::Negotiation(event));
443                  }
444                  _ => (),
445                }
446              }
447              _ => (),
448            }
449          } else {
450            // Not an iac sequence, it's data!
451            event_list.push(events::TelnetEvents::build_receive(buffer));
452          }
453        }
454        EventType::SubNegotiation(buffer, remaining) => {
455          let len: usize = buffer.len();
456          if buffer[len - 2] == IAC && buffer[len - 1] == SE {
457            // Valid ending
458            let opt = self.options.get_option(buffer[2]);
459            if opt.local && opt.local_state {
460              let dbuffer = vbytes!(&buffer[3..len - 2]);
461              event_list.push(events::TelnetEvents::build_subnegotiation(
462                buffer[2], dbuffer,
463              ));
464              if let Some(rbuf) = remaining {
465                event_list.push(events::TelnetEvents::DecompressImmediate(rbuf));
466              }
467            }
468          } else {
469            // Missing the rest
470            self.buffer.put(&buffer[..]);
471          }
472        }
473      }
474    }
475    event_list
476  }
477}