##// END OF EJS Templates
rust-chg: reimplement attach_io operation as async function...
Yuya Nishihara -
r45232:1be60552 default
parent child Browse files
Show More
@@ -5,17 +5,15 b''
5
5
6 //! Functions to send client-side fds over the command server channel.
6 //! Functions to send client-side fds over the command server channel.
7
7
8 use futures::{try_ready, Async, Future, Poll};
9 use std::io;
8 use std::io;
10 use std::os::unix::io::AsRawFd;
9 use std::os::unix::io::AsRawFd;
11 use tokio_hglib::codec::ChannelMessage;
10 use tokio_hglib::codec::ChannelMessage;
12 use tokio_hglib::protocol::MessageLoop;
11 use tokio_hglib::{Connection, Protocol};
13 use tokio_hglib::{Client, Connection};
14
12
15 use crate::message;
13 use crate::message;
16 use crate::procutil;
14 use crate::procutil;
17
15
18 /// Future to send client-side fds over the command server channel.
16 /// Sends client-side fds over the command server channel.
19 ///
17 ///
20 /// This works as follows:
18 /// This works as follows:
21 /// 1. Client sends "attachio" request.
19 /// 1. Client sends "attachio" request.
@@ -26,58 +24,21 b' use crate::procutil;'
26 /// If the stderr is omitted, it will be redirected to the stdout. This
24 /// If the stderr is omitted, it will be redirected to the stdout. This
27 /// allows us to attach the pager stdin to both stdout and stderr, and
25 /// allows us to attach the pager stdin to both stdout and stderr, and
28 /// dispose of the client-side handle once attached.
26 /// dispose of the client-side handle once attached.
29 #[must_use = "futures do nothing unless polled"]
27 pub async fn attach_io(
30 pub struct AttachIo<C, I, O, E>
28 proto: &mut Protocol<impl Connection + AsRawFd>,
31 where
29 stdin: impl AsRawFd,
32 C: Connection,
30 stdout: impl AsRawFd,
33 {
31 stderr: Option<impl AsRawFd>,
34 msg_loop: MessageLoop<C>,
32 ) -> io::Result<()> {
35 stdin: I,
33 // TODO: unindent
36 stdout: O,
34 {
37 stderr: Option<E>,
35 proto.send_command("attachio").await?;
38 }
39
40 impl<C, I, O, E> AttachIo<C, I, O, E>
41 where
42 C: Connection + AsRawFd,
43 I: AsRawFd,
44 O: AsRawFd,
45 E: AsRawFd,
46 {
47 pub fn with_client(
48 client: Client<C>,
49 stdin: I,
50 stdout: O,
51 stderr: Option<E>,
52 ) -> AttachIo<C, I, O, E> {
53 let msg_loop = MessageLoop::start(client, b"attachio");
54 AttachIo {
55 msg_loop,
56 stdin,
57 stdout,
58 stderr,
59 }
60 }
61 }
62
63 impl<C, I, O, E> Future for AttachIo<C, I, O, E>
64 where
65 C: Connection + AsRawFd,
66 I: AsRawFd,
67 O: AsRawFd,
68 E: AsRawFd,
69 {
70 type Item = Client<C>;
71 type Error = io::Error;
72
73 fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
74 loop {
36 loop {
75 let (client, msg) = try_ready!(self.msg_loop.poll());
37 match proto.fetch_response().await? {
76 match msg {
77 ChannelMessage::Data(b'r', data) => {
38 ChannelMessage::Data(b'r', data) => {
78 let fd_cnt = message::parse_result_code(data)?;
39 let fd_cnt = message::parse_result_code(data)?;
79 if fd_cnt == 3 {
40 if fd_cnt == 3 {
80 return Ok(Async::Ready(client));
41 return Ok(());
81 } else {
42 } else {
82 return Err(io::Error::new(
43 return Err(io::Error::new(
83 io::ErrorKind::InvalidData,
44 io::ErrorKind::InvalidData,
@@ -87,18 +48,16 b' where'
87 }
48 }
88 ChannelMessage::Data(..) => {
49 ChannelMessage::Data(..) => {
89 // just ignore data sent to uninteresting (optional) channel
50 // just ignore data sent to uninteresting (optional) channel
90 self.msg_loop = MessageLoop::resume(client);
91 }
51 }
92 ChannelMessage::InputRequest(1) => {
52 ChannelMessage::InputRequest(1) => {
93 // this may fail with EWOULDBLOCK in theory, but the
53 // this may fail with EWOULDBLOCK in theory, but the
94 // payload is quite small, and the send buffer should
54 // payload is quite small, and the send buffer should
95 // be empty so the operation will complete immediately
55 // be empty so the operation will complete immediately
96 let sock_fd = client.as_raw_fd();
56 let sock_fd = proto.as_raw_fd();
97 let ifd = self.stdin.as_raw_fd();
57 let ifd = stdin.as_raw_fd();
98 let ofd = self.stdout.as_raw_fd();
58 let ofd = stdout.as_raw_fd();
99 let efd = self.stderr.as_ref().map_or(ofd, |f| f.as_raw_fd());
59 let efd = stderr.as_ref().map_or(ofd, |f| f.as_raw_fd());
100 procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
60 procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
101 self.msg_loop = MessageLoop::resume(client);
102 }
61 }
103 ChannelMessage::InputRequest(..)
62 ChannelMessage::InputRequest(..)
104 | ChannelMessage::LineRequest(..)
63 | ChannelMessage::LineRequest(..)
@@ -3,7 +3,7 b''
3 // This software may be used and distributed according to the terms of the
3 // This software may be used and distributed according to the terms of the
4 // GNU General Public License version 2 or any later version.
4 // GNU General Public License version 2 or any later version.
5
5
6 //mod attachio;
6 mod attachio;
7 //mod clientext;
7 //mod clientext;
8 //pub mod locator;
8 //pub mod locator;
9 pub mod message;
9 pub mod message;
General Comments 0
You need to be logged in to leave comments. Login now