Show More
@@ -5,17 +5,15 b'' | |||||
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 futures::{try_ready, Async, Future, Poll}; |
|
|||
9 | use std::io; |
|
8 | use std::io; | |
10 | use std::os::unix::io::AsRawFd; |
|
9 | use std::os::unix::io::AsRawFd; | |
11 | use tokio_hglib::codec::ChannelMessage; |
|
10 | use tokio_hglib::codec::ChannelMessage; | |
12 |
use tokio_hglib:: |
|
11 | use tokio_hglib::{Connection, Protocol}; | |
13 | use tokio_hglib::{Client, Connection}; |
|
|||
14 |
|
12 | |||
15 | use crate::message; |
|
13 | use crate::message; | |
16 | use crate::procutil; |
|
14 | use crate::procutil; | |
17 |
|
15 | |||
18 |
/// |
|
16 | /// Sends client-side fds over the command server channel. | |
19 | /// |
|
17 | /// | |
20 | /// This works as follows: |
|
18 | /// This works as follows: | |
21 | /// 1. Client sends "attachio" request. |
|
19 | /// 1. Client sends "attachio" request. | |
@@ -26,58 +24,21 b' use crate::procutil;' | |||||
26 | /// If the stderr is omitted, it will be redirected to the stdout. This |
|
24 | /// 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 |
|
25 | /// allows us to attach the pager stdin to both stdout and stderr, and | |
28 | /// dispose of the client-side handle once attached. |
|
26 | /// dispose of the client-side handle once attached. | |
29 | #[must_use = "futures do nothing unless polled"] |
|
27 | pub async fn attach_io( | |
30 | pub struct AttachIo<C, I, O, E> |
|
28 | proto: &mut Protocol<impl Connection + AsRawFd>, | |
31 | where |
|
29 | stdin: impl AsRawFd, | |
32 | C: Connection, |
|
30 | stdout: impl AsRawFd, | |
33 | { |
|
31 | stderr: Option<impl AsRawFd>, | |
34 | msg_loop: MessageLoop<C>, |
|
32 | ) -> io::Result<()> { | |
35 | stdin: I, |
|
33 | // TODO: unindent | |
36 | stdout: O, |
|
34 | { | |
37 | stderr: Option<E>, |
|
35 | proto.send_command("attachio").await?; | |
38 | } |
|
|||
39 |
|
||||
40 | impl<C, I, O, E> AttachIo<C, I, O, E> |
|
|||
41 | where |
|
|||
42 | C: Connection + AsRawFd, |
|
|||
43 | I: AsRawFd, |
|
|||
44 | O: AsRawFd, |
|
|||
45 | E: AsRawFd, |
|
|||
46 | { |
|
|||
47 | pub fn with_client( |
|
|||
48 | client: Client<C>, |
|
|||
49 | stdin: I, |
|
|||
50 | stdout: O, |
|
|||
51 | stderr: Option<E>, |
|
|||
52 | ) -> AttachIo<C, I, O, E> { |
|
|||
53 | let msg_loop = MessageLoop::start(client, b"attachio"); |
|
|||
54 | AttachIo { |
|
|||
55 | msg_loop, |
|
|||
56 | stdin, |
|
|||
57 | stdout, |
|
|||
58 | stderr, |
|
|||
59 | } |
|
|||
60 | } |
|
|||
61 | } |
|
|||
62 |
|
||||
63 | impl<C, I, O, E> Future for AttachIo<C, I, O, E> |
|
|||
64 | where |
|
|||
65 | C: Connection + AsRawFd, |
|
|||
66 | I: AsRawFd, |
|
|||
67 | O: AsRawFd, |
|
|||
68 | E: AsRawFd, |
|
|||
69 | { |
|
|||
70 | type Item = Client<C>; |
|
|||
71 | type Error = io::Error; |
|
|||
72 |
|
||||
73 | fn poll(&mut self) -> Poll<Self::Item, Self::Error> { |
|
|||
74 | loop { |
|
36 | loop { | |
75 | let (client, msg) = try_ready!(self.msg_loop.poll()); |
|
37 | match proto.fetch_response().await? { | |
76 | match msg { |
|
|||
77 | ChannelMessage::Data(b'r', data) => { |
|
38 | ChannelMessage::Data(b'r', data) => { | |
78 | let fd_cnt = message::parse_result_code(data)?; |
|
39 | let fd_cnt = message::parse_result_code(data)?; | |
79 | if fd_cnt == 3 { |
|
40 | if fd_cnt == 3 { | |
80 |
return Ok( |
|
41 | return Ok(()); | |
81 | } else { |
|
42 | } else { | |
82 | return Err(io::Error::new( |
|
43 | return Err(io::Error::new( | |
83 | io::ErrorKind::InvalidData, |
|
44 | io::ErrorKind::InvalidData, | |
@@ -87,18 +48,16 b' where' | |||||
87 | } |
|
48 | } | |
88 | ChannelMessage::Data(..) => { |
|
49 | ChannelMessage::Data(..) => { | |
89 | // just ignore data sent to uninteresting (optional) channel |
|
50 | // just ignore data sent to uninteresting (optional) channel | |
90 | self.msg_loop = MessageLoop::resume(client); |
|
|||
91 | } |
|
51 | } | |
92 | ChannelMessage::InputRequest(1) => { |
|
52 | ChannelMessage::InputRequest(1) => { | |
93 | // this may fail with EWOULDBLOCK in theory, but the |
|
53 | // this may fail with EWOULDBLOCK in theory, but the | |
94 | // payload is quite small, and the send buffer should |
|
54 | // payload is quite small, and the send buffer should | |
95 | // be empty so the operation will complete immediately |
|
55 | // be empty so the operation will complete immediately | |
96 |
let sock_fd = |
|
56 | let sock_fd = proto.as_raw_fd(); | |
97 |
let ifd = |
|
57 | let ifd = stdin.as_raw_fd(); | |
98 |
let ofd = |
|
58 | let ofd = stdout.as_raw_fd(); | |
99 |
let efd = |
|
59 | let efd = stderr.as_ref().map_or(ofd, |f| f.as_raw_fd()); | |
100 | procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?; |
|
60 | procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?; | |
101 | self.msg_loop = MessageLoop::resume(client); |
|
|||
102 | } |
|
61 | } | |
103 | ChannelMessage::InputRequest(..) |
|
62 | ChannelMessage::InputRequest(..) | |
104 | | ChannelMessage::LineRequest(..) |
|
63 | | ChannelMessage::LineRequest(..) |
@@ -3,7 +3,7 b'' | |||||
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 |
|
|
6 | mod attachio; | |
7 | //mod clientext; |
|
7 | //mod clientext; | |
8 | //pub mod locator; |
|
8 | //pub mod locator; | |
9 | pub mod message; |
|
9 | pub mod message; |
General Comments 0
You need to be logged in to leave comments.
Login now