diff --git a/rust/chg/src/attachio.rs b/rust/chg/src/attachio.rs --- a/rust/chg/src/attachio.rs +++ b/rust/chg/src/attachio.rs @@ -5,17 +5,15 @@ //! Functions to send client-side fds over the command server channel. -use futures::{try_ready, Async, Future, Poll}; use std::io; use std::os::unix::io::AsRawFd; use tokio_hglib::codec::ChannelMessage; -use tokio_hglib::protocol::MessageLoop; -use tokio_hglib::{Client, Connection}; +use tokio_hglib::{Connection, Protocol}; use crate::message; use crate::procutil; -/// Future to send client-side fds over the command server channel. +/// Sends client-side fds over the command server channel. /// /// This works as follows: /// 1. Client sends "attachio" request. @@ -26,58 +24,21 @@ /// If the stderr is omitted, it will be redirected to the stdout. This /// allows us to attach the pager stdin to both stdout and stderr, and /// dispose of the client-side handle once attached. -#[must_use = "futures do nothing unless polled"] -pub struct AttachIo -where - C: Connection, -{ - msg_loop: MessageLoop, - stdin: I, - stdout: O, - stderr: Option, -} - -impl AttachIo -where - C: Connection + AsRawFd, - I: AsRawFd, - O: AsRawFd, - E: AsRawFd, -{ - pub fn with_client( - client: Client, - stdin: I, - stdout: O, - stderr: Option, - ) -> AttachIo { - let msg_loop = MessageLoop::start(client, b"attachio"); - AttachIo { - msg_loop, - stdin, - stdout, - stderr, - } - } -} - -impl Future for AttachIo -where - C: Connection + AsRawFd, - I: AsRawFd, - O: AsRawFd, - E: AsRawFd, -{ - type Item = Client; - type Error = io::Error; - - fn poll(&mut self) -> Poll { +pub async fn attach_io( + proto: &mut Protocol, + stdin: impl AsRawFd, + stdout: impl AsRawFd, + stderr: Option, +) -> io::Result<()> { + // TODO: unindent + { + proto.send_command("attachio").await?; loop { - let (client, msg) = try_ready!(self.msg_loop.poll()); - match msg { + match proto.fetch_response().await? { ChannelMessage::Data(b'r', data) => { let fd_cnt = message::parse_result_code(data)?; if fd_cnt == 3 { - return Ok(Async::Ready(client)); + return Ok(()); } else { return Err(io::Error::new( io::ErrorKind::InvalidData, @@ -87,18 +48,16 @@ } ChannelMessage::Data(..) => { // just ignore data sent to uninteresting (optional) channel - self.msg_loop = MessageLoop::resume(client); } ChannelMessage::InputRequest(1) => { // this may fail with EWOULDBLOCK in theory, but the // payload is quite small, and the send buffer should // be empty so the operation will complete immediately - let sock_fd = client.as_raw_fd(); - let ifd = self.stdin.as_raw_fd(); - let ofd = self.stdout.as_raw_fd(); - let efd = self.stderr.as_ref().map_or(ofd, |f| f.as_raw_fd()); + let sock_fd = proto.as_raw_fd(); + let ifd = stdin.as_raw_fd(); + let ofd = stdout.as_raw_fd(); + let efd = stderr.as_ref().map_or(ofd, |f| f.as_raw_fd()); procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?; - self.msg_loop = MessageLoop::resume(client); } ChannelMessage::InputRequest(..) | ChannelMessage::LineRequest(..) diff --git a/rust/chg/src/lib.rs b/rust/chg/src/lib.rs --- a/rust/chg/src/lib.rs +++ b/rust/chg/src/lib.rs @@ -3,7 +3,7 @@ // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. -//mod attachio; +mod attachio; //mod clientext; //pub mod locator; pub mod message;