From cfdfedb5b4ac38eecc9c0b65c99b88c79291ac91 Mon Sep 17 00:00:00 2001 From: TQ Hirsch Date: Wed, 11 Nov 2020 16:17:02 +0100 Subject: [PATCH] Now with rudimentary support for reading incoming records --- Cargo.toml | 1 + examples/demo3270.rs | 12 ++++++++++-- src/tn3270.rs | 43 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7539d69..8ee2b62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,4 @@ structopt = "0.3.20" anyhow = "1.0.33" thiserror = "1.0.21" bitflags = "1.2.1" +hex = "0.4.2" \ No newline at end of file diff --git a/examples/demo3270.rs b/examples/demo3270.rs index d0ffa40..13a35a2 100644 --- a/examples/demo3270.rs +++ b/examples/demo3270.rs @@ -5,7 +5,7 @@ use tn3270s::tn3270; #[derive(StructOpt)] pub struct Cli { - #[structopt(short="h", long = "host", default_value="[::1]")] + #[structopt(short="h", long = "host", default_value="::1")] host: String, #[structopt(short="p", long = "port", default_value="2101")] port: u16, @@ -14,7 +14,7 @@ pub struct Cli { fn run(mut session: tn3270::Session) -> anyhow::Result<()> { use tn3270::stream::*; - let mut record = WriteCommand::new(WriteCommandCode::Write, WCC::RESET); + let mut record = WriteCommand::new(WriteCommandCode::Write, WCC::RESET | WCC::KBD_RESTORE); let bufsz = BufferAddressCalculator { width: 80, height: 24 }; record.set_buffer_address(0) .erase_unprotected_to_address(bufsz.encode_address(79, 23)) @@ -23,6 +23,14 @@ fn run(mut session: tn3270::Session) -> anyhow::Result<()> { .send_text("Hello from Rust!"); session.send_record(record)?; + let record = session.receive_record(None)?; + if let Some(record) = record { + eprintln!("Incoming record: {:?}", hex::encode(record)); + } else { + eprintln!("No record"); + } + + std::thread::sleep(Duration::from_secs(60)); Ok(()) } diff --git a/src/tn3270.rs b/src/tn3270.rs index 32eba3b..79757c7 100644 --- a/src/tn3270.rs +++ b/src/tn3270.rs @@ -9,20 +9,21 @@ use libtelnet_rs::{ use std::net::TcpStream; use std::io::{Write, Read}; use std::time::Duration; +use std::collections::VecDeque; pub mod stream; pub struct Session { parser: Parser, - ibuf: Vec, - obuf: Vec, stream: std::net::TcpStream, term_type: Option>, is_eor: bool, is_bin: bool, + + incoming_records: VecDeque>, cur_record: Vec, } @@ -32,8 +33,7 @@ impl Session { pub fn new(stream: TcpStream) -> Result { let mut session = Session { parser: Parser::new(), - ibuf: Vec::new(), - obuf: Vec::new(), + incoming_records: VecDeque::new(), stream, term_type: None, is_bin: false, @@ -57,10 +57,9 @@ impl Session { opt.local_state && opt.remote_state } - fn process_events(&mut self, mut events: Vec) -> Result>, Error> { + fn process_events(&mut self, mut events: Vec) -> Result<(), Error> { let mut extra_events = Vec::new(); let mut sendbuf = Vec::new(); - let mut records_in = Vec::new(); while !events.is_empty() || !extra_events.is_empty() { events.append(&mut extra_events); extra_events.truncate(0); @@ -69,7 +68,7 @@ impl Session { TelnetEvents::DataSend(ref mut data) => sendbuf.append(data), TelnetEvents::DataReceive(ref mut data) => self.cur_record.append(data), TelnetEvents::IAC(TelnetIAC { command: tn_cmd::EOR }) => - records_in.push(std::mem::replace(&mut self.cur_record, Vec::new())), + self.incoming_records.push_back(std::mem::replace(&mut self.cur_record, Vec::new())), TelnetEvents::IAC(iac) => eprintln!("Unknown IAC {}", iac.command), TelnetEvents::Negotiation(TelnetNegotiation { command: tn_cmd::WILL, option: tn_opt::TTYPE }) => { eprintln!("WILL ttype"); @@ -110,8 +109,8 @@ impl Session { } eprintln!("Sending: {:?}", &sendbuf); - self.stream.write(sendbuf.as_slice())?; - Ok(records_in) + self.stream.write_all(sendbuf.as_slice())?; + Ok(()) } fn is_ready(&self) -> bool { @@ -154,5 +153,31 @@ impl Session { self.stream.write_all(send_data.as_slice()) } + + pub fn receive_record(&mut self, timeout: Option) -> std::io::Result>> { + if !self.incoming_records.is_empty() { + return Ok(self.incoming_records.pop_front()); + } + + self.stream.set_read_timeout(timeout)?; + let mut buf = vec![0; 1024]; + let mut len = self.stream.read(buf.as_mut_slice())?; + if len != 0 { + self.stream.set_nonblocking(true)?; + while len != 0 { + let events = self.parser.receive(&buf[..len]); + self.process_events(events); + len = match self.stream.read(buf.as_mut_slice()) { + Ok(len) => len, + Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => 0, + Err(err) => return Err(err), + }; + } + self.stream.set_nonblocking(false)?; + } + + self.stream.set_read_timeout(None)?; + Ok(self.incoming_records.pop_front()) + } }