1use colored::*;
4use failure::{err_msg, Error};
5use libc;
6use std::ffi::CString;
7use std::fs::{self, File};
8use std::io::{self, Read, Write};
9use std::os::unix::ffi::OsStringExt;
10use std::path::PathBuf;
11use std::thread;
12use std::time::Duration;
13
14#[derive(Fail, Debug)]
16#[fail(display = "ITM Overflow")]
17pub struct Overflow;
18
19pub fn create_pipe(name: &str) -> Result<(), Error> {
21 let pipe = PathBuf::from(name);
22 if pipe.exists() {
23 fs::remove_file(&pipe)?;
24 }
25 let pipe = pipe.clone().into_os_string().into_vec();
26 let result = unsafe { libc::mkfifo(CString::new(pipe)?.as_ptr(), 0o644) };
27 if result != 0 {
28 Err(err_msg("Failed to create a FIFO"))?;
29 }
30 Ok(())
31}
32
33pub fn run_loop(pipe: &str, port: u8, debug: bool) -> Result<(), Error> {
35 let mut stream = io::BufReader::new(File::open(pipe)?);
36 let mut buffer = [0; 4];
37 loop {
38 match read(&mut stream, &mut buffer, port, debug) {
39 Ok(Some(payload)) => {
40 if debug {
41 for byte in payload {
42 print!("{:?} ", *byte as char);
43 }
44 println!();
45 } else {
46 io::stdout().write_all(payload)?;
47 io::stdout().flush()?;
48 }
49 }
50 Ok(None) => {
51 if debug {
52 println!("{}", "[IGN]".yellow());
53 }
54 }
55 Err(err) => {
56 if err.downcast_ref::<Overflow>().is_some() {
57 writeln!(io::stderr(), "{}", "[OFLW]".bold().white().on_red())?;
58 } else if let Some(err) = err.downcast_ref::<io::Error>() {
59 match err.kind() {
60 io::ErrorKind::UnexpectedEof => {
61 writeln!(io::stderr(), "{}", "[EOF]".red())?;
62 thread::sleep(Duration::from_millis(100));
63 }
64 kind => {
65 let message = format!("[IO: {:?}]", kind);
66 writeln!(io::stderr(), "{}", message.red())?;
67 }
68 }
69 }
70 }
71 }
72 }
73}
74
75fn read<'a, 'b>(
77 stream: &'a mut io::BufReader<File>,
78 buffer: &'b mut [u8],
79 _selected_port: u8,
80 debug: bool,
81) -> Result<Option<&'b [u8]>, Error> {
82 stream.read_exact(&mut buffer[0..1])?;
83 let header = buffer[0];
84 if debug {
85 debug_print_byte(header)?;
86 }
87 if header == 0 {
88 return Ok(None);
90 }
91 let size = header & 0b11;
92 if size == 0 {
93 if header == 0b0111_0000 {
94 Err(Overflow)?
96 } else {
97 Ok(None)
99 }
100 } else if header & 0b100 == 0 {
101 let _port = header >> 3;
103 let payload = match size {
107 0b01 => &mut buffer[0..1],
108 0b10 => &mut buffer[0..2],
109 0b11 => &mut buffer[0..4],
110 _ => unreachable!(),
111 };
112 if debug {
113 for byte in payload.chunks_mut(1) {
114 stream.read_exact(byte)?;
115 debug_print_byte(byte[0])?;
116 }
117 } else {
118 stream.read_exact(payload)?;
119 }
120 Ok(Some(payload))
121 } else {
122 Ok(None)
124 }
125}
126
127fn debug_print_byte(byte: u8) -> Result<(), Error> {
128 print!("{:08b} ", byte);
129 io::stdout().flush()?;
130 Ok(())
131}