Skip to content

feat(dvc): add DVC named pipe proxy support#791

Merged
Benoît Cortier (CBenoit) merged 8 commits into
masterfrom
feat/now-proto-dvc-server
Jun 17, 2025
Merged

feat(dvc): add DVC named pipe proxy support#791
Benoît Cortier (CBenoit) merged 8 commits into
masterfrom
feat/now-proto-dvc-server

Conversation

@pacmancoder
Copy link
Copy Markdown
Contributor

@pacmancoder Vladyslav Nikonov (pacmancoder) commented May 16, 2025

This PR adds DVC proxy implementation based on named pipes (currently windows-only), a separate fifio Unix implementation is needed.

How to test:

  • Run IronRDP pipe with NowProto pipe proxy:
    cargo run -p ironrdp-client -- -u <USER> -p <PASS> <IP> --dvc-proxy Devolutions::Now::Agent=now-proto-GLOBAL
  • Run NowDvcApp project from now-proto repo.

image

FFI is not yet implemented in this PR, it will be posted as separate follow-up PR.

@pacmancoder Vladyslav Nikonov (pacmancoder) changed the title feat(dvc): add DVC named pipe proxy support [DRAFT] feat(dvc): add DVC named pipe proxy support May 16, 2025
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2025

Coverage Report 🤖 ⚙️

Past:
Total lines: 30906
Covered lines: 19789 (64.03%)

New:
Total lines: 31018
Covered lines: 19785 (63.79%)

Diff: -0.24%

[this comment will be updated automatically]

@pacmancoder Vladyslav Nikonov (pacmancoder) changed the title [DRAFT] feat(dvc): add DVC named pipe proxy support feat(dvc): add DVC named pipe proxy support May 20, 2025
@pacmancoder Vladyslav Nikonov (pacmancoder) marked this pull request as ready for review May 20, 2025 15:08
}

