Skip to content

Commit

Permalink
Merge pull request #2 from smorks/master
Browse files Browse the repository at this point in the history
Add Windows Named Pipes
  • Loading branch information
Sami Vänttinen authored Dec 3, 2017
2 parents 6c5f96f + 7a2298f commit 31fa5bf
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target/
47 changes: 47 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ license = "GPL-3.0"
repository = "https://github.com/varjolintu/keepassxc-proxy-rust"

[dependencies]
byteorder = "1.1.0"
byteorder = "1.1.0"

[target.'cfg(windows)'.dependencies]
named_pipe = "0.2"
81 changes: 34 additions & 47 deletions src/main.rs
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();
}
53 changes: 53 additions & 0 deletions src/proxy_socket.rs
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 })
}

0 comments on commit 31fa5bf

Please sign in to comment.