-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from smorks/master
Add Windows Named Pipes
- Loading branch information
Showing
5 changed files
with
139 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/target/ |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,70 @@ | ||
extern crate byteorder; | ||
#[cfg(windows)] | ||
extern crate named_pipe; | ||
|
||
use std::io::{self, Read, Write}; | ||
use std::os::unix::net::UnixStream; | ||
use std::os::unix::net::UnixListener; | ||
use std::str; | ||
use std::thread; | ||
use std::time::Duration; | ||
use byteorder::{ByteOrder, NativeEndian, WriteBytesExt}; | ||
|
||
fn valid_length(length: u32) -> bool | ||
{ | ||
return length > 0 && length <= 4096; // 1024 ^ 2 is the maximum | ||
mod proxy_socket; | ||
|
||
use proxy_socket::ProxySocket; | ||
|
||
const BUFFER_SIZE: u32 = 1024 * 16; | ||
|
||
fn valid_length(length: u32) -> bool { | ||
return length > 0 && length <= 4096; // 1024 ^ 2 is the maximum | ||
} | ||
|
||
fn read_header() -> (u32) | ||
{ | ||
fn read_header() -> u32 { | ||
let stdin = io::stdin(); | ||
let mut buf = vec![0; 4]; | ||
let mut handle = stdin.lock(); | ||
|
||
handle.read_exact(&mut buf).unwrap(); | ||
let length: u32 = NativeEndian::read_u32(&buf); | ||
return length; | ||
NativeEndian::read_u32(&buf) | ||
} | ||
|
||
fn read_body(length: u32, mut socket: &UnixStream) | ||
{ | ||
fn read_body<T: Read + Write>(length: u32, socket: &mut ProxySocket<T>) { | ||
let mut buffer = vec![0; length as usize]; | ||
let stdin = io::stdin(); | ||
let mut handle = stdin.lock(); | ||
|
||
match handle.read_exact(&mut buffer) { | ||
Ok(_v) => { | ||
if valid_length(length) { | ||
socket.write(&buffer).unwrap(); | ||
socket.flush().unwrap(); | ||
read_unix_response(length, &socket); | ||
} | ||
}, | ||
Err(_e) => {} | ||
if let Ok(_) = handle.read_exact(&mut buffer) { | ||
if valid_length(length) { | ||
socket.write(&buffer).unwrap(); | ||
socket.flush().unwrap(); | ||
read_response(socket); | ||
} | ||
} | ||
} | ||
|
||
fn read_unix_response(length: u32, mut socket: &UnixStream) | ||
{ | ||
let mut buf = vec![0; length as usize]; | ||
|
||
match socket.read(&mut buf) { | ||
Ok(_length) => { | ||
let text = str::from_utf8(&buf).unwrap(); | ||
write_output(text); | ||
}, | ||
Err(_e) => {} | ||
} | ||
fn read_response<T: Read>(socket: &mut ProxySocket<T>) { | ||
let mut buf = vec![0; BUFFER_SIZE as usize]; | ||
if let Ok(len) = socket.read(&mut buf) { | ||
write_response(&buf[0..len]); | ||
} | ||
} | ||
|
||
fn write_output(text: &str) | ||
{ | ||
let textlen = text.len(); | ||
fn write_response(buf: &[u8]) { | ||
let stdout = io::stdout(); | ||
let mut handle = stdout.lock(); | ||
let mut out = stdout.lock(); | ||
|
||
handle.write_u32::<NativeEndian>(textlen as u32).unwrap(); | ||
handle.write(text.as_bytes()).unwrap(); | ||
out.write_u32::<NativeEndian>(buf.len() as u32).unwrap(); | ||
out.write(buf).unwrap(); | ||
out.flush().unwrap(); | ||
} | ||
|
||
fn main() { | ||
let socket = UnixStream::connect("/tmp/kpxc_server").unwrap(); | ||
let timeout: Option<Duration> = Some(Duration::from_secs(1)); | ||
socket.set_read_timeout(timeout).unwrap(); | ||
let mut socket = proxy_socket::connect().unwrap(); | ||
|
||
// Start thread for user input reading | ||
let send_socket = socket.try_clone().expect("Cannot clone socket"); | ||
let ui = thread::spawn(move || { | ||
loop { | ||
let length = read_header(); | ||
read_body(length, &send_socket); | ||
} | ||
}); | ||
read_body(length, &mut socket); | ||
} | ||
}); | ||
|
||
let _ui_res = ui.join(); | ||
let _ui_res = ui.join().unwrap(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use std::env; | ||
use std::io::{self, Read, Write}; | ||
|
||
#[cfg(not(windows))] | ||
use std::os::unix::net::UnixStream; | ||
|
||
#[cfg(windows)] | ||
use named_pipe::PipeClient; | ||
|
||
pub struct ProxySocket<T> { | ||
inner: T, | ||
} | ||
|
||
impl<R: Read> Read for ProxySocket<R> { | ||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | ||
self.inner.read(buf) | ||
} | ||
} | ||
|
||
impl<W: Write> Write for ProxySocket<W> { | ||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | ||
self.inner.write(buf) | ||
} | ||
|
||
fn flush(&mut self) -> io::Result<()> { | ||
self.inner.flush() | ||
} | ||
} | ||
|
||
#[cfg(windows)] | ||
pub fn connect() -> io::Result<ProxySocket<PipeClient>> { | ||
let temp_path = env::var("TEMP").unwrap(); | ||
let pipe_name = format!("\\\\.\\pipe\\{}\\kpxc_server", temp_path); | ||
let client = PipeClient::connect(pipe_name)?; | ||
Ok(ProxySocket { inner: client }) | ||
} | ||
|
||
#[cfg(not(windows))] | ||
pub fn connect() -> io::Result<ProxySocket<UnixStream>> { | ||
use std::time::Duration; | ||
|
||
let socket_name = "kpxc_server"; | ||
let socket: String; | ||
if let Ok(xdg) = env::var("XDG_RUNTIME_DIR") { | ||
socket = format!("{}/{}", xdg, socket_name); | ||
} else { | ||
socket = format!("/tmp/{}", socket_name); | ||
} | ||
let s = UnixStream::connect(socket)?; | ||
let timeout: Option<Duration> = Some(Duration::from_secs(1)); | ||
s.set_read_timeout(timeout)?; | ||
Ok(ProxySocket { inner: s }) | ||
} |