pub struct DvcPipeProxyFactory {
rdp_input_sender: mpsc::UnboundedSender<RdpInputEvent>,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: It’s typically not ideal to use unbounded channels because there is no backpressure. You may consider a bounded channel and using async send or blocking_send instead. The sender will have to wait if the queue is full, creating (typically) necessary backpressure when the target system is overloaded.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am re-using the already existing RdpInputEvent channel, which is tokio::mpsc::Unbounded*, I agree that we need to change that in follow-up

Comment thread crates/ironrdp-client/src/rdp.rs
Comment thread crates/ironrdp-dvc-pipe-proxy/README.md
Comment thread crates/ironrdp-dvc-pipe-proxy/CHANGELOG.md
Comment thread crates/ironrdp-dvc-pipe-proxy/src/platform/windows/mod.rs Outdated
Comment thread crates/ironrdp-dvc-pipe-proxy/src/platform/windows/worker.rs Outdated
Comment thread crates/ironrdp-dvc-pipe-proxy/src/platform/windows/worker.rs Outdated
Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/error.rs
Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/event.rs Outdated
Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/handle.rs Outdated
Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/handle.rs Outdated
Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/mod.rs Outdated
Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/pipe.rs
Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/semaphore.rs Outdated
Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/wide_string.rs Outdated
Comment thread crates/ironrdp-dvc/src/client.rs
Comment thread crates/ironrdp-session/src/active_stage.rs Outdated
Comment thread crates/ironrdp-session/src/x224/mod.rs Outdated
Copy link
Copy Markdown
Member

@CBenoit Benoît Cortier (CBenoit) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Very high quality PR, as always!

However, the unsafe code needs to be reviewed carefully.

The CI is also red for macOS and Linux. Likely some Windows-specific code is not properly feature-gated.

Comment thread crates/ironrdp-dvc-pipe-proxy/Cargo.toml Outdated
// Semaphore wrapper API itself by restricting handle usage:
// - release() method which calls ReleaseSemaphore inside (which is thread-safe).
// - borrow() method which returns a BorrowedHandle for waiting on the semaphore.
// - Handle lifetime is ensured by Arc, so it is always valid when used.
Copy link
Copy Markdown
Member

@CBenoit Benoît Cortier (CBenoit) May 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: I didn’t understand the point immediately. I think that this is not an argument explaining why the type is Send, but why it’s okay to implement Clone on it: if we were not using Arc, the handle would be closed on the first Semaphore that is dropped, invaliding the other semaphores and even causing the handle to be closed multiple times. But this is unrelated to thread safety, because that would be a problem even without Send. It’s still important to document that somewhere.

// CreateSemaphoreW returns a valid handle on success.
Ok(Self {
// See `unsafe impl Send` comment.
#[allow(clippy::arc_with_non_send_sync)]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: To myself, this is a bit suspicious. I need to verify.

@pacmancoder
Copy link
Copy Markdown
Contributor Author

Benoît Cortier (@CBenoit) are there any outstanding comments blocking this merge? 👀

Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/pipe.rs Outdated
Copy link
Copy Markdown
Member

@CBenoit Benoît Cortier (CBenoit) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are implementing a safe wrapper around Windows named pipes, but I know about two libraries that are doing that:

Did you consider them? Is there a reason for not using one of these instead? That would save us from a lot of unsafe code.

@CBenoit
Copy link
Copy Markdown
Member

are there any outstanding comments blocking this merge? 👀

I just added a few extra comments, and I believe you didn’t address all of the existing comments either!
Also, I think I would like a bit more of context and explanation in the README.md for the new crate.
Since this repo is public, consider that people not familiar with the internals of RDM may stumble upon this, and wonder what is this thing.
Do you think you could look into all of this before we merge? 🙏

@pacmancoder
Copy link
Copy Markdown
Contributor Author

I think you are implementing a safe wrapper around Windows named pipes, but I know about two libraries that are doing that:

tokio (async): https://docs.rs/tokio/latest/tokio/net/windows/named_pipe/index.html
interprocess (blocking): https://docs.rs/interprocess/latest/x86_64-pc-windows-msvc/interprocess/os/windows/named_pipe/index.html

Did you consider them? Is there a reason for not using one of these instead? That would save us from a lot of unsafe code.

I did not want to use named_pipe mainly because I don't want to force tokio dependency in a relatively lightweight crate, but I'll look closer into it again, maybe the advantages (namely its cross-platform-ness) are worth reconsidering using it here. As for interprocess, I haven't looked into it, I'll look it up. Let's merge as-is and then make a switch if needed.

@pacmancoder
Copy link
Copy Markdown
Contributor Author

Benoît Cortier (@CBenoit) approve please 😅

@CBenoit
Copy link
Copy Markdown
Member

Benoît Cortier (@CBenoit) approve please 😅

Sure thing – reviewing now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: Good README.md, thank you!

Comment on lines +52 to +55
// Standard generic syntax is used instead if `impl` because of the following lint:
// > warning: lifetime parameter `'a` only used once
//
// Fixing this lint (use of '_ lifetime) produces compiler error.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue? Maybe this comment is outdated

Comment thread crates/ironrdp-dvc-pipe-proxy/src/windows/semaphore.rs
Copy link
Copy Markdown
Member

@CBenoit Benoît Cortier (CBenoit) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Please, follow up the remaining comments in separate PRs when you have some time

@CBenoit Benoît Cortier (CBenoit) enabled auto-merge (squash) June 17, 2025 09:36
@CBenoit Benoît Cortier (CBenoit) merged commit 5482365 into master Jun 17, 2025
10 checks passed
@CBenoit Benoît Cortier (CBenoit) deleted the feat/now-proto-dvc-server branch June 17, 2025 10:16
@CBenoit
Copy link
Copy Markdown
Member

I think you are implementing a safe wrapper around Windows named pipes, but I know about two libraries that are doing that:

tokio (async): https://docs.rs/tokio/latest/tokio/net/windows/named_pipe/index.html
interprocess (blocking): https://docs.rs/interprocess/latest/x86_64-pc-windows-msvc/interprocess/os/windows/named_pipe/index.html

Did you consider them? Is there a reason for not using one of these instead? That would save us from a lot of unsafe code.

I did not want to use named_pipe mainly because I don't want to force tokio dependency in a relatively lightweight crate, but I'll look closer into it again, maybe the advantages (namely its cross-platform-ness) are worth reconsidering using it here. As for interprocess, I haven't looked into it, I'll look it up. Let's merge as-is and then make a switch if needed.

Indeed, I wouldn’t necessarily want tokio either at this point. interprocess does not require tokio, but we’ll see if it’s worth it.

Vladyslav Nikonov (pacmancoder) added a commit that referenced this pull request Aug 4, 2025
### Changes
- Make dvc named pipe proxy cross-platform (Unix implementation via
`tokio::net::unix::UnixStream`)
- Removed unsafe code for Windows implementation, switched to
`tokio::net::windows::named_pipe`

### Testing
This feature can be used in the [same
way](#791) as on Windows,
however instead of GUI test app there is new basic
[CLI](Devolutions/now-proto#31) app
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants