Introduce a synchronized ConfigState and make ConfigTextManager static. Update configuration access across desktop and WebAPI, and add an AddServer overload using the current configuration.
Move configuration queries to ConfigDbQuery and profile migrations to ConfigDbManager. Update desktop, Web API, and test callers to use the new locations.
Use ConfigTextManager instance methods for window sizes and grid heights in both desktop clients. Standardize formatting and remove redundant imports and casts across the Web API and tests.
Move file-backed settings to ConfigTextManager and database operations to ConfigDbManager. Update desktop, Web API, and test references, and add Web API development launch settings.
GenDns applies the DNS Strategy4Proxy setting to the generated proxy
outbound, but ApplyCustomOutboundReplace replaces the whole JSON object
and dropped targetStrategy when the custom outbound did not define one.
Keep the generated value unless the custom JSON sets it explicitly.
Add regression tests for the inherited and explicitly configured cases.
ProfileExManager kept its entries in a ConcurrentBag and found them with
FirstOrDefault, which copies and scans the whole bag on every lookup.
Recording test results, SaveTo, MoveServer and subscription imports
were quadratic in the number of servers.
Store the entries in a ConcurrentDictionary keyed by IndexId and track
the highest sort in SetSort so GetMaxSort no longer scans.
Saving the settings runs AutoStartupHandler.UpdateTask, which on macOS
first ran "launchctl unload -w" on the v2rayN LaunchAgent. When v2rayN
was started by that agent at login, launchd terminates the job processes
on unload, so v2rayN received SIGTERM and exited before it could delete
and re-create the plist. The "-w" also left the job disabled, so the
next login did not start v2rayN although auto-start was still enabled.
The agent only has RunAtLoad, so unloading it has no effect other than
killing its processes. Removing the plist is enough to stop the next
start; enabling still writes the plist and runs "launchctl load -w".
Fixes#10522
DomainRemoteDNSAddress gains https://1.1.1.1/dns-query and
https://8.8.8.8/dns-query: on networks that transparently rewrite port 53,
hostname-based DoH endpoints resolve to the block page and fail, so the
existing presets are unusable there while the IP-literal forms work.
InboundTags gains dns-module so the routing rule editor can express
'route DNS out direct', a tag xray already supports and v2rayN itself
emits in the generated config.
GenMinimizedDns rebuilt route.default_domain_resolver with only a server, so speedtest configs dropped the user's Strategy4ProxyDial preference while normal configs applied it. Reuse the same resolver strategy selection for both normal and minimized configs, and add a regression test comparing both configs for UseIPv6v4.
* feat(core): support AUTO detection and manual selection for BindInterface (#10519)
- Implements the 3-state design agreed in #10519:
1. Empty: do not bind interface, preserve existing behavior.
2. AUTO: automatically detect default active physical network interface and bind to it.
3. Specific interface: prioritize user-selected network interface.
- Centralizes interface resolution in NetworkUtils.GetRealBindInterfaceName().
- Supports AUTO in CoreConfigContextBuilder, Singbox, and V2ray template services.
- Adds comprehensive unit tests covering AUTO detection, context validation, and config generation.
* refactor: optimize AUTO bindInterface resolution and add mock-based tests
- Resolve AUTO interface once in CoreConfigContextBuilder and store in CoreConfigContext.ResolvedBindInterface as single-source-of-truth
- Downstream sing-box and Xray outbound/TUN services consume ResolvedBindInterface directly
- Unify TrimEx and case-insensitive check via NetworkUtils.IsAuto to tolerate user input whitespace
- Log and issue validator warning when AUTO fails to resolve any physical adapter
- Extract pure SelectDefaultInterface function with NetworkInterfaceCandidate for deterministic, mock-based unit testing
- Add comprehensive unit tests covering Ethernet vs Wi-Fi preference, no-gateway fallback, and virtual adapter filtering
* refactor(network): filter non-IP NDIS interfaces and simplify AUTO bindInterface resolution
* fix(ui,network): align BindInterface ComboBox width and refine physical NIC matching
* Update CoreConfigContextBuilder.cs
---------
Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
Removing "?ed=2048" from a WebSocket path also removed the '?', so
"/ws?ed=2048&key=value" was sent to sing-box as "/ws&key=value".
Match "ed" without the separator in front of it and trim the
leftover '&' or '?' instead.
NaiveFmt.ToUri percent-encodes the username and password, so a
password-only profile with the password a:b is exported as
naive+https://a%3Ab@host. Resolve decoded the user info before
looking for the ':' separator and imported it as username "a",
password "b". Split the raw user info first and decode each part.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Use generated JSON type metadata and propagate mapped SQLite types through CRUD and transactional bulk operations. Cover serialization options, affected counts, rollback and native test compatibility without changing UI models or persistence entities.
For a SIP002 link whose user info is "method:password" rather than
base64 (the 2022-blake3 form), ResolveSip002 unescapes the whole user
info and then unescapes the password a second time. A password that
still holds a valid percent sequence after the first pass decays:
p%41ss is written as p%2541ss and imported as pAss.
Same double-decoding as #10027 fixed for query values.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>