Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(windows): listen for DNS change events #4198

Merged
merged 39 commits into from
Mar 25, 2024

Conversation

ReactorScram
Copy link
Collaborator

@ReactorScram ReactorScram commented Mar 18, 2024

Tasks

@ReactorScram ReactorScram added kind/feature New feature or request area/windows_client Issues related to the Windows client area/rust_gui_client The Windows and Linux Rust GUI clients labels Mar 18, 2024
@ReactorScram ReactorScram added this to the 1.0 GA milestone Mar 18, 2024
@ReactorScram ReactorScram self-assigned this Mar 18, 2024
Copy link

vercel bot commented Mar 18, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Comments Updated (UTC)
firezone ⬜️ Ignored (Inspect) Visit Preview Mar 25, 2024 9:02pm

Copy link

github-actions bot commented Mar 18, 2024

Terraform Cloud Plan Output

Plan: 9 to add, 8 to change, 9 to destroy.

Terraform Cloud Plan

Copy link

github-actions bot commented Mar 18, 2024

Performance Test Results

TCP

Test Name Received/s Sent/s Retransmits
direct-tcp-client2server 225.5 MiB (+1%) 226.8 MiB (+1%) 188 (-50%)
direct-tcp-server2client 221.3 MiB (-2%) 222.8 MiB (-2%) 214 (+193%)
relayed-tcp-client2server 147.3 MiB (-1%) 148.0 MiB (-1%) 200 (-5%)
relayed-tcp-server2client 150.2 MiB (-4%) 150.4 MiB (-4%) 170 (-8%)

UDP

Test Name Total/s Jitter Lost
direct-udp-client2server 50.0 MiB (+0%) 0.31ms (-1%) 0.00% (NaN%)
direct-udp-server2client 50.0 MiB (+0%) 0.01ms (+13%) 0.00% (NaN%)
relayed-udp-client2server 50.0 MiB (-0%) 0.12ms (+49%) 0.00% (-100%)
relayed-udp-server2client 50.0 MiB (-0%) 0.06ms (+18%) 0.00% (NaN%)

@ReactorScram ReactorScram marked this pull request as ready for review March 18, 2024 21:54
Copy link
Member

@jamilbk jamilbk left a comment

Choose a reason for hiding this comment

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

Nice work! Just some clarifying questions.

Hopefully this is the deepest integration we'll need with the Registry for a while...

Copy link
Collaborator

@conectado conectado left a comment

Choose a reason for hiding this comment

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

Looks good! Just left a few comment but nothing big

rust/gui-client/src-tauri/src/client/gui.rs Outdated Show resolved Hide resolved
// SAFETY: It's complicated.
// The callback here can cause a lot of problems. We pin the `Notify` object.
// We don't use an `Arc` because `Notify` already has only `&self` methods, and
// the callback has no way to free an `Arc`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

The callback can decrement the Arc using Arc::from_raw

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

But when drop is called, we'll cancel the callback, which will forget the callback's cloned Arc, if the callback has not fired. We could check the Receiver to see whether we need to force the Arc to drop, but I thought it's simpler to imagine that the callback is taking a const borrow from Listener, and Drop enforces the lifetimes, and not that they're actually sharing ownership.

Copy link
Collaborator

Choose a reason for hiding this comment

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

but if we use the arc we don't need to unregister the callback, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't understand. This one is the long-lived callback registered by RegisterWaitForSingleObject and unregistered in Drop by UnregisterWaitEx. If I didn't unregister the callback, it would leak the Arc and 1 or 2 Win32 handles.

}

// Be careful with this, if you register twice before the callback fires,
// it will probably leak something. Check the MS docs for `RegNotifyChangeKeyValue`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should be an unsafe function

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Because of the constraint mentioned in that comment?
🤔 Since it's all &mut self, what if I enforce it at runtime with a flag callback_armed?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I mean, it's okay to mark this as unsafe, specially since we use it only internally, the methods using it can make sure that they are enforcing the constaints.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think it's memory-unsafe, I was thinking of this sentence from the docs https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regnotifychangekeyvalue#remarks

Each time a process calls RegNotifyChangeKeyValue with the same set of parameters, it establishes another wait operation, creating a resource leak. Therefore, check that you are not calling RegNotifyChangeKeyValue with the same parameters until the previous wait operation has completed.

