1#![cfg_attr(not(feature = "std"), no_std)]
2#![warn(clippy::pedantic)]
3#![allow(
4 clippy::module_name_repetitions,
5 clippy::fn_params_excessive_bools,
6 clippy::struct_excessive_bools,
7 deprecated
8)]
9
10#[cfg(not(feature = "std"))]
11extern crate alloc;
12#[cfg(feature = "std")]
13extern crate std as alloc;
14
15use alloc::{format, vec, vec::Vec};
16
17use bytes::{BufMut, Bytes, BytesMut};
18
19pub use bytes;
20pub mod compatibility;
21pub mod events;
22pub mod telnet;
23
24use compatibility::{CompatibilityEntry, CompatibilityTable};
25use events::{TelnetEvents, TelnetNegotiation, TelnetSubnegotiation};
26use telnet::op_command::{DO, DONT, EOR, GA, IAC, NOP, SB, SE, WILL, WONT};
27
28enum EventType {
29 None(Bytes),
30 Iac(Bytes),
31 SubNegotiation(Bytes, Option<Bytes>),
32 Neg(Bytes),
33}
34
35#[deprecated(
36 since = "0.2.1",
37 note = "Use `Bytes::copy_from_slice` directly instead."
38)]
39#[macro_export]
40macro_rules! vbytes {
42 ($slice:expr) => {
43 Bytes::copy_from_slice($slice)
44 };
45}
46
47pub struct Parser {
49 pub options: CompatibilityTable,
50 buffer: BytesMut,
51}
52
53impl Default for Parser {
54 fn default() -> Self {
55 Parser::with_capacity(128)
56 }
57}
58
59impl Parser {
60 #[must_use]
62 pub fn new() -> Self {
63 Self::default()
64 }
65
66 #[must_use]
68 pub fn with_capacity(size: usize) -> Self {
69 Self::with_support_and_capacity(size, CompatibilityTable::default())
70 }
71
72 #[must_use]
76 pub fn with_support(table: CompatibilityTable) -> Self {
77 Self::with_support_and_capacity(128, table)
78 }
79
80 #[must_use]
83 pub fn with_support_and_capacity(size: usize, table: CompatibilityTable) -> Self {
84 Self {
85 options: table,
86 buffer: BytesMut::with_capacity(size),
87 }
88 }
89
90 pub fn receive(&mut self, data: &[u8]) -> Vec<TelnetEvents> {
101 self.buffer.put(data);
102 self.process()
103 }
104
105 pub fn linemode_enabled(&mut self) -> bool {
107 matches!(
108 self.options.get_option(telnet::op_option::LINEMODE),
109 CompatibilityEntry {
110 remote: true,
111 remote_state: true,
112 ..
113 }
114 )
115 }
116
117 pub fn escape_iac<T>(data: T) -> Bytes
122 where
123 Bytes: From<T>,
124 {
125 let data = Bytes::from(data);
126 let mut res = BytesMut::with_capacity(data.len());
127 for byte in data {
128 res.put_u8(byte);
129 if byte == IAC {
130 res.put_u8(IAC);
131 }
132 }
133 res.freeze()
134 }
135
136 pub fn unescape_iac<T>(data: T) -> Bytes
141 where
142 Bytes: From<T>,
143 {
144 #[derive(Debug, Clone, Copy)]
145 enum States {
146 Normal,
147 Iac,
148 }
149
150 let data = Bytes::from(data);
151 let mut res = BytesMut::with_capacity(data.len());
152
153 let mut state = States::Normal;
154 let mut out_val;
155 for val in data {
156 (state, out_val) = match (state, val) {
157 (States::Normal, IAC) => (States::Iac, Some(val)),
158 (States::Iac, IAC) => (States::Normal, None),
159 (States::Normal | States::Iac, _) => (States::Normal, Some(val)),
160 };
161 if let Some(val) = out_val {
162 res.put_u8(val);
163 }
164 }
165
166 res.freeze()
167 }
168
169 pub fn negotiate(&mut self, command: u8, option: u8) -> TelnetEvents {
187 TelnetEvents::build_send(TelnetNegotiation::new(command, option).to_bytes())
188 }
189
190 pub fn _will(&mut self, option: u8) -> Option<TelnetEvents> {
204 match self.options.get_option(option) {
205 mut opt @ CompatibilityEntry {
206 local: true,
207 local_state: false,
208 ..
209 } => {
210 opt.local_state = true;
211 self.options.set_option(option, opt);
212 Some(self.negotiate(WILL, option))
213 }
214 _ => None,
215 }
216 }
217
218 pub fn _wont(&mut self, option: u8) -> Option<TelnetEvents> {
229 match self.options.get_option(option) {
230 mut opt @ CompatibilityEntry {
231 local_state: true, ..
232 } => {
233 opt.local_state = false;
234 self.options.set_option(option, opt);
235 Some(self.negotiate(WONT, option))
236 }
237 _ => None,
238 }
239 }
240
241 pub fn _do(&mut self, option: u8) -> Option<TelnetEvents> {
255 match self.options.get_option(option) {
256 CompatibilityEntry {
257 remote: true,
258 remote_state: false,
259 ..
260 } => Some(self.negotiate(DO, option)),
261 _ => None,
262 }
263 }
264
265 pub fn _dont(&mut self, option: u8) -> Option<TelnetEvents> {
276 match self.options.get_option(option) {
277 CompatibilityEntry {
278 remote_state: true, ..
279 } => Some(self.negotiate(DONT, option)),
280 _ => None,
281 }
282 }
283
284 pub fn subnegotiation<T>(&mut self, option: u8, data: T) -> Option<TelnetEvents>
300 where
301 Bytes: From<T>,
302 {
303 match self.options.get_option(option) {
304 CompatibilityEntry {
305 local: true,
306 local_state: true,
307 ..
308 } => Some(TelnetEvents::build_send(
309 TelnetSubnegotiation::new(option, Bytes::from(data)).to_bytes(),
310 )),
311 _ => None,
312 }
313 }
314
315 pub fn subnegotiation_text(&mut self, option: u8, text: &str) -> Option<TelnetEvents> {
331 self.subnegotiation(option, Bytes::copy_from_slice(text.as_bytes()))
332 }
333
334 pub fn send_text(&mut self, text: &str) -> TelnetEvents {
344 TelnetEvents::build_send(Parser::escape_iac(format!("{text}\r\n")))
345 }
346
347 fn extract_event_data(&mut self) -> Vec<EventType> {
349 #[derive(Copy, Clone)]
350 enum State {
351 Normal,
352 Iac,
353 Neg,
354 Sub,
355 SubOpt { opt: u8 },
356 SubIac { opt: u8 },
357 }
358
359 let mut events = Vec::with_capacity(4);
360 let mut iter_state = State::Normal;
361 let mut cmd_begin = 0;
362
363 let buf = self.buffer.split().freeze();
367 for (index, &val) in buf.iter().enumerate() {
368 (iter_state, cmd_begin) = match (&iter_state, val) {
369 (State::Normal, IAC) => {
370 if cmd_begin != index {
371 events.push(EventType::None(buf.slice(cmd_begin..index)));
372 }
373 (State::Iac, index)
374 }
375 (State::Iac, IAC) => (State::Normal, cmd_begin), (State::Iac, GA | EOR | NOP) => {
377 events.push(EventType::Iac(buf.slice(cmd_begin..=index)));
378 (State::Normal, index + 1)
379 }
380 (State::Iac, SB) => (State::Sub, cmd_begin),
381 (State::Iac, _) => (State::Neg, cmd_begin), (State::Neg, _) => {
383 events.push(EventType::Neg(buf.slice(cmd_begin..=index)));
384 (State::Normal, index + 1)
385 }
386 (State::Sub, opt) => (State::SubOpt { opt }, cmd_begin),
387 (State::SubOpt { opt } | State::SubIac { opt }, IAC) => {
388 (State::SubIac { opt: *opt }, cmd_begin)
389 }
390 (State::SubIac { opt }, SE)
391 if *opt == telnet::op_option::MCCP2 || *opt == telnet::op_option::MCCP3 =>
392 {
393 events.push(EventType::SubNegotiation(
395 buf.slice(cmd_begin..=index),
396 Some(buf.slice(index + 1..)),
397 ));
398 cmd_begin = buf.len();
399 break;
400 }
401 (State::SubIac { .. }, SE) => {
402 events.push(EventType::SubNegotiation(
403 buf.slice(cmd_begin..=index),
404 None,
405 ));
406 (State::Normal, index + 1)
407 }
408 (State::SubIac { opt }, _) => (State::SubOpt { opt: *opt }, cmd_begin),
409 (cur_state, _) => (*cur_state, cmd_begin),
410 };
411 }
412
413 if cmd_begin < buf.len() {
414 match iter_state {
415 State::Sub | State::SubOpt { .. } | State::SubIac { .. } => {
416 events.push(EventType::SubNegotiation(buf.slice(cmd_begin..), None));
417 }
418 _ => events.push(EventType::None(buf.slice(cmd_begin..))),
419 }
420 }
421
422 events
423 }
424
425 fn process(&mut self) -> Vec<TelnetEvents> {
427 let mut event_list = Vec::with_capacity(2);
428 let events = self.extract_event_data();
429 for event in events {
430 match event {
431 EventType::None(buffer) | EventType::Iac(buffer) | EventType::Neg(buffer) => {
432 match (buffer.first(), buffer.get(1), buffer.get(2)) {
433 (Some(&IAC), Some(command), None) if *command != SE => {
434 event_list.push(TelnetEvents::build_iac(*command));
436 }
437 (Some(&IAC), Some(command), Some(opt)) => {
438 event_list.extend(self.process_negotiation(*command, *opt));
440 }
441 (Some(c), _, _) if *c != IAC => {
442 event_list.push(TelnetEvents::build_receive(buffer));
444 }
445 _ => {}
446 }
447 }
448 EventType::SubNegotiation(buffer, remaining) => {
449 let len = buffer.len();
450 if buffer[len - 2] == IAC && buffer[len - 1] == SE {
451 let opt = self.options.get_option(buffer[2]);
453 if opt.local && opt.local_state && len - 2 >= 3 {
454 event_list.push(TelnetEvents::build_subnegotiation(
455 buffer[2],
456 vbytes!(&buffer[3..len - 2]),
457 ));
458 if let Some(rbuf) = remaining {
459 event_list.push(TelnetEvents::DecompressImmediate(rbuf));
460 }
461 }
462 } else {
463 self.buffer.put(&buffer[..]);
465 }
466 }
467 }
468 }
469 event_list
470 }
471
472 fn process_negotiation(&mut self, command: u8, opt: u8) -> Vec<TelnetEvents> {
473 let event = TelnetNegotiation::new(command, opt);
474 match (command, self.options.get_option(opt)) {
475 (
476 WILL,
477 mut entry @ CompatibilityEntry {
478 remote: true,
479 remote_state: false,
480 ..
481 },
482 ) => {
483 entry.remote_state = true;
484 self.options.set_option(opt, entry);
485 vec![
486 TelnetEvents::build_send(vbytes!(&[IAC, DO, opt])),
487 TelnetEvents::Negotiation(event),
488 ]
489 }
490 (WILL, CompatibilityEntry { remote: false, .. }) => {
491 vec![TelnetEvents::build_send(vbytes!(&[IAC, DONT, opt]))]
492 }
493 (
494 WONT,
495 mut entry @ CompatibilityEntry {
496 remote_state: true, ..
497 },
498 ) => {
499 entry.remote_state = false;
500 self.options.set_option(opt, entry);
501 vec![
502 TelnetEvents::build_send(vbytes!(&[IAC, DONT, opt])),
503 TelnetEvents::Negotiation(event),
504 ]
505 }
506 (
507 DO,
508 mut entry @ CompatibilityEntry {
509 local: true,
510 local_state: false,
511 ..
512 },
513 ) => {
514 entry.local_state = true;
515 entry.remote_state = true;
516 self.options.set_option(opt, entry);
517 vec![
518 TelnetEvents::build_send(vbytes!(&[IAC, WILL, opt])),
519 TelnetEvents::Negotiation(event),
520 ]
521 }
522 (
523 DO,
524 CompatibilityEntry {
525 local_state: false, ..
526 }
527 | CompatibilityEntry { local: false, .. },
528 ) => {
529 vec![TelnetEvents::build_send(vbytes!(&[IAC, WONT, opt]))]
530 }
531 (
532 DONT,
533 mut entry @ CompatibilityEntry {
534 local_state: true, ..
535 },
536 ) => {
537 entry.local_state = false;
538 self.options.set_option(opt, entry);
539 vec![
540 TelnetEvents::build_send(vbytes!(&[IAC, WONT, opt])),
541 TelnetEvents::Negotiation(event),
542 ]
543 }
544 (DONT | WONT, CompatibilityEntry { .. }) => {
545 vec![TelnetEvents::Negotiation(event)]
546 }
547 _ => Vec::default(),
548 }
549 }
550}