##// END OF EJS Templates
test-check-rust-format: specify --edition=2018...
test-check-rust-format: specify --edition=2018 rustfmt doesn't read Cargo.toml unless it's executed by cargo. https://github.com/rust-lang/rustfmt#rusts-editions

File last commit:

r45180:6bef9d43 default
r45226:f44a7d86 default
Show More
attachio.rs
114 lines | 3.7 KiB | application/rls-services+xml | RustLexer
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 // Copyright 2018 Yuya Nishihara <yuya@tcha.org>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
//! Functions to send client-side fds over the command server channel.
Yuya Nishihara
rust-chg: upgrade to 2018 edition and remove useless extern crates...
r45179 use futures::{try_ready, Async, Future, Poll};
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 use std::io;
use std::os::unix::io::AsRawFd;
use tokio_hglib::codec::ChannelMessage;
use tokio_hglib::protocol::MessageLoop;
Gregory Szorc
rust: run rustfmt...
r44270 use tokio_hglib::{Client, Connection};
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008
Yuya Nishihara
rust-chg: use "crate::" to import local modules...
r45180 use crate::message;
use crate::procutil;
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008
/// Future to send client-side fds over the command server channel.
///
/// This works as follows:
/// 1. Client sends "attachio" request.
/// 2. Server sends back 1-byte input request.
/// 3. Client sends fds with 1-byte dummy payload in response.
/// 4. Server returns the number of the fds received.
///
/// 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<C, I, O, E>
Gregory Szorc
rust: run rustfmt...
r44270 where
C: Connection,
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 {
msg_loop: MessageLoop<C>,
stdin: I,
stdout: O,
stderr: Option<E>,
}
impl<C, I, O, E> AttachIo<C, I, O, E>
Gregory Szorc
rust: run rustfmt...
r44270 where
C: Connection + AsRawFd,
I: AsRawFd,
O: AsRawFd,
E: AsRawFd,
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 {
Gregory Szorc
rust: run rustfmt...
r44270 pub fn with_client(
client: Client<C>,
stdin: I,
stdout: O,
stderr: Option<E>,
) -> AttachIo<C, I, O, E> {
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 let msg_loop = MessageLoop::start(client, b"attachio");
Gregory Szorc
rust: run rustfmt...
r44270 AttachIo {
msg_loop,
stdin,
stdout,
stderr,
}
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 }
}
impl<C, I, O, E> Future for AttachIo<C, I, O, E>
Gregory Szorc
rust: run rustfmt...
r44270 where
C: Connection + AsRawFd,
I: AsRawFd,
O: AsRawFd,
E: AsRawFd,
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 {
type Item = Client<C>;
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
let (client, msg) = try_ready!(self.msg_loop.poll());
match msg {
ChannelMessage::Data(b'r', data) => {
let fd_cnt = message::parse_result_code(data)?;
if fd_cnt == 3 {
return Ok(Async::Ready(client));
} else {
Gregory Szorc
rust: run rustfmt...
r44270 return Err(io::Error::new(
io::ErrorKind::InvalidData,
"unexpected attachio result",
));
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 }
}
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());
procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
self.msg_loop = MessageLoop::resume(client);
}
Gregory Szorc
rust: run rustfmt...
r44270 ChannelMessage::InputRequest(..)
| ChannelMessage::LineRequest(..)
| ChannelMessage::SystemRequest(..) => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"unsupported request while attaching io",
));
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 }
}
}
}
}