Skip to content

feat(client): implement FastStart for early connection and background resolver discovery - #205

Open
taskkillstar wants to merge 13 commits into
masterking32:mainfrom
taskkillstar:feat/fast-start-resolvers
Open

taskkillstar wants to merge 13 commits into
masterking32:mainfrom
taskkillstar:feat/fast-start-resolvers

Conversation

@taskkillstar

Copy link
Copy Markdown

Summary

When configured with large resolver lists (e.g. 50–100+ endpoints), the client previously blocked session initialization and local proxy (SOCKS5/DNS) startup until 100% of all resolvers were synchronously probed for MTU.

This PR introduces FastStart:

  • When \RECHECK_INACTIVE_SERVERS_ENABLED = true\ (default), the initial MTU test completes early as soon as a minimal working set of resolvers (\min(TotalResolvers, max(1, RX_TX_WORKERS))) is validated.
  • The client connects and opens local proxy listeners immediately (~1–2s startup time).
  • The remaining unscanned resolvers remain in the pool as \inactive, where the existing background
    unResolverHealthLoop\ discovers and reactivates them asynchronously without blocking user traffic.
  • When \RECHECK_INACTIVE_SERVERS_ENABLED = false, the legacy behavior is preserved (full 100% upfront scan).

Key Changes

  • **\internal/client/mtu.go**: Added early-exit condition to \RunInitialMTUTests\ bounded by \ argetValid, capped worker count during fast start, and added completion logs.
  • **\internal/client/fast_start_test.go**: Added comprehensive unit test suite (\TestRunInitialMTUTests_FastStartExitsEarly, \TestRunInitialMTUTests_FullScanWhenRecheckDisabled, \TestRunInitialMTUTests_FallbackWhenFewerResolversWork).
  • **\client_config.toml.simple\ & \README.MD**: Documented FastStart behavior under \RECHECK_INACTIVE_SERVERS_ENABLED.
  • Exported helper methods in \internal/config\ and \internal/udpserver\ (\DefaultClientConfig, \DefaultServerConfig, \Server.HandlePacket).

Verification

  • \go test -v ./internal/client -run TestRunInitialMTUTests\ -> PASS
  • \go test ./...\ -> PASS across all packages
  • \go build ./cmd/client && go build ./cmd/server\ -> PASS (clean build)

@taskkillstar

taskkillstar commented Aug 16, 2026 •

Copy link
Copy Markdown
Author

Minimizes startup time (no need to scan the entire resolvers list), allows to have several hundreds of resolvers in the list without sacrificing connection time.

Requested by FR #179

…speed qualification

- Add pipelined micro-burst speed prober to detect rate-limiting and burst packet loss
- Add candidate ranking score and top-N active pool selection (MAX_ACTIVE_RESOLVERS)
- Add initial balancer stat seeding (SeedBurstStats) and set Loss-Then-Latency (6) as default strategy
- Add micro-burst qualification on background inactive resolver reactivation
- Update client config, sample configs, and all 6 localized READMEs with full documentation
… resolvers for fast warm-start

- Preserved natural input order in LoadClientResolvers without forced sorting
- Added managed header block in client_resolvers.txt to persist top-performing resolvers across runs
- Added AUTO_SAVE_RANKED_RESOLVERS configuration option (default: true)
- Added Balancer.GetRankedEndpoints and Client.SaveRankedResolversToFile
- Auto-saves upon initial MTU test completion, pool optimization swaps, and graceful shutdown
- Added unit tests for order preservation, atomic file update, and endpoint ranking
- Synchronized documentation, CLI parameters, and samples across all README files
@salehMomtaz

Copy link
Copy Markdown

@masterking32 these precious times are passing by and the complete internet blackout resistance projects were not developed since filternet came back. i hope you do not abandon this project.

@salehMomtaz

Copy link
Copy Markdown

@Mygod @masterking32 attention needed

@taskkillstar

Copy link
Copy Markdown
Author

