Fix: Support VPN modes on MacOS without hacks with osascript #1644
+2,435
−71
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I’ve added the
SingboxHelper
daemon agent, which registers on launch with privileged mode, allowing the VPN service to run smoothly without any hacks. To implement this, I added anotherSingboxService
implementation, which is enabled by default on macOS 13+ (and honestly, I didn’t bother with settings no one’s asked for). macOS 13+ is the minimum supported version for theSMAppService
daemons API, and while there’sSMBlessJob
, it’s deprecated—so who even cares about supporting outdated macOS versions? Just to be clear, the app still works on earlier macOS versions, I just didn’t feel like writing two different daemon registration flows for those ancient OS versions.Communication with the daemon is handled by
NSXPCConnection
, which is type-safe, secure, and fast. The daemon loads thedylib
, so now all functions inlibcore
run withsudo
rights, and the VPN mode just works™.There’s also another thing: since
libcore
expects aDartDL_API
, and Swift didn’t have that out of the box, I went ahead and created one. It’s mostly a bunch of stubs, semi-auto-generated from C++ headers (don’t judge me, I’m too lazy to finish the script and upload it, but it would be super easy, I swear). The only function that’s implemented so far isDart_PostCObject
, which receives different statuses from libcore.What else, code is type-safe, with all the necessary assertions, checks, and guards. It’s not the most readable thing in the world, but who cares if it solves the problem? And if anyone cares to tidy it up, it should be pretty easy to reorganize.