Skip to content

Add advanced Hysteria2 client options#35

Merged
hawkff merged 1 commit into
mainfrom
feat/hy2-quic-advanced-options
Jun 19, 2026
Merged

Add advanced Hysteria2 client options#35
hawkff merged 1 commit into
mainfrom
feat/hy2-quic-advanced-options

Conversation

@hawkff

@hawkff hawkff commented Jun 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • add Hysteria2 UI/model/persistence for advanced QUIC settings: stream/connection windows, idle timeout, keepalive, and path MTU discovery toggle
  • add Hysteria2 random port-hop interval fields while keeping the existing fixed hop interval setting
  • import/export the new fields in HY2 links using Hysteria-compatible query names
  • route HY2 profiles with unsupported advanced core fields through the bundled Hysteria2 sidecar, while keeping default HY2/Gecko on sing-box

Validation

  • git diff --check
  • ./gradlew :app:compileOssDebugKotlin
  • ./gradlew :app:dexBuilderOssDebug + clean generated AppleDouble files + ./gradlew :app:assembleOssDebug

Note: builds on this external volume can generate macOS AppleDouble ._* files in intermediate outputs; I used cleanfork --path . between build phases to keep AAPT/D8 inputs clean.

Greptile Summary

This PR extends the Hysteria2 profile model with eight new advanced QUIC fields (stream/connection receive windows, idle timeout, keepalive period, path MTU discovery toggle, and random hop-interval min/max), wires them through the UI, DataStore, serialization (version 9), and URI import/export, and routes HY2 profiles that use any of those fields through the bundled Hysteria2 sidecar binary instead of the sing-box core.

  • Model & persistence: HysteriaBean gains 8 new Integer fields with a versioned deserialize block (v9); DataStore uses stringToIntIfExists so null correctly means "use Hysteria default" rather than an explicit zero.
  • Sidecar routing: hasAdvancedHysteria2Options() returns true when any advanced field is set (hop-interval check is correctly gated on isMultiPort), flipping canUseSingBox() to false and directing those profiles to buildHysteria2SidecarConfig, which emits the appropriate Hysteria2 JSON with a quic section and, for multi-port servers, a transport/udp section with the hop intervals.
  • URI round-trip: parseDurationSeconds now handles ms, s, m, and h suffixes (improving on the previous \"s\"-only stripping); queryInt/queryBool/querySeconds helpers accept camelCase, snake_case, and kebab-case variants of each parameter name for broad interoperability.

Confidence Score: 5/5

Safe to merge; the new sidecar routing correctly falls back to the original sing-box path for all unmodified HY2 profiles.

The serialization version bump (8→9) is correct and backward-compatible, the sidecar routing predicate guards hop-interval checks on isMultiPort as expected, and the parseDurationSeconds helper handles all common duration suffixes safely. The only nit is that hopInterval can be emitted for single-port URIs, which is harmless but inconsistent with how the sidecar config builder treats that field.

HysteriaFmt.kt — the toUri() hop-interval emission path is the only place worth a second look.

Important Files Changed

Filename Overview
app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt Core logic for parsing/emitting HY2 URIs and building the sidecar JSON config; adds parseDurationSeconds for multi-unit duration parsing, extended toUri() for new advanced fields, hasAdvancedHysteria2Options() routing predicate, and buildHysteria2SidecarConfig extension with transport and QUIC sections. One minor inconsistency: hopInterval is emitted in toUri() without a multi-port guard.
app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaBean.java Adds 8 new Integer fields for HY2 advanced QUIC options; bumps serialization version to 9 with correct initializeDefaultValues() null-guards and versioned deserialize() block.
app/src/main/java/io/nekohasekai/sagernet/bg/proto/BoxInstance.kt Splits the HysteriaBean sidecar path to dispatch HY1 to hysteria-plugin and HY2 to hysteria2-plugin, using the new buildHysteria2SidecarConfig builder; command-line argument order for hysteria2 is correct (binary client --config --log-level).
app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt Adds 8 nullable Int? DataStore properties (stringToIntIfExists) for the new HY2 fields; correctly uses nullable delegates to distinguish "not set" from zero.
app/src/main/java/io/nekohasekai/sagernet/ui/profile/HysteriaSettingsActivity.kt Adds serialize/deserialize pairs for the 8 new fields, constructs the hy2Advanced preference list for per-version show/hide, and attaches Number keyboard to each new EditTextPreference; correctly restores hy1DisableMtuDiscovery visibility for HY2.
app/src/main/java/io/nekohasekai/sagernet/Constants.kt Adds 8 new Key constants for HY2 advanced QUIC fields; constant names are consistent with existing naming conventions.
app/src/main/res/xml/hysteria_preferences.xml Adds 8 new EditTextPreference entries for the HY2 advanced fields; keys match Constants.kt; no defaultValue attributes needed since zero/null means "use Hysteria default".
app/src/main/res/values/strings.xml Adds 8 display strings for the new HY2 preference fields; all correctly reference seconds for timeout/period units.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[HysteriaBean profile] --> B{protocolVersion == 2?}
    B -- No --> C[HY1 path: canUseSingBox returns false for non-UDP]
    B -- Yes --> D{hasAdvancedHysteria2Options?}
    D -- No --> E[canUseSingBox = true / buildSingBoxOutboundHysteriaBean]
    D -- Yes --> F[canUseSingBox = false / buildHysteria2SidecarConfig]
    F --> G{isMultiPort?}
    G -- Yes --> H[Add transport section with hop intervals]
    G -- No --> I[No transport section]
    H --> J[Add quic section: windows / timeout / keepalive / MTU]
    I --> J
    J --> K[hysteria2-plugin sidecar process]
    E --> L[sing-box hysteria2 outbound]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[HysteriaBean profile] --> B{protocolVersion == 2?}
    B -- No --> C[HY1 path: canUseSingBox returns false for non-UDP]
    B -- Yes --> D{hasAdvancedHysteria2Options?}
    D -- No --> E[canUseSingBox = true / buildSingBoxOutboundHysteriaBean]
    D -- Yes --> F[canUseSingBox = false / buildHysteria2SidecarConfig]
    F --> G{isMultiPort?}
    G -- Yes --> H[Add transport section with hop intervals]
    G -- No --> I[No transport section]
    H --> J[Add quic section: windows / timeout / keepalive / MTU]
    I --> J
    J --> K[hysteria2-plugin sidecar process]
    E --> L[sing-box hysteria2 outbound]
Loading

Reviews (2): Last reviewed commit: "Add advanced Hysteria2 client options" | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Eight advanced HY2 QUIC tuning parameters (stream/connection receive windows, max idle timeout, keep-alive period, hop interval min/max) are added to HysteriaBean (schema version bumped to 9), wired through hy2:// URL parsing and serialization, emitted into sidecar JSON configuration, used to route HY2 with advanced options through the hysteria2-plugin sidecar instead of sing-box, and exposed in the settings UI.

Changes

HY2 Advanced QUIC Options

Layer / File(s) Summary
HysteriaBean data model and serialization (v8→v9)
app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaBean.java, app/src/main/java/io/nekohasekai/sagernet/Constants.kt, app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt
Declares eight new public Integer advanced QUIC fields on HysteriaBean, defaults them to 0, bumps serialization from version 8 to 9, and extends serialize()/deserialize() to handle the new fields. Matching key constants and DataStore properties are added.
HY2 URL parsing, serialization, and canUseSingBox routing
app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt
parseHysteria2 reads the eight new fields from hy2:// query parameters via new private helpers (queryInt, queryBool, querySeconds). toUri() emits them back. hasAdvancedHysteria2Options() is introduced and canUseSingBox() returns false for HY2 when any advanced option is set. getFirstPort parsing is tightened.
Protocol-version-aware sidecar init, launch, and JSON generation
app/src/main/java/io/nekohasekai/sagernet/bg/proto/BoxInstance.kt, app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt
BoxInstance.init() and launch() branch on protocolVersion to select hysteria2-plugin vs hysteria-plugin and adjust CLI arguments. buildHysteria2SidecarConfig JSON is extended with a transportudp section for hop intervals and a quic section for the advanced window/timeout/keepalive fields.
Settings UI wiring and preferences XML
app/src/main/java/io/nekohasekai/sagernet/ui/profile/HysteriaSettingsActivity.kt, app/src/main/res/xml/hysteria_preferences.xml, app/src/main/res/values/strings.xml
HysteriaSettingsActivity reads/writes the eight new DataStore fields in init()/serialize(). A hy2Advanced preference group of 8 EditTextPreferences is defined with visibility toggled by updateVersion(). Eight new EditTextPreference XML items and eight string labels are added.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • hawkff/NekoBoxForAndroid#17: Introduced the hysteria2-plugin sidecar path and buildHysteria2SidecarConfig that this PR directly extends with advanced QUIC options.
  • hawkff/NekoBoxForAndroid#26: Modified the same canUseSingBox() decision logic and BoxInstance HY2 sidecar branching that this PR further adjusts.

Poem

🐇 Hop along, little packets, through windows so wide,
With quic sections blooming and new fields inside!
Stream windows and timeouts, keep-alive in tow,
The hy2 sidecar config puts on quite a show.
Version nine is here now — the bean has grown tall,
This rabbit tuned QUIC, and she tuned it for all! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add advanced Hysteria2 client options' directly and accurately summarizes the main change of introducing advanced QUIC configuration settings for Hysteria2.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is directly related to the changeset, clearly documenting the addition of Hysteria2 advanced QUIC settings, UI/model/persistence changes, import/export functionality, and sidecar routing logic.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands and usage tips.

@hawkff hawkff force-pushed the feat/hy2-quic-advanced-options branch from 5d1c476 to ff91fdc Compare June 19, 2026 19:02
@hawkff hawkff merged commit 3228a18 into main Jun 19, 2026
5 checks passed
@hawkff hawkff deleted the feat/hy2-quic-advanced-options branch June 19, 2026 19:13
hawkff added a commit that referenced this pull request Jun 19, 2026
…ions"

This reverts commit 3228a18, reversing
changes made to 8dc2b50.
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.

1 participant