@salehMomtaz
You can try my fork which already has this feature and more. Read the full description at the top of Readme.md and download the client for your platform from Releases page (https://github.com/taskkillstar/MasterDnsVPN/releases/tag/fork-v1.0.0)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Resolver qualification, concurrency, persistence, and configuration-contract defects can activate rejected resolvers or produce incorrect rankings.

Review effort: Balanced
Findings: 3 High severity · 7 Medium severity · 7 Low severity

Open (17)
What changed in this PR

Introduces FastStart resolver discovery, micro-burst qualification, ranked resolver persistence, and live runtime statistics.

Changes:

  • Starts after validating a minimal resolver set and rechecks others asynchronously.
  • Adds resolver scoring, active-pool limits, burst testing, and ranked persistence.
  • Expands tests, configuration, and multilingual documentation.
File Description
.gitignore Adds generated/runtime exclusions.
README.MD Documents new CLI and resolver features.
README_ZH.MD Updates Chinese documentation.
README_RU.MD Updates Russian documentation.
README_IT.MD Updates Italian documentation.
README_FA.MD Updates Persian documentation.
README_ES.MD Updates Spanish documentation.
client_config.toml.simple Adds burst, ranking, and stats settings.
client_resolvers.simple Documents managed resolver ranking.
internal/​config/​client.go Adds and validates client settings.
internal/​config/​client_test.go Tests new configuration fields.
internal/​config/​client_resolvers.go Preserves order and writes ranked blocks.
internal/​config/​client_resolvers_test.go Tests ordering and persistence.
internal/​config/​server.go Exports default server configuration.
internal/​udpserver/​server.go Exports packet handling for tests.
internal/​client/​async_runtime.go Persists rankings during shutdown.
internal/​client/​balancer.go Adds pool limits, scoring, and optimization.
internal/​client/​balancer_test.go Tests pool selection and ranking.
internal/​client/​client.go Starts stats monitoring and configures limits.
internal/​client/​client_utils.go Saves rankings and improves banner output.
internal/​client/​fast_start_test.go Tests FastStart behavior.
internal/​client/​micro_burst.go Implements burst qualification.
internal/​client/​micro_burst_test.go Tests burst probing and selection.
internal/​client/​mtu.go Implements early MTU-test completion.
internal/​client/​mtu_logging.go Adds qualification and reactivation logs.
internal/​client/​runtime_stats.go Implements runtime monitoring.
internal/​client/​runtime_stats_test.go Tests runtime statistics and persistence.
internal/​client/​score.go Adds resolver scoring utilities.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/client/balancer.go
Comment thread internal/client/micro_burst.go Outdated
Comment thread internal/config/client_resolvers.go
Comment thread internal/client/client.go Outdated
Comment thread internal/client/micro_burst.go Outdated
Comment thread README_FA.MD
| `-version` | نمایش نسخه و خروج |
| پارامتر | نام مستعار | هدف | توضیح |
| :--- | :--- | :--- | :--- |
| `-config` | `-c` | هر دو | مسیر فایل تنظیمات (پیش‌فرض: `client_config.toml` / `server_config.toml`) |
Comment thread README_IT.MD
| `-version` | Stampa la versione ed esce |
| Parametro | Alias | Destinazione | Descrizione |
| :--- | :--- | :--- | :--- |
| `-config` | `-c` | Entrambi | Percorso del file di configurazione (predefinito: `client_config.toml` / `server_config.toml`) |
Comment thread README_IT.MD Outdated
| `RESOLVER_BALANCING_STRATEGY` | `6` | `0..8` | Sceglie come vengono selezionati i resolver.<br>`0/2` = Round Robin, `1` = Random, `3` = Least Loss, `4` = Lowest Latency, `5` = Hybrid Score, `6` = Loss Then Latency (Predefinito), `7` = Least Loss Top Random, `8` = Least Loss Top Round Robin.<br>La modalità ibrida usa un punteggio combinato ponderato. La modalità loss-then-latency seleziona prima una rosa in base alla perdita, poi predilige la latenza inferiore all'interno di quella fascia e ruota tra i migliori candidati quasi equivalenti. La modalità top-random sceglie casualmente tra la migliore fascia di perdita affinché il carico non si concentri su un unico resolver. La modalità top-round-robin scorre la stessa migliore fascia di perdita con una rotazione deterministica. |
| `PACKET_DUPLICATION_COUNT` | `2` | limitato all'intervallo valido nel codice | Conteggio normale di duplicazione dei pacchetti in uscita.<br>Valori più alti aumentano il costo di traffico ma migliorano la sopravvivenza su collegamenti deboli. |
| `SETUP_PACKET_DUPLICATION_COUNT` | `2` | limitato all'intervallo valido nel codice | Simile a `PACKET_DUPLICATION_COUNT`, ma usato per i pacchetti sensibili al setup come la creazione degli stream e altri eventi di controllo critici. |
| `SETUP_PACKET_DUPLICATION_COUNT` | `2` | limitato all'intervallo valido nel codice | Simile a `PACKET_DUPLICATION_COUNT`, mas usato per i pacchetti sensibili al setup come la creazione degli stream e altri eventi di controllo critici. |
Comment thread README_RU.MD
| `-version` | Вывод версии |
| Параметр | Алиас | Для кого | Описание |
| :--- | :--- | :--- | :--- |
| `-config` | `-c` | Оба | Путь к файлу конфигурации (по умолчанию: `client_config.toml` / `server_config.toml`) |
Comment thread README_ZH.MD
| `-version` | 打印版本并退出 |
| 参数 | 别名 | 目标 | 说明 |
| :--- | :--- | :--- | :--- |
| `-config` | `-c` | 双端 | 配置文件路径(默认:`client_config.toml` / `server_config.toml`) |

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Startup can overlook usable resolvers, and pool optimization can reactivate rejected or MTU-incompatible candidates.

10 open issues
4 previously missed issues

In code that hasn't changed since last review

Medium severity Apply resolver capacity limits after MTU burst qualification

internal/​client/​balancer.go:1379

This cap also applies during ApplyMTUProbeResult, before burst qualification. RunInitialMTUTests then qualifies only ActiveConnections(), excluding MTU-passing candidates placed on standby here. With MAX_ACTIVE_RESOLVERS=1 and FastStart disabled, a low-latency but rate-limited resolver can exclude a usable alternative, fail the burst test, and prevent startup despite a full MTU scan. Keep all MTU-passing candidates eligible for qualification, and apply the capacity limit after burst ranking.

Medium severity Limit test parallelism to make cancellation assertions deterministic

internal/​client/​fast_start_test.go:90

The default MTUTestParallelism=16 allows all ten mock resolvers to run at once. All ten can commit successful results before cancellation is observed, making the later activeCount < 10 assertion fail under valid scheduling. Set parallelism to two so reaching the target necessarily leaves some endpoints untested.

Medium severity Timestamp MTU responses while the packet train is sent

internal/​client/​micro_burst.go:184

Responses are read only after the entire paced send loop finishes, so this timestamp includes time already-arrived packets spent queued locally. With 32 packets spaced 2 ms apart, an immediate reply to the first query is measured roughly 62 ms late. These inflated round-trip times seed the balancer and affect ranking and promotion. Receive and timestamp responses while sending the train, synchronizing access to the per-query timing state.

Medium severity Use monotonic traffic totals for periodic report gating

internal/​client/​runtime_stats.go:247

calculateTotalSentPackets sums adaptive scoring counters, not monotonic traffic totals: connectionStats.applyHalfLife halves them above 1,000 observations, and health rechecks can reseed them. After a decrease, this comparison suppresses periodic reports until the previous high-water mark is exceeded, potentially indefinitely despite ongoing traffic. Use a monotonic traffic counter or an interval activity flag for this gate instead of the decaying statistics.

10 resolved since last review

Review effort: Balanced

Comment on lines +1456 to +1460
conn := &b.connections[inactIdx]
if conn.UploadMTUBytes <= 0 || conn.DownloadMTUBytes <= 0 {
continue
}
score := b.calculateConnectionScoreLocked(inactIdx)
Comment thread internal/client/mtu.go
Comment on lines +402 to +403
if fastStart && counters.uniqueValidCount() >= int32(targetValidResolvers) {
cancelScan()
Comment thread internal/client/mtu.go
Comment on lines +443 to +448
qualifiedConns, _ := c.runMicroBurstQualification(ctx, validConns)
if len(qualifiedConns) == 0 {
if c.log != nil {
c.log.Errorf("<red>No valid connections remaining after micro-burst qualification!</red>")
}
return ErrNoValidConnections
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants