How UpdateService Checks for and Applies Core Updates in v2rayN
The UpdateService class orchestrates core updates by comparing local and remote versions via the GitHub API, downloading the correct architecture-specific binary to a temporary location, and notifying the UI through callback delegates for final installation.
The v2rayN proxy client relies on external core binaries such as Xray, v2fly, and sing-box to handle network traffic. The UpdateService class located in v2rayN/ServiceLib/Services/UpdateService.cs automates the entire core-update workflow, from version detection to file retrieval, while delegating the final extraction and service restart to the UI layer via asynchronous callbacks.
The Core Update Workflow
Initializing the Download Service and Callbacks
The public entry point CheckUpdateCore begins by instantiating a DownloadService and registering event handlers for UpdateCompleted and Error (lines 56‑75). These handlers invoke the injected updateFunc callback to stream progress messages back to the caller. The method immediately signals the start of the operation by calling UpdateFunc with the localized "Start Updating" message (line 82).
Fetching Remote Version Information
The CheckUpdateAsync method (lines 13‑30) coordinates version detection by first invoking GetRemoteVersion. This helper uses DownloadService.TryDownloadString to query the GitHub API, following the latest redirect for stable releases or parsing the releases endpoint for pre-releases (lines 32‑61). The result is the tag name of the newest available core version.
Resolving the Correct Download URL
Once the remote version is known, ParseDownloadUrl (lines 16‑70) determines whether an update is required. It executes the local binary via GetCoreVersion (passing the core’s VersionArg) to parse the currently installed version. Using GetUrlFromCore, it constructs the platform-specific download URL by evaluating Utils.IsWindows, IsLinux, or IsMacOS combined with RuntimeInformation.ProcessArchitecture. If the remote version is less than or equal to the local version, the method returns a failure result; otherwise, it populates result.Url (lines 62‑65).
Downloading and Reporting Progress
When CheckUpdateAsync returns a valid URL, CheckUpdateCore generates a temporary file path via Utils.GetTempPath and initiates the download through downloadHandle.DownloadFileAsync(url, fileName, true, _timeout) (line 92). Upon completion, the UpdateCompleted event fires, invoking UpdateFunc(true, fileName) to hand the archive path to the UI for extraction (lines 58‑71). Errors are reported via UpdateFunc(false, message).
Key Implementation Details
Architecture-Aware Asset Resolution
Actual download URLs are not hardcoded in UpdateService. Instead, CoreInfoManager provides CoreInfo objects containing per-core metadata, including download URL templates for each supported platform. The GetUrlFromCore helper selects the correct GitHub release asset based on the runtime operating system and CPU architecture, ensuring Windows users receive .zip archives while Linux and macOS users get the appropriate binaries.
Version Comparison Logic
The service prevents unnecessary downloads by executing a direct comparison in ParseDownloadUrl. After normalizing version strings from the local binary output and the remote GitHub tag, the logic skips the download if curVersion >= version, immediately notifying the UI that the core is already up-to-date.
Using UpdateService in Practice
Instantiate the service with a callback delegate and check for a stable release:
// UI-side: define a simple progress callback
Func<bool, string, Task> updateCallback = async (notify, msg) =>
{
// `notify == true` means the file path is ready
if (notify)
Console.WriteLine($"Core archive ready: {msg}");
else
Console.WriteLine(msg);
};
// Create the service (pass the global Config instance)
var updater = new UpdateService(Config.Instance, updateCallback);
// Request an update for the V2Ray core (stable release)
await updater.CheckUpdateCore(ECoreType.v2fly, preRelease: false);
Process multiple core types sequentially:
foreach (var core in new[] { ECoreType.v2fly, ECoreType.mihomo, ECoreType.sing_box })
{
await updater.CheckUpdateCore(core, preRelease: false);
}
Integrate with UI progress indicators:
Func<bool, string, Task> uiProgress = async (notify, msg) =>
{
if (notify)
progressBar.Value = 100; // download finished
else
statusLabel.Content = msg; // status text updates
};
var updater = new UpdateService(Config.Instance, uiProgress);
await updater.CheckUpdateCore(ECoreType.Xray, preRelease: true);
Summary
- UpdateService.cs serves as the central coordinator for core updates, implementing the
CheckUpdateCorepublic API that drives the entire workflow. - The service uses DownloadService for HTTP operations, including
TryDownloadStringfor API queries andDownloadFileAsyncfor binary retrieval. - Architecture awareness is built into
GetUrlFromCore, which selects the correct GitHub release asset based on the current OS and CPU architecture. - Version comparison happens in
ParseDownloadUrlby executing the local binary to get its version and comparing against the GitHub tag, skipping downloads when the local core is current. - Callback-driven design allows the UI to receive real-time status updates and the final temporary file path without
UpdateServicehandling extraction or service restarts directly.
Frequently Asked Questions
Where does UpdateService download the core binaries from?
UpdateService queries GitHub Releases for each core type. It uses the GitHub API to fetch tag names for pre-releases or follows the latest redirect for stable builds, then constructs download URLs pointing to the release assets hosted on GitHub.
How does UpdateService determine if an update is actually needed?
The service executes the current local binary with its version argument via GetCoreVersion to obtain the installed version string. It compares this against the remote version tag in ParseDownloadUrl. If the remote version is not greater than the local version, the update is skipped and the UI is notified that the core is already up-to-date.
What happens after the core archive is downloaded?
UpdateService does not handle extraction or installation internally. Instead, it invokes the UpdateFunc callback with notify: true and the temporary file path. The UI layer (typically the main window) receives this path, extracts the archive, replaces the old binaries, and restarts the service if necessary.
Does UpdateService support updating multiple core types simultaneously?
While CheckUpdateCore processes one core type per call, the service instance can be reused. You can loop through multiple ECoreType values (such as v2fly, Xray, and sing-box) and call CheckUpdateCore for each, using the same callback delegate to handle progress for all operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →