@@ -375,10 +375,12 @@ fun getFirstPort(portStr: String): Int {
375375}
376376
377377fun HysteriaBean.canUseSingBox (): Boolean {
378- if (protocol != HysteriaBean .PROTOCOL_UDP ) return false
379- // Gecko obfs is now supported natively by this fork's sing-box core (via the
380- // hawkff/sing-quic gecko backport), so it no longer needs the sidecar.
381- return true
378+ // Hysteria2 always uses the native sing-box outbound; the faketcp / wechat-video
379+ // transports are a Hysteria1-only concept, and gecko obfs is handled natively by
380+ // this fork's core (via the hawkff/sing-quic gecko backport).
381+ if (protocolVersion == 2 ) return true
382+ // Hysteria1 falls back to the external plugin for the non-UDP transports.
383+ return protocol == HysteriaBean .PROTOCOL_UDP
382384}
383385
384386fun buildSingBoxOutboundHysteriaBean (bean : HysteriaBean ): SingBoxOptions .SingBoxOption {
@@ -440,9 +442,9 @@ fun buildSingBoxOutboundHysteriaBean(bean: HysteriaBean): SingBoxOptions.SingBox
440442 HysteriaBean .OBFS_GECKO -> {
441443 type = " gecko"
442444 password = bean.obfuscation
443- // Clamp + order to match the sidecar builder's bounds
444- // (1..2048, min <= max); an inverted/ out-of-range pair
445- // would otherwise be rejected by the core at connect time.
445+ // Clamp and order the bounds (1..2048, min <= max);
446+ // an inverted or out-of-range pair would otherwise be
447+ // rejected by the core at connect time.
446448 val min = bean.geckoMinPacketSize?.takeIf { it > 0 }?.coerceIn(1 , 2048 )
447449 val max = bean.geckoMaxPacketSize?.takeIf { it > 0 }?.coerceIn(min ? : 1 , 2048 )
448450 if (min != null ) min_packet_size = min
@@ -491,101 +493,3 @@ fun hopPortsToSingboxList(s: String): List<String> {
491493 }
492494 }
493495}
494-
495- /* *
496- * Builds a config for the bundled official apernet/hysteria client binary (sidecar).
497- *
498- * NOTE: Hysteria2 (including Gecko obfs) now runs natively in the sing-box core, so this
499- * sidecar path is no longer used for Gecko. This builder is retained for the bundled
500- * hysteria2 binary infrastructure and potential fallback use.
501- *
502- * Emitted as JSON (hysteria uses viper, which detects format by the .json extension).
503- * The client's upstream QUIC sockets are protected from the VPN via
504- * quic.sockopts.fdControlUnixSocket, pointing at libcore's protect_server socket
505- * ("protect_path" in the process working dir). It exposes a loopback-only SOCKS5 listener
506- * that the generated sing-box "socks" outbound dials (no auth, matching the other sidecars).
507- *
508- * @param port local SOCKS5 port for the sidecar to listen on (== sing-box outbound port).
509- * @param protectPath absolute path to libcore's protect unix socket.
510- */
511- fun HysteriaBean.buildHysteria2SidecarConfig (port : Int , protectPath : String ): String {
512- if (protocolVersion != 2 ) {
513- throw Exception (" error version: $protocolVersion " )
514- }
515- var realSni = sni
516- if (realSni.isBlank() && ! serverAddress.isIpAddress()) {
517- realSni = serverAddress
518- }
519- return JSONObject ().apply {
520- put(" server" , " $serverAddress :$serverPorts " )
521- if (authPayload.isNotBlank()) put(" auth" , authPayload)
522- put(
523- " tls" ,
524- JSONObject ().apply {
525- if (realSni.isNotBlank()) put(" sni" , realSni)
526- put(" insecure" , allowInsecure || DataStore .globalAllowInsecure)
527- if (caText.isNotBlank()) put(" ca" , caText)
528- },
529- )
530- if (hysteria2ObfsType == HysteriaBean .OBFS_GECKO && obfuscation.isNotBlank()) {
531- // Clamp to hysteria's accepted bounds: 1 <= min <= max <= 2048.
532- val min = geckoMinPacketSize.coerceIn(1 , 2048 )
533- val max = geckoMaxPacketSize.coerceIn(min, 2048 )
534- put(
535- " obfs" ,
536- JSONObject ().apply {
537- put(" type" , " gecko" )
538- put(
539- " gecko" ,
540- JSONObject ().apply {
541- put(" password" , obfuscation)
542- put(" minPacketSize" , min)
543- put(" maxPacketSize" , max)
544- },
545- )
546- },
547- )
548- } else if (hysteria2ObfsType == HysteriaBean .OBFS_SALAMANDER && obfuscation.isNotBlank()) {
549- put(
550- " obfs" ,
551- JSONObject ().apply {
552- put(" type" , " salamander" )
553- put(
554- " salamander" ,
555- JSONObject ().apply {
556- put(" password" , obfuscation)
557- },
558- )
559- },
560- )
561- }
562- if (uploadMbps > 0 || downloadMbps > 0 ) {
563- put(
564- " bandwidth" ,
565- JSONObject ().apply {
566- if (uploadMbps > 0 ) put(" up" , " $uploadMbps mbps" )
567- if (downloadMbps > 0 ) put(" down" , " $downloadMbps mbps" )
568- },
569- )
570- }
571- put(
572- " quic" ,
573- JSONObject ().apply {
574- put(
575- " sockopts" ,
576- JSONObject ().apply {
577- put(" fdControlUnixSocket" , protectPath)
578- },
579- )
580- },
581- )
582- put(
583- " socks5" ,
584- JSONObject ().apply {
585- put(" listen" , " $LOCALHOST :$port " )
586- put(" disableUDP" , false )
587- },
588- )
589- put(" lazy" , true )
590- }.toStringPretty()
591- }
0 commit comments