|
1 | | -use ironrdp_core::impl_as_any; |
2 | | -use ironrdp_dvc::{DvcClientProcessor, DvcMessage, DvcProcessor}; |
3 | | -use ironrdp_pdu::{pdu_other_err, PduResult}; |
4 | | -use ironrdp_svc::SvcMessage; |
5 | | - |
6 | | -/// A proxy DVC pipe client that forwards DVC messages to/from a named pipe server. |
7 | | -pub struct DvcNamedPipeProxy { |
8 | | - channel_name: String, |
| 1 | +use async_trait::async_trait; |
| 2 | +use tokio::fs; |
| 3 | +use tokio::io::{AsyncReadExt, AsyncWriteExt}; |
| 4 | + |
| 5 | +use crate::error::DvcPipeProxyError; |
| 6 | +use crate::os_pipe::OsPipe; |
| 7 | + |
| 8 | +/// Unix-specific implementation of the OS pipe trait. |
| 9 | +pub(crate) struct UnixPipe { |
| 10 | + socket: tokio::net::UnixStream, |
9 | 11 | } |
10 | 12 |
|
11 | | -impl DvcNamedPipeProxy { |
12 | | - /// Creates a new DVC named pipe proxy. |
13 | | - /// `dvc_write_callback` is called when the proxy receives a DVC message from the |
14 | | - /// named pipe server and the SVC message is ready to be sent to the DVC channel in the main |
15 | | - /// IronRDP active session loop. |
16 | | - pub fn new<F>(channel_name: &str, _named_pipe_name: &str, _dvc_write_callback: F) -> Self |
17 | | - where |
18 | | - F: Fn(u32, Vec<SvcMessage>) -> PduResult<()> + Send + 'static, |
19 | | - { |
20 | | - error!("DvcNamedPipeProxy is not implemented on Unix-like systems, using a stub implementation"); |
21 | | - |
22 | | - Self { |
23 | | - channel_name: channel_name.to_owned(), |
| 13 | +#[async_trait] |
| 14 | +impl OsPipe for UnixPipe { |
| 15 | + async fn connect(pipe_name: &str) -> Result<Self, DvcPipeProxyError> { |
| 16 | + // Domain socket file could already exist from a previous run. |
| 17 | + match fs::metadata(&pipe_name).await { |
| 18 | + Ok(metadata) => { |
| 19 | + use std::os::unix::fs::FileTypeExt; |
| 20 | + |
| 21 | + info!( |
| 22 | + %pipe_name, |
| 23 | + "DVC pipe already exists, removing stale file." |
| 24 | + ); |
| 25 | + |
| 26 | + // Just to be sure, check if it's indeed a socket - |
| 27 | + // throw an error if calling code accidentally passed a regular file. |
| 28 | + if !metadata.file_type().is_socket() { |
| 29 | + return Err(DvcPipeProxyError::Io(std::io::Error::new( |
| 30 | + std::io::ErrorKind::InvalidInput, |
| 31 | + format!("Path {} is not a socket", pipe_name), |
| 32 | + ))); |
| 33 | + } |
| 34 | + |
| 35 | + fs::remove_file(pipe_name).await.map_err(DvcPipeProxyError::Io)?; |
| 36 | + } |
| 37 | + Err(e) if e.kind() == std::io::ErrorKind::NotFound => { |
| 38 | + trace!( |
| 39 | + %pipe_name, |
| 40 | + "DVC pipe does not exist, creating it." |
| 41 | + ); |
| 42 | + } |
| 43 | + Err(e) => { |
| 44 | + return Err(DvcPipeProxyError::Io(e)); |
| 45 | + } |
24 | 46 | } |
25 | | - } |
26 | | -} |
27 | 47 |
|
28 | | -impl_as_any!(DvcNamedPipeProxy); |
| 48 | + let listener = tokio::net::UnixListener::bind(pipe_name).map_err(DvcPipeProxyError::Io)?; |
29 | 49 |
|
30 | | -impl DvcProcessor for DvcNamedPipeProxy { |
31 | | - fn channel_name(&self) -> &str { |
32 | | - &self.channel_name |
| 50 | + let (socket, _) = listener.accept().await.map_err(DvcPipeProxyError::Io)?; |
| 51 | + |
| 52 | + Ok(Self { socket }) |
33 | 53 | } |
34 | 54 |
|
35 | | - fn start(&mut self, _channel_id: u32) -> PduResult<Vec<DvcMessage>> { |
36 | | - Err(pdu_other_err!( |
37 | | - "DvcNamedPipeProxy is not implemented on Unix-like systems" |
38 | | - )) |
| 55 | + async fn read(&mut self, buffer: &mut [u8]) -> Result<usize, DvcPipeProxyError> { |
| 56 | + self.socket.read(buffer).await.map_err(DvcPipeProxyError::Io) |
39 | 57 | } |
40 | 58 |
|
41 | | - fn process(&mut self, _channel_id: u32, _payload: &[u8]) -> PduResult<Vec<DvcMessage>> { |
42 | | - Err(pdu_other_err!( |
43 | | - "DvcNamedPipeProxy is not implemented on Unix-like systems" |
44 | | - )) |
| 59 | + async fn write_all(&mut self, buffer: &[u8]) -> Result<(), DvcPipeProxyError> { |
| 60 | + self.socket |
| 61 | + .write_all(buffer) |
| 62 | + .await |
| 63 | + .map_err(DvcPipeProxyError::Io) |
| 64 | + .map(|_| ()) |
45 | 65 | } |
46 | 66 | } |
47 | | - |
48 | | -impl DvcClientProcessor for DvcNamedPipeProxy {} |
|
0 commit comments