From e2a2ac23cd85cb845f6216f34c57dc48f73ca032 Mon Sep 17 00:00:00 2001 From: laerling Date: Mon, 8 Oct 2018 19:17:10 +0200 Subject: [PATCH 1/6] Normal mode connection, fixed read length --- Cargo.lock | 5 +++++ Cargo.toml | 1 + src/connection.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 9 ++++++++ 4 files changed, 71 insertions(+) create mode 100644 src/connection.rs diff --git a/Cargo.lock b/Cargo.lock index 343f695..317792b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,6 +5,7 @@ dependencies = [ "conch-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "conch-runtime 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "vt6 0.0.1", ] [[package]] @@ -713,6 +714,10 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vt6" +version = "0.0.1" + [[package]] name = "winapi" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index d7ccf4e..adc61de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ authors = ["lærling "] conch-parser = "^0.1.0" conch-runtime = "^0.1.4" tokio-core = "^0.1.17" +vt6 = { path = "../vt6.rs" } \ No newline at end of file diff --git a/src/connection.rs b/src/connection.rs new file mode 100644 index 0000000..0fba00c --- /dev/null +++ b/src/connection.rs @@ -0,0 +1,56 @@ +/******************************************************************************* + * + * Copyright 2018 lærling + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + *******************************************************************************/ + +use std::env::vars; +use std::io; +use std::io::Write; +use std::os::unix::net::UnixStream; +use std::path::PathBuf; +use std::io::Error; +use std::io::ErrorKind; + +/// Encapsulates the message connection to the VT6 server +pub struct Connection { + stream: UnixStream, +} + +impl Connection { + + /// finds the vt6 socket and connects to it + pub fn new() -> Result { + + if let Some(vt6_socket_var) = vars().find(|var| var.0 == "VT6") { + return Ok(Connection { + stream: UnixStream::connect(PathBuf::from(vt6_socket_var.1))?, + }); + } + + Err(Error::new(ErrorKind::NotFound, "VT6 server connection not found.")) + } + + pub fn send(&mut self, msg: &str) { + self.stream.write_all(msg.as_bytes()).unwrap(); + } + + pub fn read(&mut self) { + use std::io::Read; + let mut answer = String::with_capacity(24); // FIXME: Always read to message end, not into a buffer of fixed size + let read_bytes = self.stream.read_to_string(&mut answer).unwrap(); + println!("Read {} bytes: {}", read_bytes, answer); + } +} diff --git a/src/main.rs b/src/main.rs index 9b05c30..acf87ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,7 @@ extern crate conch_parser; extern crate conch_runtime; extern crate tokio_core; +extern crate vt6; use conch_parser::lexer::Lexer; use conch_parser::parse::DefaultParser; @@ -32,6 +33,8 @@ use std::option::Option; use tokio_core::reactor::Core; use std::process::exit; +mod connection; + fn repl(script: &mut T) -> io::Result<()> { // make event loop @@ -79,6 +82,12 @@ fn repl(script: &mut T) -> io::Result<()> { fn main() { + // FIXME temp + let mut con = connection::Connection::new().unwrap(); + con.send("{3|4:want,4:core,1:1,}"); + con.read(); + std::process::exit(0); + // evaluate command line argument let eval_result = match env::args().nth(1) { From 7eb3c557498538e14947c1fcfbd33993f9dad5a3 Mon Sep 17 00:00:00 2001 From: laerling Date: Fri, 19 Oct 2018 17:45:18 +0200 Subject: [PATCH 2/6] Connection: Read until vt6 message parsing successful --- src/connection.rs | 40 ++++++++++++++++++++++++++++++++-------- src/main.rs | 3 +-- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/connection.rs b/src/connection.rs index 0fba00c..2e0b08a 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -23,34 +23,58 @@ use std::os::unix::net::UnixStream; use std::path::PathBuf; use std::io::Error; use std::io::ErrorKind; +use vt6::common::core::msg::Message; -/// Encapsulates the message connection to the VT6 server +/// Encapsulates the server connection pub struct Connection { stream: UnixStream, + buffer: Vec, } impl Connection { - /// finds the vt6 socket and connects to it + /// finds the vt6 socket and connects to it, returning a new connection object pub fn new() -> Result { if let Some(vt6_socket_var) = vars().find(|var| var.0 == "VT6") { return Ok(Connection { stream: UnixStream::connect(PathBuf::from(vt6_socket_var.1))?, + buffer: vec![0;1024], }); } Err(Error::new(ErrorKind::NotFound, "VT6 server connection not found.")) } - pub fn send(&mut self, msg: &str) { + /// sends a message and waits for the response synchronously + pub fn send_and_receive(&mut self, msg: &str) { + + // send + // TODO: Use vt6 messages self.stream.write_all(msg.as_bytes()).unwrap(); - } - pub fn read(&mut self) { + // receive use std::io::Read; - let mut answer = String::with_capacity(24); // FIXME: Always read to message end, not into a buffer of fixed size - let read_bytes = self.stream.read_to_string(&mut answer).unwrap(); - println!("Read {} bytes: {}", read_bytes, answer); + let read_bytes: usize; + let read_result: (Message, usize); + loop { + + // read from stream + match self.stream.read(self.buffer) { + Ok(amount) => read_bytes = amount, + Err(e) => panic!(e), + } + + // try to parse and end reading as soon as parsing successful + match Message::parse(&self.buffer) { + Ok(result) => { + read_result = result; + break; + }, + Err(_) => {}, // continue + } + } + + println!("Read {} bytes: {:?}", read_bytes, read_result.0); } } diff --git a/src/main.rs b/src/main.rs index acf87ba..8658368 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,8 +84,7 @@ fn main() { // FIXME temp let mut con = connection::Connection::new().unwrap(); - con.send("{3|4:want,4:core,1:1,}"); - con.read(); + con.send_and_receive("{3|4:want,4:core,1:1,}"); std::process::exit(0); // evaluate command line argument From 7fb95b2140d8f30f623b6da7c7288b0221038e07 Mon Sep 17 00:00:00 2001 From: laerling Date: Sun, 21 Oct 2018 10:26:48 +0200 Subject: [PATCH 3/6] Synchronous sending/receiving - Use [u8; 1024] for now - Better error reporting when socket not found - Use correct vt6 path (changed when vt6tokio was introduced) --- Cargo.toml | 2 +- src/connection.rs | 49 +++++++++++++++++++++-------------------------- src/main.rs | 3 ++- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index adc61de..8f3bd59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,4 @@ authors = ["lærling "] conch-parser = "^0.1.0" conch-runtime = "^0.1.4" tokio-core = "^0.1.17" -vt6 = { path = "../vt6.rs" } \ No newline at end of file +vt6 = { path = "../vt6.rs/vt6" } \ No newline at end of file diff --git a/src/connection.rs b/src/connection.rs index 2e0b08a..dbd54eb 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -24,11 +24,12 @@ use std::path::PathBuf; use std::io::Error; use std::io::ErrorKind; use vt6::common::core::msg::Message; +use std::io::Read; /// Encapsulates the server connection pub struct Connection { stream: UnixStream, - buffer: Vec, + buffer: [u8; 1024], } impl Connection { @@ -37,44 +38,38 @@ impl Connection { pub fn new() -> Result { if let Some(vt6_socket_var) = vars().find(|var| var.0 == "VT6") { - return Ok(Connection { - stream: UnixStream::connect(PathBuf::from(vt6_socket_var.1))?, - buffer: vec![0;1024], - }); + let con = Connection { + stream: match UnixStream::connect(PathBuf::from(&vt6_socket_var.1)) { + Ok(stream) => stream, + Err(e) => { eprintln!("Cannot connect to socket '{}'", vt6_socket_var.1); panic!(e); }, + }, + buffer: [0; 1024], + }; + return Ok(con); } Err(Error::new(ErrorKind::NotFound, "VT6 server connection not found.")) } - /// sends a message and waits for the response synchronously - pub fn send_and_receive(&mut self, msg: &str) { - - // send - // TODO: Use vt6 messages - self.stream.write_all(msg.as_bytes()).unwrap(); - - // receive - use std::io::Read; - let read_bytes: usize; - let read_result: (Message, usize); + /// waits for a response (synchronously) + pub fn send_and_receive(&mut self, msg: &str) -> (Message, usize) { loop { - // read from stream - match self.stream.read(self.buffer) { - Ok(amount) => read_bytes = amount, - Err(e) => panic!(e), - } + // send + self.stream.write_all(msg.as_bytes()).unwrap(); // TODO: Use vt6 messages + + // read from stream... + self.stream.read(&mut self.buffer).ok(); - // try to parse and end reading as soon as parsing successful + // ...until there is something that can be parsed match Message::parse(&self.buffer) { - Ok(result) => { - read_result = result; - break; - }, + // TODO: Why can't we do 'Ok(x) => return x,'??? + Ok(_) => break, // we cannot return immediately Err(_) => {}, // continue } } - println!("Read {} bytes: {:?}", read_bytes, read_result.0); + // return + Message::parse(&self.buffer).unwrap() } } diff --git a/src/main.rs b/src/main.rs index 8658368..7fab8c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,7 +84,8 @@ fn main() { // FIXME temp let mut con = connection::Connection::new().unwrap(); - con.send_and_receive("{3|4:want,4:core,1:1,}"); + println!("{}", con.send_and_receive("{3|4:want,4:core,1:1,}").0); + println!("{}", con.send_and_receive("{3|4:want,4:LmAo,1:1,}").0); std::process::exit(0); // evaluate command line argument From 79953badf2bd6030246e9b200d97c1416a86b023 Mon Sep 17 00:00:00 2001 From: laerling Date: Sat, 27 Oct 2018 11:28:13 +0200 Subject: [PATCH 4/6] Fix: Messages are being sent in endless loop --- src/connection.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/connection.rs b/src/connection.rs index dbd54eb..f48ab51 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -53,10 +53,11 @@ impl Connection { /// waits for a response (synchronously) pub fn send_and_receive(&mut self, msg: &str) -> (Message, usize) { - loop { - // send - self.stream.write_all(msg.as_bytes()).unwrap(); // TODO: Use vt6 messages + // send + self.stream.write_all(msg.as_bytes()).unwrap(); // TODO: Use vt6 messages + + loop { // read from stream... self.stream.read(&mut self.buffer).ok(); From a75f0bfe5eeaf4f181221583192e660014c11b0a Mon Sep 17 00:00:00 2001 From: laerling Date: Sat, 27 Oct 2018 17:01:22 +0200 Subject: [PATCH 5/6] Append message parts to each other until parsing is successful --- src/connection.rs | 29 ++++++++++++++++++++--------- src/main.rs | 4 ++-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/connection.rs b/src/connection.rs index f48ab51..236f759 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -26,10 +26,12 @@ use std::io::ErrorKind; use vt6::common::core::msg::Message; use std::io::Read; +const BUF_SIZE: usize = 1024; + /// Encapsulates the server connection pub struct Connection { stream: UnixStream, - buffer: [u8; 1024], + buffer: [u8; BUF_SIZE], } impl Connection { @@ -43,12 +45,12 @@ impl Connection { Ok(stream) => stream, Err(e) => { eprintln!("Cannot connect to socket '{}'", vt6_socket_var.1); panic!(e); }, }, - buffer: [0; 1024], + buffer: [0; BUF_SIZE], }; return Ok(con); } - Err(Error::new(ErrorKind::NotFound, "VT6 server connection not found.")) + Err(Error::new(ErrorKind::NotFound, "VT6 server socket not found.")) } /// waits for a response (synchronously) @@ -57,20 +59,29 @@ impl Connection { // send self.stream.write_all(msg.as_bytes()).unwrap(); // TODO: Use vt6 messages + // FIXME: When the server closes the connection amidst sending a message, the loop keeps running + + // read until there is something that can be parsed + let mut buffer_offset: usize = 0; loop { - // read from stream... - self.stream.read(&mut self.buffer).ok(); + // read into buffer... + let bytes_read = self.stream.read(&mut self.buffer[buffer_offset..]).unwrap(); + + // adjust offset for next read + buffer_offset += bytes_read; // ...until there is something that can be parsed - match Message::parse(&self.buffer) { - // TODO: Why can't we do 'Ok(x) => return x,'??? - Ok(_) => break, // we cannot return immediately + match Message::parse(&self.buffer[..buffer_offset]) { + Ok(_) => break, Err(_) => {}, // continue } } // return - Message::parse(&self.buffer).unwrap() + let (msg, consumed) = Message::parse(&self.buffer[..buffer_offset]).unwrap(); + + // return + (msg, consumed) } } diff --git a/src/main.rs b/src/main.rs index 7fab8c5..2e88bec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,8 +84,8 @@ fn main() { // FIXME temp let mut con = connection::Connection::new().unwrap(); - println!("{}", con.send_and_receive("{3|4:want,4:core,1:1,}").0); - println!("{}", con.send_and_receive("{3|4:want,4:LmAo,1:1,}").0); + println!("main: core: {}", con.send_and_receive("{3|4:want,4:core,1:1,}").0); + println!("main: LmAo: {}", con.send_and_receive("{3|4:want,4:LmAo,1:1,}").0); std::process::exit(0); // evaluate command line argument From 3c916815002d5b8946c563ca07fc34ae0b5c4954 Mon Sep 17 00:00:00 2001 From: laerling Date: Tue, 30 Oct 2018 19:37:49 +0100 Subject: [PATCH 6/6] Fix: connection loss causes endless loop --- src/connection.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/connection.rs b/src/connection.rs index 236f759..69e94ac 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -43,7 +43,10 @@ impl Connection { let con = Connection { stream: match UnixStream::connect(PathBuf::from(&vt6_socket_var.1)) { Ok(stream) => stream, - Err(e) => { eprintln!("Cannot connect to socket '{}'", vt6_socket_var.1); panic!(e); }, + Err(e) => { + eprintln!("Cannot connect to socket '{}'", vt6_socket_var.1); + panic!(e); // TODO: Only in debug profile, else exit with 1 + }, }, buffer: [0; BUF_SIZE], }; @@ -53,20 +56,24 @@ impl Connection { Err(Error::new(ErrorKind::NotFound, "VT6 server socket not found.")) } - /// waits for a response (synchronously) + /// sends a message and waits for the response (synchronously) pub fn send_and_receive(&mut self, msg: &str) -> (Message, usize) { // send self.stream.write_all(msg.as_bytes()).unwrap(); // TODO: Use vt6 messages - // FIXME: When the server closes the connection amidst sending a message, the loop keeps running - // read until there is something that can be parsed let mut buffer_offset: usize = 0; loop { // read into buffer... - let bytes_read = self.stream.read(&mut self.buffer[buffer_offset..]).unwrap(); + let bytes_read = match self.stream.read(&mut self.buffer[buffer_offset..]) { + Ok(b) => b, + Err(e) => { + eprintln!("Connection to server socket lost"); + panic!(e); // TODO: Only in debug profile, else exit with 1 + } + }; // adjust offset for next read buffer_offset += bytes_read; @@ -78,10 +85,6 @@ impl Connection { } } - // return - let (msg, consumed) = Message::parse(&self.buffer[..buffer_offset]).unwrap(); - - // return - (msg, consumed) + return Message::parse(&self.buffer[..buffer_offset]).unwrap(); } }