annotate rust/chg/src/attachio.rs @ 39972:7a0ffdd4af78

rust-chg: add future that handles "attachio" request This is the sequence to send client-side stdio and pager stdin to the server.
author Yuya Nishihara <yuya@tcha.org>
date Mon, 24 Sep 2018 16:59:12 +0900
parents
children ce088b38f92b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
1 // Copyright 2018 Yuya Nishihara <yuya@tcha.org>
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
2 //
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
3 // This software may be used and distributed according to the terms of the
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
4 // GNU General Public License version 2 or any later version.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
5
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
6 //! Functions to send client-side fds over the command server channel.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
7
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
8 use futures::{Async, Future, Poll};
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
9 use std::io;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
10 use std::os::unix::io::AsRawFd;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
11 use tokio_hglib::{Client, Connection};
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
12 use tokio_hglib::codec::ChannelMessage;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
13 use tokio_hglib::protocol::MessageLoop;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
14
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
15 use super::message;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
16 use super::procutil;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
17
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
18 /// Future to send client-side fds over the command server channel.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
19 ///
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
20 /// This works as follows:
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
21 /// 1. Client sends "attachio" request.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
22 /// 2. Server sends back 1-byte input request.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
23 /// 3. Client sends fds with 1-byte dummy payload in response.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
24 /// 4. Server returns the number of the fds received.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
25 ///
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
26 /// If the stderr is omitted, it will be redirected to the stdout. This
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
27 /// allows us to attach the pager stdin to both stdout and stderr, and
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
28 /// dispose of the client-side handle once attached.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
29 #[must_use = "futures do nothing unless polled"]
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
30 pub struct AttachIo<C, I, O, E>
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
31 where C: Connection,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
32 {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
33 msg_loop: MessageLoop<C>,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
34 stdin: I,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
35 stdout: O,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
36 stderr: Option<E>,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
37 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
38
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
39 impl<C, I, O, E> AttachIo<C, I, O, E>
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
40 where C: Connection + AsRawFd,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
41 I: AsRawFd,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
42 O: AsRawFd,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
43 E: AsRawFd,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
44 {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
45 pub fn with_client(client: Client<C>, stdin: I, stdout: O, stderr: Option<E>)
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
46 -> AttachIo<C, I, O, E> {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
47 let msg_loop = MessageLoop::start(client, b"attachio");
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
48 AttachIo { msg_loop, stdin, stdout, stderr }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
49 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
50 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
51
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
52 impl<C, I, O, E> Future for AttachIo<C, I, O, E>
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
53 where C: Connection + AsRawFd,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
54 I: AsRawFd,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
55 O: AsRawFd,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
56 E: AsRawFd,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
57 {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
58 type Item = Client<C>;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
59 type Error = io::Error;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
60
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
61 fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
62 loop {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
63 let (client, msg) = try_ready!(self.msg_loop.poll());
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
64 match msg {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
65 ChannelMessage::Data(b'r', data) => {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
66 let fd_cnt = message::parse_result_code(data)?;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
67 if fd_cnt == 3 {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
68 return Ok(Async::Ready(client));
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
69 } else {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
70 return Err(io::Error::new(io::ErrorKind::InvalidData,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
71 "unexpected attachio result"));
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
72 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
73 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
74 ChannelMessage::Data(..) => {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
75 // just ignore data sent to uninteresting (optional) channel
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
76 self.msg_loop = MessageLoop::resume(client);
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
77 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
78 ChannelMessage::InputRequest(1) => {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
79 // this may fail with EWOULDBLOCK in theory, but the
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
80 // payload is quite small, and the send buffer should
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
81 // be empty so the operation will complete immediately
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
82 let sock_fd = client.as_raw_fd();
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
83 let ifd = self.stdin.as_raw_fd();
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
84 let ofd = self.stdout.as_raw_fd();
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
85 let efd = self.stderr.as_ref().map_or(ofd, |f| f.as_raw_fd());
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
86 procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
87 self.msg_loop = MessageLoop::resume(client);
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
88 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
89 ChannelMessage::InputRequest(..) | ChannelMessage::LineRequest(..) |
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
90 ChannelMessage::SystemRequest(..) => {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
91 return Err(io::Error::new(io::ErrorKind::InvalidData,
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
92 "unsupported request while attaching io"));
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
93 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
94 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
95 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
96 }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
97 }