##// END OF EJS Templates
rust-chg: have attach_io() simply take reference of AsRawFd object...
Yuya Nishihara -
r45233:cb5822e6 default
parent child Browse files
Show More
@@ -1,73 +1,71 b''
1 1 // Copyright 2018 Yuya Nishihara <yuya@tcha.org>
2 2 //
3 3 // This software may be used and distributed according to the terms of the
4 4 // GNU General Public License version 2 or any later version.
5 5
6 6 //! Functions to send client-side fds over the command server channel.
7 7
8 8 use std::io;
9 9 use std::os::unix::io::AsRawFd;
10 10 use tokio_hglib::codec::ChannelMessage;
11 11 use tokio_hglib::{Connection, Protocol};
12 12
13 13 use crate::message;
14 14 use crate::procutil;
15 15
16 16 /// Sends client-side fds over the command server channel.
17 17 ///
18 18 /// This works as follows:
19 19 /// 1. Client sends "attachio" request.
20 20 /// 2. Server sends back 1-byte input request.
21 21 /// 3. Client sends fds with 1-byte dummy payload in response.
22 22 /// 4. Server returns the number of the fds received.
23 23 ///
24 /// If the stderr is omitted, it will be redirected to the stdout. This
25 /// allows us to attach the pager stdin to both stdout and stderr, and
26 /// dispose of the client-side handle once attached.
24 /// The client-side fds may be dropped once duplicated to the server.
27 25 pub async fn attach_io(
28 26 proto: &mut Protocol<impl Connection + AsRawFd>,
29 stdin: impl AsRawFd,
30 stdout: impl AsRawFd,
31 stderr: Option<impl AsRawFd>,
27 stdin: &impl AsRawFd,
28 stdout: &impl AsRawFd,
29 stderr: &impl AsRawFd,
32 30 ) -> io::Result<()> {
33 31 // TODO: unindent
34 32 {
35 33 proto.send_command("attachio").await?;
36 34 loop {
37 35 match proto.fetch_response().await? {
38 36 ChannelMessage::Data(b'r', data) => {
39 37 let fd_cnt = message::parse_result_code(data)?;
40 38 if fd_cnt == 3 {
41 39 return Ok(());
42 40 } else {
43 41 return Err(io::Error::new(
44 42 io::ErrorKind::InvalidData,
45 43 "unexpected attachio result",
46 44 ));
47 45 }
48 46 }
49 47 ChannelMessage::Data(..) => {
50 48 // just ignore data sent to uninteresting (optional) channel
51 49 }
52 50 ChannelMessage::InputRequest(1) => {
53 51 // this may fail with EWOULDBLOCK in theory, but the
54 52 // payload is quite small, and the send buffer should
55 53 // be empty so the operation will complete immediately
56 54 let sock_fd = proto.as_raw_fd();
57 55 let ifd = stdin.as_raw_fd();
58 56 let ofd = stdout.as_raw_fd();
59 let efd = stderr.as_ref().map_or(ofd, |f| f.as_raw_fd());
57 let efd = stderr.as_raw_fd();
60 58 procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
61 59 }
62 60 ChannelMessage::InputRequest(..)
63 61 | ChannelMessage::LineRequest(..)
64 62 | ChannelMessage::SystemRequest(..) => {
65 63 return Err(io::Error::new(
66 64 io::ErrorKind::InvalidData,
67 65 "unsupported request while attaching io",
68 66 ));
69 67 }
70 68 }
71 69 }
72 70 }
73 71 }
General Comments 0
You need to be logged in to leave comments. Login now