Show More
@@ -1,73 +1,71 b'' | |||||
1 | // Copyright 2018 Yuya Nishihara <yuya@tcha.org> |
|
1 | // Copyright 2018 Yuya Nishihara <yuya@tcha.org> | |
2 | // |
|
2 | // | |
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 | //! 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 std::io; |
|
8 | use std::io; | |
9 | use std::os::unix::io::AsRawFd; |
|
9 | use std::os::unix::io::AsRawFd; | |
10 | use tokio_hglib::codec::ChannelMessage; |
|
10 | use tokio_hglib::codec::ChannelMessage; | |
11 | use tokio_hglib::{Connection, Protocol}; |
|
11 | use tokio_hglib::{Connection, Protocol}; | |
12 |
|
12 | |||
13 | use crate::message; |
|
13 | use crate::message; | |
14 | use crate::procutil; |
|
14 | use crate::procutil; | |
15 |
|
15 | |||
16 | /// Sends client-side fds over the command server channel. |
|
16 | /// Sends client-side fds over the command server channel. | |
17 | /// |
|
17 | /// | |
18 | /// This works as follows: |
|
18 | /// This works as follows: | |
19 | /// 1. Client sends "attachio" request. |
|
19 | /// 1. Client sends "attachio" request. | |
20 | /// 2. Server sends back 1-byte input request. |
|
20 | /// 2. Server sends back 1-byte input request. | |
21 | /// 3. Client sends fds with 1-byte dummy payload in response. |
|
21 | /// 3. Client sends fds with 1-byte dummy payload in response. | |
22 | /// 4. Server returns the number of the fds received. |
|
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 |
|
24 | /// The client-side fds may be dropped once duplicated to the server. | |
25 | /// allows us to attach the pager stdin to both stdout and stderr, and |
|
|||
26 | /// dispose of the client-side handle once attached. |
|
|||
27 | pub async fn attach_io( |
|
25 | pub async fn attach_io( | |
28 | proto: &mut Protocol<impl Connection + AsRawFd>, |
|
26 | proto: &mut Protocol<impl Connection + AsRawFd>, | |
29 | stdin: impl AsRawFd, |
|
27 | stdin: &impl AsRawFd, | |
30 | stdout: impl AsRawFd, |
|
28 | stdout: &impl AsRawFd, | |
31 |
stderr: |
|
29 | stderr: &impl AsRawFd, | |
32 | ) -> io::Result<()> { |
|
30 | ) -> io::Result<()> { | |
33 | // TODO: unindent |
|
31 | // TODO: unindent | |
34 | { |
|
32 | { | |
35 | proto.send_command("attachio").await?; |
|
33 | proto.send_command("attachio").await?; | |
36 | loop { |
|
34 | loop { | |
37 | match proto.fetch_response().await? { |
|
35 | match proto.fetch_response().await? { | |
38 | ChannelMessage::Data(b'r', data) => { |
|
36 | ChannelMessage::Data(b'r', data) => { | |
39 | let fd_cnt = message::parse_result_code(data)?; |
|
37 | let fd_cnt = message::parse_result_code(data)?; | |
40 | if fd_cnt == 3 { |
|
38 | if fd_cnt == 3 { | |
41 | return Ok(()); |
|
39 | return Ok(()); | |
42 | } else { |
|
40 | } else { | |
43 | return Err(io::Error::new( |
|
41 | return Err(io::Error::new( | |
44 | io::ErrorKind::InvalidData, |
|
42 | io::ErrorKind::InvalidData, | |
45 | "unexpected attachio result", |
|
43 | "unexpected attachio result", | |
46 | )); |
|
44 | )); | |
47 | } |
|
45 | } | |
48 | } |
|
46 | } | |
49 | ChannelMessage::Data(..) => { |
|
47 | ChannelMessage::Data(..) => { | |
50 | // just ignore data sent to uninteresting (optional) channel |
|
48 | // just ignore data sent to uninteresting (optional) channel | |
51 | } |
|
49 | } | |
52 | ChannelMessage::InputRequest(1) => { |
|
50 | ChannelMessage::InputRequest(1) => { | |
53 | // this may fail with EWOULDBLOCK in theory, but the |
|
51 | // this may fail with EWOULDBLOCK in theory, but the | |
54 | // payload is quite small, and the send buffer should |
|
52 | // payload is quite small, and the send buffer should | |
55 | // be empty so the operation will complete immediately |
|
53 | // be empty so the operation will complete immediately | |
56 | let sock_fd = proto.as_raw_fd(); |
|
54 | let sock_fd = proto.as_raw_fd(); | |
57 | let ifd = stdin.as_raw_fd(); |
|
55 | let ifd = stdin.as_raw_fd(); | |
58 | let ofd = stdout.as_raw_fd(); |
|
56 | let ofd = stdout.as_raw_fd(); | |
59 |
let efd = stderr. |
|
57 | let efd = stderr.as_raw_fd(); | |
60 | procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?; |
|
58 | procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?; | |
61 | } |
|
59 | } | |
62 | ChannelMessage::InputRequest(..) |
|
60 | ChannelMessage::InputRequest(..) | |
63 | | ChannelMessage::LineRequest(..) |
|
61 | | ChannelMessage::LineRequest(..) | |
64 | | ChannelMessage::SystemRequest(..) => { |
|
62 | | ChannelMessage::SystemRequest(..) => { | |
65 | return Err(io::Error::new( |
|
63 | return Err(io::Error::new( | |
66 | io::ErrorKind::InvalidData, |
|
64 | io::ErrorKind::InvalidData, | |
67 | "unsupported request while attaching io", |
|
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