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