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