I might write a unit test for some of the registry stuff, there's no equivalent Unregister function, there's just closing the event handle. Even though it's only closed at the end of the process, it would be nice to know that editing the key won't break anything.

I don't want to delete the whole `dev.firezone.client` key in case some other test needs it
github-merge-queue bot pushed a commit that referenced this pull request Mar 22, 2024
…oesn't like it (#4261)

Should fix the problem with #4198 after hooking `set_dns`
Copy link
Collaborator

@conectado conectado left a comment

Choose a reason for hiding this comment

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

I've tested that network switching works with this branch, I'd be okay to merge :)

@jamilbk jamilbk removed this from the 1.0 GA milestone Mar 25, 2024
@ReactorScram ReactorScram added this pull request to the merge queue Mar 25, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 25, 2024
@ReactorScram ReactorScram added this to the 1.0 GA milestone Mar 25, 2024
@ReactorScram
Copy link
Collaborator Author

Made this GA again since #4262 is GA and is blocked on Windows set_dns

@jamilbk
Copy link
Member

jamilbk commented Mar 25, 2024

Made this GA again since #4262 is GA and is blocked on Windows set_dns

We don't usually set milestones or projects on PRs because it just makes the board too busy. Curious if you're finding it useful though?

PRs will get auto-labeled by CI based on PR title so the changelog is nice, so it's not necessary to label them either, but labeling them doesn't hurt I suppose.

@ReactorScram
Copy link
Collaborator Author

ReactorScram commented Mar 25, 2024

@jamilbk Yeah I could use something to prioritize, since I accidentally ended up with IPC stuff that's post-GA, like this: #4277

If there's a different way I can do it without a milestone and without closing the PR (I'm worried I'd lose track of the branch and not be able to find the PR again when I'm ready to resume it), something else could work.

Edit: Maybe editing the message at the top is enough, usually I put "paused" or "waiting on" or something already.

So normally I try to finish any work-in-progress, starting with things closest to merging, and I want to remember that this PR needs my attention and the IPC PR doesn't.

In general, having PRs and issues separate is a little tough - If I put a tasklist on an issue, I may not remember to check it before merging a PR. But I can't open a PR until the issue is investigated to a certain point, so there's a period where there isn't a good place to "land" more information about an issue.

But that's how all Git forges work, I can't really think of a solution unless Github did a huge change to allow shared tasklists between issues and their PRs. I just like having those little micro-tasks that aren't big enough for a full issue, so that I know I won't forget anything.

@jamilbk
Copy link
Member

jamilbk commented Mar 25, 2024

@ReactorScram No worries, I won't change PR milestones then

@ReactorScram ReactorScram added this pull request to the merge queue Mar 25, 2024
Merged via the queue into main with commit 70c0dc1 Mar 25, 2024
138 checks passed
@ReactorScram ReactorScram deleted the feat/windows/network-and-dns-changes branch March 25, 2024 21:33

pub(crate) fn run_debug() -> Result<()> {
tracing_subscriber::fmt::init();
let rt = tokio::runtime::Runtime::new()?;
Copy link
Member

Choose a reason for hiding this comment

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

Out of curiosity, why make a new runtime here and not just make it an async function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For the debug commands I don't want to start a runtime until I know which command it'll be, in case one of them needs something odd.

It's pretty rare that it matters, there's only a couple things (COM and Tauri) that could really care what thread they're on or what's happening.

Copy link
Member

Choose a reason for hiding this comment

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

I see! I should have checked the code in more detailed, I was assuming that we use async fn main!

Comment on lines +453 to +456
tokio::select! {
_r = tokio::signal::ctrl_c() => break,
r = listener.notified() => r?,
}
Copy link
Member

Choose a reason for hiding this comment

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

Personally, I am not touching tokio::select with a 10ft pole because it has so many "interesting" features. If you only have two futures, it would suggest using futures::future::select instead which is trivial to understand when you look at the implementation.

If it is possible to remove the runtime above, you can even remove the ctrl_c listener here and just make this fn a loop of listening to be notified and compose it with ctrl_c at the outer layer of your app. I find listening to ctrl_c in main less surprising than several layers deep here.

YMMV :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/rust_gui_client The Windows and Linux Rust GUI clients area/windows_client Issues related to the Windows client kind/feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants