Closed thomasantony closed 4 years ago
I'm currently sick in bed with stomach pains, so I'll look later into this. I didn't quite understand your use case. I don't understand "repl that is presented over a raw TcpStream". Can you explain this?
I have been using this to interact with a device that presents a console over a serial port. We send commands and read responses/prompts from the device over this interface. In our particular use case, we have a separate TCP bridge program that passes through data from a TCP port to the serial port and back. We connect to it using a TCPStream
and I use StreamSession
to send commands and read responses from the device. We still use the send_line
and exp_string
methods like your examples, but the data goes over TCP and then a serial port instead of a shell command.
StreamSession
would also work with a direct serial port connection. A rust library like serialport implements the Read
and Write
traits and StreamSession
could be used with that.
Basically, StreamSession
makes it so you can use rexpect
with any system that implements the Read
and Write
traits regardless of the underlying implementation.
Here is an example:
use rexpect::spawn_stream;
use std::net::TcpStream;
fn main() -> Result<(), Box<dyn Error>>
{
let tcp = TcpStream::connect("127.0.0.1:1234")?;
let tcp_w = tcp.try_clone()?;
let mut session = spawn_stream(tcp, tcp_w, Some(2000));
loop {
// This loop waits until we get a command prompt from the device
session.send_line(" ")?; // get command prompt
match session.exp_string(">") {
Ok(_) => break, // Got prompt! break the loop
Err(_) => println!("Device is not responding, trying again."), // Keep trying
};
}
// Do other stuff with session
Ok(())
}
I just checked about the "less context on error", and the loss of information is minimal. When giving a wrong argument to ftp. Before PR:
thread 'main' panicked at 'ftp job failed with EOF (End of File): Expected Regex: "Name \(.*\):" but got EOF after reading "ftp: invalid option -- 'l'
Try 'ftp --help' or 'ftp --usage' for more information.
", process terminated with "Exited(Pid(24427), 64)"', examples/ftp.rs:24:33
after PR:
thread 'main' panicked at 'ftp job failed with EOF (End of File): Expected Regex: "Name \(.*\):" but got EOF after reading "ftp: invalid option -- 'l'
Try 'ftp --help' or 'ftp --usage' for more information.
", process terminated with "unknown"', examples/ftp.rs:24:33
=> seems ok to me, as pid and exit code are usually not crucial for debugging
thanks @thomasantony for this pull PR. Elegantly solved and now allows also sessions over TCP, I'll add an example to master branch (didn't see any way I can add a file in your PR, I only could edit the changes…)
I wanted to use
rexpect
with a REPL that is presented over a rawTcpStream
(and possibly a serial link in the future). The changes I have made creates a genericStreamSession
struct that can take something that implementsRead
and something that implementsWrite
instead of being forced to use a command-line program.I have also updated
PtySession
to use this. One drawback is that "exp()" no longer gives extra context on error. I am open to suggestions. Thanks!