author | Raphaël Gomès <rgomes@octobus.net> |
Fri, 29 Nov 2019 18:33:56 +0100 | |
changeset 43832 | 1bb4e9b02984 |
parent 43818 | ce088b38f92b |
child 44688 | 1f5ab1a9363d |
permissions | -rw-r--r-- |
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::codec::ChannelMessage; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
12 |
use tokio_hglib::protocol::MessageLoop; |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
13 |
use tokio_hglib::{Client, Connection}; |
39972
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> |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
31 |
where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
32 |
C: Connection, |
39972
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
33 |
{ |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
34 |
msg_loop: MessageLoop<C>, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
35 |
stdin: I, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
36 |
stdout: O, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
37 |
stderr: Option<E>, |
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 |
|
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
40 |
impl<C, I, O, E> AttachIo<C, I, O, E> |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
41 |
where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
42 |
C: Connection + AsRawFd, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
43 |
I: AsRawFd, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
44 |
O: AsRawFd, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
45 |
E: AsRawFd, |
39972
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
46 |
{ |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
47 |
pub fn with_client( |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
48 |
client: Client<C>, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
49 |
stdin: I, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
50 |
stdout: O, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
51 |
stderr: Option<E>, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
52 |
) -> AttachIo<C, I, O, E> { |
39972
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
53 |
let msg_loop = MessageLoop::start(client, b"attachio"); |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
54 |
AttachIo { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
55 |
msg_loop, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
56 |
stdin, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
57 |
stdout, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
58 |
stderr, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
59 |
} |
39972
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 |
} |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
62 |
|
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
63 |
impl<C, I, O, E> Future for AttachIo<C, I, O, E> |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
64 |
where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
65 |
C: Connection + AsRawFd, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
66 |
I: AsRawFd, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
67 |
O: AsRawFd, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
68 |
E: AsRawFd, |
39972
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
69 |
{ |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
70 |
type Item = Client<C>; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
71 |
type Error = io::Error; |
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 |
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
|
74 |
loop { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
75 |
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
|
76 |
match msg { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
77 |
ChannelMessage::Data(b'r', data) => { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
78 |
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
|
79 |
if fd_cnt == 3 { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
80 |
return Ok(Async::Ready(client)); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
81 |
} else { |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
82 |
return Err(io::Error::new( |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
83 |
io::ErrorKind::InvalidData, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
84 |
"unexpected attachio result", |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
85 |
)); |
39972
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
86 |
} |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
87 |
} |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
88 |
ChannelMessage::Data(..) => { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
89 |
// 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
|
90 |
self.msg_loop = MessageLoop::resume(client); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
91 |
} |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
92 |
ChannelMessage::InputRequest(1) => { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
93 |
// 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
|
94 |
// 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
|
95 |
// 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
|
96 |
let sock_fd = client.as_raw_fd(); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
97 |
let ifd = self.stdin.as_raw_fd(); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
98 |
let ofd = self.stdout.as_raw_fd(); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
99 |
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
|
100 |
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
|
101 |
self.msg_loop = MessageLoop::resume(client); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
102 |
} |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
103 |
ChannelMessage::InputRequest(..) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
104 |
| ChannelMessage::LineRequest(..) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
105 |
| ChannelMessage::SystemRequest(..) => { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
106 |
return Err(io::Error::new( |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
107 |
io::ErrorKind::InvalidData, |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
108 |
"unsupported request while attaching io", |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39972
diff
changeset
|
109 |
)); |
39972
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
110 |
} |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
111 |
} |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
112 |
} |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
113 |
} |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
114 |
} |