diff --git a/.github/update.log b/.github/update.log index 6e7fccbb10..1d1cdfa66e 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1102,3 +1102,4 @@ Update On Sat Aug 23 20:35:18 CEST 2025 Update On Sun Aug 24 20:36:09 CEST 2025 Update On Mon Aug 25 20:39:10 CEST 2025 Update On Tue Aug 26 20:39:16 CEST 2025 +Update On Wed Aug 27 20:38:26 CEST 2025 diff --git a/clash-meta-android/build.gradle.kts b/clash-meta-android/build.gradle.kts index e40497e125..36c40780b0 100644 --- a/clash-meta-android/build.gradle.kts +++ b/clash-meta-android/build.gradle.kts @@ -46,8 +46,8 @@ subprojects { minSdk = 21 targetSdk = 35 - versionName = "2.11.15" - versionCode = 211015 + versionName = "2.11.16" + versionCode = 211016 resValue("string", "release_name", "v$versionName") resValue("integer", "release_code", "$versionCode") diff --git a/clash-meta-android/core/src/foss/golang/clash/.github/workflows/build.yml b/clash-meta-android/core/src/foss/golang/clash/.github/workflows/build.yml index 9ddf316014..48858ef500 100644 --- a/clash-meta-android/core/src/foss/golang/clash/.github/workflows/build.yml +++ b/clash-meta-android/core/src/foss/golang/clash/.github/workflows/build.yml @@ -80,6 +80,13 @@ jobs: - { goos: android, goarch: arm, ndk: armv7a-linux-androideabi34, output: armv7 } - { goos: android, goarch: arm64, ndk: aarch64-linux-android34, output: arm64-v8 } + # Go 1.24 with special patch can work on Windows 7 + # https://github.com/MetaCubeX/go/commits/release-branch.go1.24/ + - { goos: windows, goarch: '386', output: '386-go124', goversion: '1.24' } + - { goos: windows, goarch: amd64, goamd64: v1, output: amd64-v1-go124, goversion: '1.24' } + - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2-go124, goversion: '1.24' } + - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3-go124, goversion: '1.24' } + # Go 1.23 with special patch can work on Windows 7 # https://github.com/MetaCubeX/go/commits/release-branch.go1.23/ - { goos: windows, goarch: '386', output: '386-go123', goversion: '1.23' } @@ -108,6 +115,12 @@ jobs: - { goos: windows, goarch: amd64, goamd64: v2, output: amd64-v2-go120, goversion: '1.20' } - { goos: windows, goarch: amd64, goamd64: v3, output: amd64-v3-go120, goversion: '1.20' } + # Go 1.24 is the last release that will run on macOS 11 Big Sur. Go 1.25 will require macOS 12 Monterey or later. + - { goos: darwin, goarch: arm64, output: arm64-go124, goversion: '1.24' } + - { goos: darwin, goarch: amd64, goamd64: v1, output: amd64-v1-go124, goversion: '1.24' } + - { goos: darwin, goarch: amd64, goamd64: v2, output: amd64-v2-go124, goversion: '1.24' } + - { goos: darwin, goarch: amd64, goamd64: v3, output: amd64-v3-go124, goversion: '1.24' } + # Go 1.22 is the last release that will run on macOS 10.15 Catalina. Go 1.23 will require macOS 11 Big Sur or later. - { goos: darwin, goarch: arm64, output: arm64-go122, goversion: '1.22' } - { goos: darwin, goarch: amd64, goamd64: v1, output: amd64-v1-go122, goversion: '1.22' } @@ -139,7 +152,7 @@ jobs: if: ${{ matrix.jobs.goversion == '' && matrix.jobs.abi != '1' }} uses: actions/setup-go@v5 with: - go-version: '1.24' + go-version: '1.25' - name: Set up Go if: ${{ matrix.jobs.goversion != '' && matrix.jobs.abi != '1' }} @@ -154,6 +167,25 @@ jobs: sudo tar zxf go1.24.0.linux-amd64-abi1.tar.gz -C /usr/local echo "/usr/local/go/bin" >> $GITHUB_PATH + # modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557 + # this patch file only works on golang1.25.x + # that means after golang1.26 release it must be changed + # see: https://github.com/MetaCubeX/go/commits/release-branch.go1.25/ + # revert: + # 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng" + # 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7" + # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround" + # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries" + - name: Revert Golang1.25 commit for Windows7/8 + if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '' }} + run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' + cd $(go env GOROOT) + curl https://github.com/MetaCubeX/go/commit/8cb5472d94c34b88733a81091bd328e70ee565a4.diff | patch --verbose -p 1 + curl https://github.com/MetaCubeX/go/commit/6788c4c6f9fafb56729bad6b660f7ee2272d699f.diff | patch --verbose -p 1 + curl https://github.com/MetaCubeX/go/commit/a5b2168bb836ed9d6601c626f95e56c07923f906.diff | patch --verbose -p 1 + curl https://github.com/MetaCubeX/go/commit/f56f1e23507e646c85243a71bde7b9629b2f970c.diff | patch --verbose -p 1 + # modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557 # this patch file only works on golang1.24.x # that means after golang1.25 release it must be changed @@ -164,8 +196,9 @@ jobs: # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround" # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries" - name: Revert Golang1.24 commit for Windows7/8 - if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '' }} + if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.24' }} run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' cd $(go env GOROOT) curl https://github.com/MetaCubeX/go/commit/2a406dc9f1ea7323d6ca9fccb2fe9ddebb6b1cc8.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/7b1fd7d39c6be0185fbe1d929578ab372ac5c632.diff | patch --verbose -p 1 @@ -184,6 +217,7 @@ jobs: - name: Revert Golang1.23 commit for Windows7/8 if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.23' }} run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' cd $(go env GOROOT) curl https://github.com/MetaCubeX/go/commit/9ac42137ef6730e8b7daca016ece831297a1d75b.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/21290de8a4c91408de7c2b5b68757b1e90af49dd.diff | patch --verbose -p 1 @@ -202,6 +236,7 @@ jobs: - name: Revert Golang1.22 commit for Windows7/8 if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.22' }} run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' cd $(go env GOROOT) curl https://github.com/MetaCubeX/go/commit/9779155f18b6556a034f7bb79fb7fb2aad1e26a9.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/ef0606261340e608017860b423ffae5c1ce78239.diff | patch --verbose -p 1 @@ -212,6 +247,7 @@ jobs: - name: Revert Golang1.21 commit for Windows7/8 if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.21' }} run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' cd $(go env GOROOT) curl https://github.com/golang/go/commit/9e43850a3298a9b8b1162ba0033d4c53f8637571.diff | patch --verbose -R -p 1 diff --git a/clash-meta-android/core/src/foss/golang/clash/.github/workflows/test.yml b/clash-meta-android/core/src/foss/golang/clash/.github/workflows/test.yml index db7ac0373e..ab046bd17f 100644 --- a/clash-meta-android/core/src/foss/golang/clash/.github/workflows/test.yml +++ b/clash-meta-android/core/src/foss/golang/clash/.github/workflows/test.yml @@ -24,6 +24,7 @@ jobs: - 'ubuntu-24.04-arm' # arm64 linux - 'macos-13' # amd64 macos go-version: + - '1.25' - '1.24' - '1.23' - '1.22' @@ -47,6 +48,25 @@ jobs: with: go-version: ${{ matrix.go-version }} + # modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557 + # this patch file only works on golang1.25.x + # that means after golang1.26 release it must be changed + # see: https://github.com/MetaCubeX/go/commits/release-branch.go1.25/ + # revert: + # 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng" + # 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7" + # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround" + # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries" + - name: Revert Golang1.25 commit for Windows7/8 + if: ${{ matrix.jobs.goos == 'windows' && matrix.jobs.goversion == '1.25' }} + run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' + cd $(go env GOROOT) + curl https://github.com/MetaCubeX/go/commit/8cb5472d94c34b88733a81091bd328e70ee565a4.diff | patch --verbose -p 1 + curl https://github.com/MetaCubeX/go/commit/6788c4c6f9fafb56729bad6b660f7ee2272d699f.diff | patch --verbose -p 1 + curl https://github.com/MetaCubeX/go/commit/a5b2168bb836ed9d6601c626f95e56c07923f906.diff | patch --verbose -p 1 + curl https://github.com/MetaCubeX/go/commit/f56f1e23507e646c85243a71bde7b9629b2f970c.diff | patch --verbose -p 1 + # modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557 # this patch file only works on golang1.24.x # that means after golang1.25 release it must be changed @@ -59,6 +79,7 @@ jobs: - name: Revert Golang1.24 commit for Windows7/8 if: ${{ runner.os == 'Windows' && matrix.go-version == '1.24' }} run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' cd $(go env GOROOT) curl https://github.com/MetaCubeX/go/commit/2a406dc9f1ea7323d6ca9fccb2fe9ddebb6b1cc8.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/7b1fd7d39c6be0185fbe1d929578ab372ac5c632.diff | patch --verbose -p 1 @@ -77,6 +98,7 @@ jobs: - name: Revert Golang1.23 commit for Windows7/8 if: ${{ runner.os == 'Windows' && matrix.go-version == '1.23' }} run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' cd $(go env GOROOT) curl https://github.com/MetaCubeX/go/commit/9ac42137ef6730e8b7daca016ece831297a1d75b.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/21290de8a4c91408de7c2b5b68757b1e90af49dd.diff | patch --verbose -p 1 @@ -95,6 +117,7 @@ jobs: - name: Revert Golang1.22 commit for Windows7/8 if: ${{ runner.os == 'Windows' && matrix.go-version == '1.22' }} run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' cd $(go env GOROOT) curl https://github.com/MetaCubeX/go/commit/9779155f18b6556a034f7bb79fb7fb2aad1e26a9.diff | patch --verbose -p 1 curl https://github.com/MetaCubeX/go/commit/ef0606261340e608017860b423ffae5c1ce78239.diff | patch --verbose -p 1 @@ -105,6 +128,7 @@ jobs: - name: Revert Golang1.21 commit for Windows7/8 if: ${{ runner.os == 'Windows' && matrix.go-version == '1.21' }} run: | + alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"' cd $(go env GOROOT) curl https://github.com/golang/go/commit/9e43850a3298a9b8b1162ba0033d4c53f8637571.diff | patch --verbose -R -p 1 diff --git a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/hysteria.go b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/hysteria.go index 966fa745dd..383184595d 100644 --- a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/hysteria.go +++ b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/hysteria.go @@ -172,7 +172,7 @@ func NewHysteria(option HysteriaOption) (*Hysteria, error) { return nil, err } - if len(option.ALPN) > 0 { + if option.ALPN != nil { // structure's Decode will ensure value not nil when input has value even it was set an empty array tlsConfig.NextProtos = option.ALPN } else { tlsConfig.NextProtos = []string{DefaultALPN} diff --git a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/hysteria2.go b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/hysteria2.go index cb844e1f0f..e7b9f0b5b0 100644 --- a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/hysteria2.go +++ b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/hysteria2.go @@ -153,7 +153,7 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) { return nil, err } - if len(option.ALPN) > 0 { + if option.ALPN != nil { // structure's Decode will ensure value not nil when input has value even it was set an empty array tlsConfig.NextProtos = option.ALPN } diff --git a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/mieru.go b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/mieru.go index fca7ede4c8..8ef9cfd758 100644 --- a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/mieru.go +++ b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/mieru.go @@ -28,15 +28,16 @@ type Mieru struct { type MieruOption struct { BasicOption - Name string `proxy:"name"` - Server string `proxy:"server"` - Port int `proxy:"port,omitempty"` - PortRange string `proxy:"port-range,omitempty"` - Transport string `proxy:"transport"` - UDP bool `proxy:"udp,omitempty"` - UserName string `proxy:"username"` - Password string `proxy:"password"` - Multiplexing string `proxy:"multiplexing,omitempty"` + Name string `proxy:"name"` + Server string `proxy:"server"` + Port int `proxy:"port,omitempty"` + PortRange string `proxy:"port-range,omitempty"` + Transport string `proxy:"transport"` + UDP bool `proxy:"udp,omitempty"` + UserName string `proxy:"username"` + Password string `proxy:"password"` + Multiplexing string `proxy:"multiplexing,omitempty"` + HandshakeMode string `proxy:"handshake-mode,omitempty"` } // DialContext implements C.ProxyAdapter @@ -245,6 +246,9 @@ func buildMieruClientConfig(option MieruOption) (*mieruclient.ClientConfig, erro Level: mierupb.MultiplexingLevel(multiplexing).Enum(), } } + if handshakeMode, ok := mierupb.HandshakeMode_value[option.HandshakeMode]; ok { + config.Profile.HandshakeMode = (*mierupb.HandshakeMode)(&handshakeMode) + } return config, nil } @@ -294,6 +298,11 @@ func validateMieruOption(option MieruOption) error { return fmt.Errorf("invalid multiplexing level: %s", option.Multiplexing) } } + if option.HandshakeMode != "" { + if _, ok := mierupb.HandshakeMode_value[option.HandshakeMode]; !ok { + return fmt.Errorf("invalid handshake mode: %s", option.HandshakeMode) + } + } return nil } diff --git a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/trojan.go b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/trojan.go index 9795ed7814..f33ac5d6b5 100644 --- a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/trojan.go +++ b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/trojan.go @@ -95,7 +95,7 @@ func (t *Trojan) StreamConnContext(ctx context.Context, c net.Conn, metadata *C. } alpn := trojan.DefaultWebsocketALPN - if len(t.option.ALPN) != 0 { + if t.option.ALPN != nil { // structure's Decode will ensure value not nil when input has value even it was set an empty array alpn = t.option.ALPN } @@ -119,7 +119,7 @@ func (t *Trojan) StreamConnContext(ctx context.Context, c net.Conn, metadata *C. // default tcp network // handle TLS alpn := trojan.DefaultALPN - if len(t.option.ALPN) != 0 { + if t.option.ALPN != nil { // structure's Decode will ensure value not nil when input has value even it was set an empty array alpn = t.option.ALPN } c, err = vmess.StreamTLSConn(ctx, c, &vmess.TLSConfig{ diff --git a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/vless.go b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/vless.go index 9b5c65f94f..3db99e1feb 100644 --- a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/vless.go +++ b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/vless.go @@ -3,14 +3,10 @@ package outbound import ( "context" "crypto/tls" - "encoding/binary" - "errors" "fmt" - "io" "net" "net/http" "strconv" - "sync" "github.com/metacubex/mihomo/common/convert" N "github.com/metacubex/mihomo/common/net" @@ -23,6 +19,7 @@ import ( C "github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/transport/gun" "github.com/metacubex/mihomo/transport/vless" + "github.com/metacubex/mihomo/transport/vless/encryption" "github.com/metacubex/mihomo/transport/vmess" vmessSing "github.com/metacubex/sing-vmess" @@ -30,16 +27,13 @@ import ( M "github.com/metacubex/sing/common/metadata" ) -const ( - // max packet length - maxLength = 1024 << 3 -) - type Vless struct { *Base client *vless.Client option *VlessOption + encryption *encryption.ClientInstance + // for gun mux gunTLSConfig *tls.Config gunConfig *gun.Config @@ -62,6 +56,7 @@ type VlessOption struct { PacketAddr bool `proxy:"packet-addr,omitempty"` XUDP bool `proxy:"xudp,omitempty"` PacketEncoding string `proxy:"packet-encoding,omitempty"` + Encryption string `proxy:"encryption,omitempty"` Network string `proxy:"network,omitempty"` ECHOpts ECHOptions `proxy:"ech-opts,omitempty"` RealityOpts RealityOptions `proxy:"reality-opts,omitempty"` @@ -173,6 +168,12 @@ func (v *Vless) streamConnContext(ctx context.Context, c net.Conn, metadata *C.M done := N.SetupContextForConn(ctx, c) defer done(&err) } + if v.encryption != nil { + c, err = v.encryption.Handshake(c) + if err != nil { + return + } + } if metadata.NetWork == C.UDP { if v.option.PacketAddr { metadata = &C.Metadata{ @@ -188,9 +189,6 @@ func (v *Vless) streamConnContext(ctx context.Context, c net.Conn, metadata *C.M } } conn, err = v.client.StreamConn(c, parseVlessAddr(metadata, v.option.XUDP)) - if v.option.PacketAddr { - conn = packetaddr.NewBindConn(conn) - } } else { conn, err = v.client.StreamConn(c, parseVlessAddr(metadata, false)) } @@ -352,12 +350,11 @@ func (v *Vless) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metada ), v), nil } else if v.option.PacketAddr { return newPacketConn(N.NewThreadSafePacketConn( - packetaddr.NewConn(&vlessPacketConn{ - Conn: c, rAddr: metadata.UDPAddr(), - }, M.SocksaddrFromNet(metadata.UDPAddr())), + packetaddr.NewConn(v.client.PacketConn(c, metadata.UDPAddr()), + M.SocksaddrFromNet(metadata.UDPAddr())), ), v), nil } - return newPacketConn(N.NewThreadSafePacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}), v), nil + return newPacketConn(N.NewThreadSafePacketConn(v.client.PacketConn(c, metadata.UDPAddr())), v), nil } // SupportUOT implements C.ProxyAdapter @@ -408,98 +405,6 @@ func parseVlessAddr(metadata *C.Metadata, xudp bool) *vless.DstAddr { } } -type vlessPacketConn struct { - net.Conn - rAddr net.Addr - remain int - mux sync.Mutex - cache [2]byte -} - -func (c *vlessPacketConn) writePacket(payload []byte) (int, error) { - binary.BigEndian.PutUint16(c.cache[:], uint16(len(payload))) - - if _, err := c.Conn.Write(c.cache[:]); err != nil { - return 0, err - } - - return c.Conn.Write(payload) -} - -func (c *vlessPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { - total := len(b) - if total == 0 { - return 0, nil - } - - if total <= maxLength { - return c.writePacket(b) - } - - offset := 0 - - for offset < total { - cursor := offset + maxLength - if cursor > total { - cursor = total - } - - n, err := c.writePacket(b[offset:cursor]) - if err != nil { - return offset + n, err - } - - offset = cursor - if offset == total { - break - } - } - - return total, nil -} - -func (c *vlessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) { - c.mux.Lock() - defer c.mux.Unlock() - - if c.remain > 0 { - length := len(b) - if c.remain < length { - length = c.remain - } - - n, err := c.Conn.Read(b[:length]) - if err != nil { - return 0, c.rAddr, err - } - - c.remain -= n - return n, c.rAddr, nil - } - - if _, err := c.Conn.Read(b[:2]); err != nil { - return 0, c.rAddr, err - } - - total := int(binary.BigEndian.Uint16(b[:2])) - if total == 0 { - return 0, c.rAddr, nil - } - - length := len(b) - if length > total { - length = total - } - - if _, err := io.ReadFull(c.Conn, b[:length]); err != nil { - return 0, c.rAddr, errors.New("read packet error") - } - - c.remain = total - length - - return length, c.rAddr, nil -} - func NewVless(option VlessOption) (*Vless, error) { var addons *vless.Addons if option.Network != "ws" && len(option.Flow) >= 16 { @@ -547,6 +452,11 @@ func NewVless(option VlessOption) (*Vless, error) { option: &option, } + v.encryption, err = encryption.NewClient(option.Encryption) + if err != nil { + return nil, err + } + v.realityConfig, err = v.option.RealityOpts.Parse() if err != nil { return nil, err diff --git a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/wireguard.go b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/wireguard.go index 84ba1dbb12..f59033febe 100644 --- a/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/wireguard.go +++ b/clash-meta-android/core/src/foss/golang/clash/adapter/outbound/wireguard.go @@ -87,15 +87,26 @@ type WireGuardPeerOption struct { } type AmneziaWGOption struct { - JC int `proxy:"jc"` - JMin int `proxy:"jmin"` - JMax int `proxy:"jmax"` - S1 int `proxy:"s1"` - S2 int `proxy:"s2"` - H1 uint32 `proxy:"h1"` - H2 uint32 `proxy:"h2"` - H3 uint32 `proxy:"h3"` - H4 uint32 `proxy:"h4"` + JC int `proxy:"jc,omitempty"` + JMin int `proxy:"jmin,omitempty"` + JMax int `proxy:"jmax,omitempty"` + S1 int `proxy:"s1,omitempty"` + S2 int `proxy:"s2,omitempty"` + H1 uint32 `proxy:"h1,omitempty"` + H2 uint32 `proxy:"h2,omitempty"` + H3 uint32 `proxy:"h3,omitempty"` + H4 uint32 `proxy:"h4,omitempty"` + + // AmneziaWG v1.5 + I1 string `proxy:"i1,omitempty"` + I2 string `proxy:"i2,omitempty"` + I3 string `proxy:"i3,omitempty"` + I4 string `proxy:"i4,omitempty"` + I5 string `proxy:"i5,omitempty"` + J1 string `proxy:"j1,omitempty"` + J2 string `proxy:"j2,omitempty"` + J3 string `proxy:"j3,omitempty"` + Itime int64 `proxy:"itime,omitempty"` } type wgSingErrorHandler struct { @@ -386,15 +397,60 @@ func (w *WireGuard) genIpcConf(ctx context.Context, updateOnly bool) (string, er if !updateOnly { ipcConf += "private_key=" + w.option.PrivateKey + "\n" if w.option.AmneziaWGOption != nil { - ipcConf += "jc=" + strconv.Itoa(w.option.AmneziaWGOption.JC) + "\n" - ipcConf += "jmin=" + strconv.Itoa(w.option.AmneziaWGOption.JMin) + "\n" - ipcConf += "jmax=" + strconv.Itoa(w.option.AmneziaWGOption.JMax) + "\n" - ipcConf += "s1=" + strconv.Itoa(w.option.AmneziaWGOption.S1) + "\n" - ipcConf += "s2=" + strconv.Itoa(w.option.AmneziaWGOption.S2) + "\n" - ipcConf += "h1=" + strconv.FormatUint(uint64(w.option.AmneziaWGOption.H1), 10) + "\n" - ipcConf += "h2=" + strconv.FormatUint(uint64(w.option.AmneziaWGOption.H2), 10) + "\n" - ipcConf += "h3=" + strconv.FormatUint(uint64(w.option.AmneziaWGOption.H3), 10) + "\n" - ipcConf += "h4=" + strconv.FormatUint(uint64(w.option.AmneziaWGOption.H4), 10) + "\n" + if w.option.AmneziaWGOption.JC != 0 { + ipcConf += "jc=" + strconv.Itoa(w.option.AmneziaWGOption.JC) + "\n" + } + if w.option.AmneziaWGOption.JMin != 0 { + ipcConf += "jmin=" + strconv.Itoa(w.option.AmneziaWGOption.JMin) + "\n" + } + if w.option.AmneziaWGOption.JMax != 0 { + ipcConf += "jmax=" + strconv.Itoa(w.option.AmneziaWGOption.JMax) + "\n" + } + if w.option.AmneziaWGOption.S1 != 0 { + ipcConf += "s1=" + strconv.Itoa(w.option.AmneziaWGOption.S1) + "\n" + } + if w.option.AmneziaWGOption.S2 != 0 { + ipcConf += "s2=" + strconv.Itoa(w.option.AmneziaWGOption.S2) + "\n" + } + if w.option.AmneziaWGOption.H1 != 0 { + ipcConf += "h1=" + strconv.FormatUint(uint64(w.option.AmneziaWGOption.H1), 10) + "\n" + } + if w.option.AmneziaWGOption.H2 != 0 { + ipcConf += "h2=" + strconv.FormatUint(uint64(w.option.AmneziaWGOption.H2), 10) + "\n" + } + if w.option.AmneziaWGOption.H3 != 0 { + ipcConf += "h3=" + strconv.FormatUint(uint64(w.option.AmneziaWGOption.H3), 10) + "\n" + } + if w.option.AmneziaWGOption.H4 != 0 { + ipcConf += "h4=" + strconv.FormatUint(uint64(w.option.AmneziaWGOption.H4), 10) + "\n" + } + if w.option.AmneziaWGOption.I1 != "" { + ipcConf += "i1=" + w.option.AmneziaWGOption.I1 + "\n" + } + if w.option.AmneziaWGOption.I2 != "" { + ipcConf += "i2=" + w.option.AmneziaWGOption.I2 + "\n" + } + if w.option.AmneziaWGOption.I3 != "" { + ipcConf += "i3=" + w.option.AmneziaWGOption.I3 + "\n" + } + if w.option.AmneziaWGOption.I4 != "" { + ipcConf += "i4=" + w.option.AmneziaWGOption.I4 + "\n" + } + if w.option.AmneziaWGOption.I5 != "" { + ipcConf += "i5=" + w.option.AmneziaWGOption.I5 + "\n" + } + if w.option.AmneziaWGOption.J1 != "" { + ipcConf += "j1=" + w.option.AmneziaWGOption.J1 + "\n" + } + if w.option.AmneziaWGOption.J2 != "" { + ipcConf += "j2=" + w.option.AmneziaWGOption.J2 + "\n" + } + if w.option.AmneziaWGOption.J3 != "" { + ipcConf += "j3=" + w.option.AmneziaWGOption.J3 + "\n" + } + if w.option.AmneziaWGOption.Itime != 0 { + ipcConf += "itime=" + strconv.FormatInt(int64(w.option.AmneziaWGOption.Itime), 10) + "\n" + } } } if len(w.option.Peers) > 0 { diff --git a/clash-meta-android/core/src/foss/golang/clash/common/atomic/value.go b/clash-meta-android/core/src/foss/golang/clash/common/atomic/value.go index e63d231096..6480ee4766 100644 --- a/clash-meta-android/core/src/foss/golang/clash/common/atomic/value.go +++ b/clash-meta-android/core/src/foss/golang/clash/common/atomic/value.go @@ -5,58 +5,50 @@ import ( "sync/atomic" ) -func DefaultValue[T any]() T { - var defaultValue T - return defaultValue -} - type TypedValue[T any] struct { - _ noCopy - value atomic.Value + value atomic.Pointer[T] } -// tValue is a struct with determined type to resolve atomic.Value usages with interface types -// https://github.com/golang/go/issues/22550 -// -// The intention to have an atomic value store for errors. However, running this code panics: -// panic: sync/atomic: store of inconsistently typed value into Value -// This is because atomic.Value requires that the underlying concrete type be the same (which is a reasonable expectation for its implementation). -// When going through the atomic.Value.Store method call, the fact that both these are of the error interface is lost. -type tValue[T any] struct { - value T +func (t *TypedValue[T]) Load() (v T) { + v, _ = t.LoadOk() + return } -func (t *TypedValue[T]) Load() T { - value, _ := t.LoadOk() - return value -} - -func (t *TypedValue[T]) LoadOk() (_ T, ok bool) { +func (t *TypedValue[T]) LoadOk() (v T, ok bool) { value := t.value.Load() if value == nil { - return DefaultValue[T](), false + return } - return value.(tValue[T]).value, true + return *value, true } func (t *TypedValue[T]) Store(value T) { - t.value.Store(tValue[T]{value}) + t.value.Store(&value) } -func (t *TypedValue[T]) Swap(new T) T { - old := t.value.Swap(tValue[T]{new}) +func (t *TypedValue[T]) Swap(new T) (v T) { + old := t.value.Swap(&new) if old == nil { - return DefaultValue[T]() + return } - return old.(tValue[T]).value + return *old } func (t *TypedValue[T]) CompareAndSwap(old, new T) bool { - return t.value.CompareAndSwap(tValue[T]{old}, tValue[T]{new}) || - // In the edge-case where [atomic.Value.Store] is uninitialized - // and trying to compare with the zero value of T, - // then compare-and-swap with the nil any value. - (any(old) == any(DefaultValue[T]()) && t.value.CompareAndSwap(any(nil), tValue[T]{new})) + for { + currentP := t.value.Load() + var currentValue T + if currentP != nil { + currentValue = *currentP + } + // Compare old and current via runtime equality check. + if any(currentValue) != any(old) { + return false + } + if t.value.CompareAndSwap(currentP, &new) { + return true + } + } } func (t *TypedValue[T]) MarshalJSON() ([]byte, error) { @@ -89,9 +81,3 @@ func NewTypedValue[T any](t T) (v TypedValue[T]) { v.Store(t) return } - -type noCopy struct{} - -// Lock is a no-op used by -copylocks checker from `go vet`. -func (*noCopy) Lock() {} -func (*noCopy) Unlock() {} diff --git a/clash-meta-android/core/src/foss/golang/clash/common/atomic/value_test.go b/clash-meta-android/core/src/foss/golang/clash/common/atomic/value_test.go index 881b3e8d8e..1697309d46 100644 --- a/clash-meta-android/core/src/foss/golang/clash/common/atomic/value_test.go +++ b/clash-meta-android/core/src/foss/golang/clash/common/atomic/value_test.go @@ -7,20 +7,6 @@ import ( ) func TestTypedValue(t *testing.T) { - { - // Always wrapping should not allocate for simple values - // because tValue[T] has the same memory layout as T. - var v TypedValue[bool] - bools := []bool{true, false} - if n := int(testing.AllocsPerRun(1000, func() { - for _, b := range bools { - v.Store(b) - } - })); n != 0 { - t.Errorf("AllocsPerRun = %d, want 0", n) - } - } - { var v TypedValue[int] got, gotOk := v.LoadOk() @@ -58,20 +44,126 @@ func TestTypedValue(t *testing.T) { } } + { + e1, e2, e3 := io.EOF, &os.PathError{}, &os.PathError{} + var v TypedValue[error] + if v.CompareAndSwap(e1, e2) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != nil { + t.Fatalf("Load = (%v), want (%v)", value, nil) + } + if v.CompareAndSwap(nil, e1) != true { + t.Fatalf("CompareAndSwap = false, want true") + } + if value := v.Load(); value != e1 { + t.Fatalf("Load = (%v), want (%v)", value, e1) + } + if v.CompareAndSwap(e2, e3) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != e1 { + t.Fatalf("Load = (%v), want (%v)", value, e1) + } + if v.CompareAndSwap(e1, e2) != true { + t.Fatalf("CompareAndSwap = false, want true") + } + if value := v.Load(); value != e2 { + t.Fatalf("Load = (%v), want (%v)", value, e2) + } + if v.CompareAndSwap(e3, e2) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != e2 { + t.Fatalf("Load = (%v), want (%v)", value, e2) + } + if v.CompareAndSwap(nil, e3) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != e2 { + t.Fatalf("Load = (%v), want (%v)", value, e2) + } + } + { c1, c2, c3 := make(chan struct{}), make(chan struct{}), make(chan struct{}) var v TypedValue[chan struct{}] if v.CompareAndSwap(c1, c2) != false { t.Fatalf("CompareAndSwap = true, want false") } + if value := v.Load(); value != nil { + t.Fatalf("Load = (%v), want (%v)", value, nil) + } if v.CompareAndSwap(nil, c1) != true { t.Fatalf("CompareAndSwap = false, want true") } + if value := v.Load(); value != c1 { + t.Fatalf("Load = (%v), want (%v)", value, c1) + } if v.CompareAndSwap(c2, c3) != false { t.Fatalf("CompareAndSwap = true, want false") } + if value := v.Load(); value != c1 { + t.Fatalf("Load = (%v), want (%v)", value, c1) + } if v.CompareAndSwap(c1, c2) != true { t.Fatalf("CompareAndSwap = false, want true") } + if value := v.Load(); value != c2 { + t.Fatalf("Load = (%v), want (%v)", value, c2) + } + if v.CompareAndSwap(c3, c2) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != c2 { + t.Fatalf("Load = (%v), want (%v)", value, c2) + } + if v.CompareAndSwap(nil, c3) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != c2 { + t.Fatalf("Load = (%v), want (%v)", value, c2) + } + } + + { + c1, c2, c3 := &io.LimitedReader{}, &io.SectionReader{}, &io.SectionReader{} + var v TypedValue[io.Reader] + if v.CompareAndSwap(c1, c2) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != nil { + t.Fatalf("Load = (%v), want (%v)", value, nil) + } + if v.CompareAndSwap(nil, c1) != true { + t.Fatalf("CompareAndSwap = false, want true") + } + if value := v.Load(); value != c1 { + t.Fatalf("Load = (%v), want (%v)", value, c1) + } + if v.CompareAndSwap(c2, c3) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != c1 { + t.Fatalf("Load = (%v), want (%v)", value, c1) + } + if v.CompareAndSwap(c1, c2) != true { + t.Fatalf("CompareAndSwap = false, want true") + } + if value := v.Load(); value != c2 { + t.Fatalf("Load = (%v), want (%v)", value, c2) + } + if v.CompareAndSwap(c3, c2) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != c2 { + t.Fatalf("Load = (%v), want (%v)", value, c2) + } + if v.CompareAndSwap(nil, c3) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if value := v.Load(); value != c2 { + t.Fatalf("Load = (%v), want (%v)", value, c2) + } } } diff --git a/clash-meta-android/core/src/foss/golang/clash/common/buf/sing.go b/clash-meta-android/core/src/foss/golang/clash/common/buf/sing.go index 59c650adeb..73f65f150d 100644 --- a/clash-meta-android/core/src/foss/golang/clash/common/buf/sing.go +++ b/clash-meta-android/core/src/foss/golang/clash/common/buf/sing.go @@ -14,6 +14,7 @@ var NewPacket = buf.NewPacket var NewSize = buf.NewSize var With = buf.With var As = buf.As +var ReleaseMulti = buf.ReleaseMulti var ( Must = common.Must diff --git a/clash-meta-android/core/src/foss/golang/clash/common/convert/converter.go b/clash-meta-android/core/src/foss/golang/clash/common/convert/converter.go index a4f89f37cc..c69a258a4f 100644 --- a/clash-meta-android/core/src/foss/golang/clash/common/convert/converter.go +++ b/clash-meta-android/core/src/foss/golang/clash/common/convert/converter.go @@ -221,6 +221,9 @@ func ConvertsV2Ray(buf []byte) ([]map[string]any, error) { if flow := query.Get("flow"); flow != "" { vless["flow"] = strings.ToLower(flow) } + if encryption := query.Get("encryption"); encryption != "" { + vless["encryption"] = encryption + } proxies = append(proxies, vless) case "vmess": diff --git a/clash-meta-android/core/src/foss/golang/clash/common/net/deadline/conn.go b/clash-meta-android/core/src/foss/golang/clash/common/net/deadline/conn.go index 01519e941c..aafad9e4ab 100644 --- a/clash-meta-android/core/src/foss/golang/clash/common/net/deadline/conn.go +++ b/clash-meta-android/core/src/foss/golang/clash/common/net/deadline/conn.go @@ -149,6 +149,10 @@ func (c *Conn) ReaderReplaceable() bool { return c.disablePipe.Load() || c.deadline.Load().IsZero() } +func (c *Conn) WriterReplaceable() bool { + return true +} + func (c *Conn) Upstream() any { return c.ExtendedConn } diff --git a/clash-meta-android/core/src/foss/golang/clash/common/net/sing.go b/clash-meta-android/core/src/foss/golang/clash/common/net/sing.go index 2cd1d726af..5cf9759427 100644 --- a/clash-meta-android/core/src/foss/golang/clash/common/net/sing.go +++ b/clash-meta-android/core/src/foss/golang/clash/common/net/sing.go @@ -22,6 +22,10 @@ type ExtendedReader = network.ExtendedReader var WriteBuffer = bufio.WriteBuffer +type ReadWaitOptions = network.ReadWaitOptions + +var NewReadWaitOptions = network.NewReadWaitOptions + func NewDeadlineConn(conn net.Conn) ExtendedConn { if deadline.IsPipe(conn) || deadline.IsPipe(network.UnwrapReader(conn)) { return NewExtendedConn(conn) // pipe always have correctly deadline implement diff --git a/clash-meta-android/core/src/foss/golang/clash/component/generater/cmd.go b/clash-meta-android/core/src/foss/golang/clash/component/generater/cmd.go deleted file mode 100644 index 96e62d7c23..0000000000 --- a/clash-meta-android/core/src/foss/golang/clash/component/generater/cmd.go +++ /dev/null @@ -1,49 +0,0 @@ -package generater - -import ( - "encoding/base64" - "fmt" - - "github.com/metacubex/mihomo/component/ech" - - "github.com/gofrs/uuid/v5" -) - -func Main(args []string) { - if len(args) < 1 { - panic("Using: generate uuid/reality-keypair/wg-keypair/ech-keypair") - } - switch args[0] { - case "uuid": - newUUID, err := uuid.NewV4() - if err != nil { - panic(err) - } - fmt.Println(newUUID.String()) - case "reality-keypair": - privateKey, err := GeneratePrivateKey() - if err != nil { - panic(err) - } - publicKey := privateKey.PublicKey() - fmt.Println("PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey[:])) - fmt.Println("PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey[:])) - case "wg-keypair": - privateKey, err := GeneratePrivateKey() - if err != nil { - panic(err) - } - fmt.Println("PrivateKey: " + privateKey.String()) - fmt.Println("PublicKey: " + privateKey.PublicKey().String()) - case "ech-keypair": - if len(args) < 2 { - panic("Using: generate ech-keypair ") - } - configBase64, keyPem, err := ech.GenECHConfig(args[1]) - if err != nil { - panic(err) - } - fmt.Println("Config:", configBase64) - fmt.Println("Key:", keyPem) - } -} diff --git a/clash-meta-android/core/src/foss/golang/clash/component/generater/types.go b/clash-meta-android/core/src/foss/golang/clash/component/generater/types.go deleted file mode 100644 index 06f59e9468..0000000000 --- a/clash-meta-android/core/src/foss/golang/clash/component/generater/types.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copy from https://github.com/WireGuard/wgctrl-go/blob/a9ab2273dd1075ea74b88c76f8757f8b4003fcbf/wgtypes/types.go#L71-L155 - -package generater - -import ( - "crypto/rand" - "encoding/base64" - "fmt" - - "golang.org/x/crypto/curve25519" -) - -// KeyLen is the expected key length for a WireGuard key. -const KeyLen = 32 // wgh.KeyLen - -// A Key is a public, private, or pre-shared secret key. The Key constructor -// functions in this package can be used to create Keys suitable for each of -// these applications. -type Key [KeyLen]byte - -// GenerateKey generates a Key suitable for use as a pre-shared secret key from -// a cryptographically safe source. -// -// The output Key should not be used as a private key; use GeneratePrivateKey -// instead. -func GenerateKey() (Key, error) { - b := make([]byte, KeyLen) - if _, err := rand.Read(b); err != nil { - return Key{}, fmt.Errorf("wgtypes: failed to read random bytes: %v", err) - } - - return NewKey(b) -} - -// GeneratePrivateKey generates a Key suitable for use as a private key from a -// cryptographically safe source. -func GeneratePrivateKey() (Key, error) { - key, err := GenerateKey() - if err != nil { - return Key{}, err - } - - // Modify random bytes using algorithm described at: - // https://cr.yp.to/ecdh.html. - key[0] &= 248 - key[31] &= 127 - key[31] |= 64 - - return key, nil -} - -// NewKey creates a Key from an existing byte slice. The byte slice must be -// exactly 32 bytes in length. -func NewKey(b []byte) (Key, error) { - if len(b) != KeyLen { - return Key{}, fmt.Errorf("wgtypes: incorrect key size: %d", len(b)) - } - - var k Key - copy(k[:], b) - - return k, nil -} - -// ParseKey parses a Key from a base64-encoded string, as produced by the -// Key.String method. -func ParseKey(s string) (Key, error) { - b, err := base64.StdEncoding.DecodeString(s) - if err != nil { - return Key{}, fmt.Errorf("wgtypes: failed to parse base64-encoded key: %v", err) - } - - return NewKey(b) -} - -// PublicKey computes a public key from the private key k. -// -// PublicKey should only be called when k is a private key. -func (k Key) PublicKey() Key { - var ( - pub [KeyLen]byte - priv = [KeyLen]byte(k) - ) - - // ScalarBaseMult uses the correct base value per https://cr.yp.to/ecdh.html, - // so no need to specify it. - curve25519.ScalarBaseMult(&pub, &priv) - - return Key(pub) -} - -// String returns the base64-encoded string representation of a Key. -// -// ParseKey can be used to produce a new Key from this string. -func (k Key) String() string { - return base64.StdEncoding.EncodeToString(k[:]) -} diff --git a/clash-meta-android/core/src/foss/golang/clash/component/generator/cmd.go b/clash-meta-android/core/src/foss/golang/clash/component/generator/cmd.go new file mode 100644 index 0000000000..320bb11d36 --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/component/generator/cmd.go @@ -0,0 +1,73 @@ +package generator + +import ( + "encoding/base64" + "fmt" + + "github.com/metacubex/mihomo/component/ech" + "github.com/metacubex/mihomo/transport/vless/encryption" + + "github.com/gofrs/uuid/v5" +) + +func Main(args []string) { + if len(args) < 1 { + panic("Using: generate uuid/reality-keypair/wg-keypair/ech-keypair/vless-mlkem768/vless-x25519") + } + switch args[0] { + case "uuid": + newUUID, err := uuid.NewV4() + if err != nil { + panic(err) + } + fmt.Println(newUUID.String()) + case "reality-keypair": + privateKey, err := GenX25519PrivateKey() + if err != nil { + panic(err) + } + fmt.Println("PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey.Bytes())) + fmt.Println("PublicKey: " + base64.RawURLEncoding.EncodeToString(privateKey.PublicKey().Bytes())) + case "wg-keypair": + privateKey, err := GenX25519PrivateKey() + if err != nil { + panic(err) + } + fmt.Println("PrivateKey: " + base64.StdEncoding.EncodeToString(privateKey.Bytes())) + fmt.Println("PublicKey: " + base64.StdEncoding.EncodeToString(privateKey.PublicKey().Bytes())) + case "ech-keypair": + if len(args) < 2 { + panic("Using: generate ech-keypair ") + } + configBase64, keyPem, err := ech.GenECHConfig(args[1]) + if err != nil { + panic(err) + } + fmt.Println("Config:", configBase64) + fmt.Println("Key:", keyPem) + case "vless-mlkem768": + var seed string + if len(args) > 1 { + seed = args[1] + } + seedBase64, clientBase64, hash32Base64, err := encryption.GenMLKEM768(seed) + if err != nil { + panic(err) + } + fmt.Println("Seed: " + seedBase64) + fmt.Println("Client: " + clientBase64) + fmt.Println("Hash32: " + hash32Base64) + case "vless-x25519": + var privateKey string + if len(args) > 1 { + privateKey = args[1] + } + privateKeyBase64, passwordBase64, hash32Base64, err := encryption.GenX25519(privateKey) + if err != nil { + panic(err) + } + fmt.Println("PrivateKey: " + privateKeyBase64) + fmt.Println("Password: " + passwordBase64) + fmt.Println("Hash32: " + hash32Base64) + } +} diff --git a/clash-meta-android/core/src/foss/golang/clash/component/generator/x25519.go b/clash-meta-android/core/src/foss/golang/clash/component/generator/x25519.go new file mode 100644 index 0000000000..e99fff2bae --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/component/generator/x25519.go @@ -0,0 +1,27 @@ +package generator + +import ( + "crypto/ecdh" + "crypto/rand" +) + +const X25519KeySize = 32 + +func GenX25519PrivateKey() (*ecdh.PrivateKey, error) { + var privateKey [X25519KeySize]byte + _, err := rand.Read(privateKey[:]) + if err != nil { + return nil, err + } + + // Avoid generating equivalent X25519 private keys + // https://github.com/XTLS/Xray-core/pull/1747 + // + // Modify random bytes using algorithm described at: + // https://cr.yp.to/ecdh.html. + privateKey[0] &= 248 + privateKey[31] &= 127 + privateKey[31] |= 64 + + return ecdh.X25519().NewPrivateKey(privateKey[:]) +} diff --git a/clash-meta-android/core/src/foss/golang/clash/component/keepalive/tcp_keepalive.go b/clash-meta-android/core/src/foss/golang/clash/component/keepalive/tcp_keepalive.go index ddb853e916..fee06a94e1 100644 --- a/clash-meta-android/core/src/foss/golang/clash/component/keepalive/tcp_keepalive.go +++ b/clash-meta-android/core/src/foss/golang/clash/component/keepalive/tcp_keepalive.go @@ -10,27 +10,27 @@ import ( ) var ( - keepAliveIdle = atomic.NewTypedValue[time.Duration](0 * time.Second) - keepAliveInterval = atomic.NewTypedValue[time.Duration](0 * time.Second) + keepAliveIdle = atomic.NewInt64(0) + keepAliveInterval = atomic.NewInt64(0) disableKeepAlive = atomic.NewBool(false) SetDisableKeepAliveCallback = utils.NewCallback[bool]() ) func SetKeepAliveIdle(t time.Duration) { - keepAliveIdle.Store(t) + keepAliveIdle.Store(int64(t)) } func SetKeepAliveInterval(t time.Duration) { - keepAliveInterval.Store(t) + keepAliveInterval.Store(int64(t)) } func KeepAliveIdle() time.Duration { - return keepAliveIdle.Load() + return time.Duration(keepAliveIdle.Load()) } func KeepAliveInterval() time.Duration { - return keepAliveInterval.Load() + return time.Duration(keepAliveInterval.Load()) } func SetDisableKeepAlive(disable bool) { diff --git a/clash-meta-android/core/src/foss/golang/clash/component/tls/reality.go b/clash-meta-android/core/src/foss/golang/clash/component/tls/reality.go index 41c14781bb..2de5c46e73 100644 --- a/clash-meta-android/core/src/foss/golang/clash/component/tls/reality.go +++ b/clash-meta-android/core/src/foss/golang/clash/component/tls/reality.go @@ -170,7 +170,7 @@ type realityVerifier struct { //var pOffset = utils.MustOK(reflect.TypeOf((*utls.Conn)(nil)).Elem().FieldByName("peerCertificates")).Offset func (c *realityVerifier) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { - //log.Debugln("REALITY localAddr: %v\t is using X25519MLKEM768 for TLS' communication: %v", c.RemoteAddr(), c.HandshakeState.ServerHello.SelectedGroup == utls.X25519MLKEM768) + log.Debugln("REALITY localAddr: %v is using X25519MLKEM768 for TLS' communication: %v", c.RemoteAddr(), c.HandshakeState.ServerHello.ServerShare.Group == utls.X25519MLKEM768) //p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates") //certs := *(*[]*x509.Certificate)(unsafe.Add(unsafe.Pointer(c.Conn), pOffset)) certs := c.Conn.PeerCertificates() diff --git a/clash-meta-android/core/src/foss/golang/clash/component/updater/update_core.go b/clash-meta-android/core/src/foss/golang/clash/component/updater/update_core.go index fedf65187f..5f7113d0fb 100644 --- a/clash-meta-android/core/src/foss/golang/clash/component/updater/update_core.go +++ b/clash-meta-android/core/src/foss/golang/clash/component/updater/update_core.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "os" + "os/exec" "path/filepath" "runtime" "strings" @@ -33,6 +34,11 @@ const ( MaxPackageFileSize = 32 * 1024 * 1024 ) +const ( + ReleaseChannel = "release" + AlphaChannel = "alpha" +) + // CoreUpdater is the mihomo updater. // modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go type CoreUpdater struct { @@ -69,20 +75,28 @@ func (u *CoreUpdater) CoreBaseName() string { } } -func (u *CoreUpdater) Update(currentExePath string) (err error) { +func (u *CoreUpdater) Update(currentExePath string, channel string, force bool) (err error) { u.mu.Lock() defer u.mu.Unlock() - _, err = os.Stat(currentExePath) + info, err := os.Stat(currentExePath) if err != nil { return fmt.Errorf("check currentExePath %q: %w", currentExePath, err) } baseURL := baseAlphaURL versionURL := versionAlphaURL - if !strings.HasPrefix(C.Version, "alpha") { + switch strings.ToLower(channel) { + case ReleaseChannel: baseURL = baseReleaseURL versionURL = versionReleaseURL + case AlphaChannel: + break + default: // auto + if !strings.HasPrefix(C.Version, "alpha") { + baseURL = baseReleaseURL + versionURL = versionReleaseURL + } } latestVersion, err := u.getLatestVersion(versionURL) @@ -91,7 +105,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) { } log.Infoln("current version %s, latest version %s", C.Version, latestVersion) - if latestVersion == C.Version { + if latestVersion == C.Version && !force { // don't change this output, some downstream dependencies on the upgrader's output fields return fmt.Errorf("update error: already using latest version %s", C.Version) } @@ -136,7 +150,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) { return fmt.Errorf("downloading: %w", err) } - err = u.unpack(updateDir, packagePath) + err = u.unpack(updateDir, packagePath, info.Mode()) if err != nil { return fmt.Errorf("unpacking: %w", err) } @@ -146,7 +160,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) { return fmt.Errorf("backuping: %w", err) } - err = u.replace(updateExePath, currentExePath) + err = u.copyFile(updateExePath, currentExePath) if err != nil { return fmt.Errorf("replacing: %w", err) } @@ -230,16 +244,16 @@ func (u *CoreUpdater) download(updateDir, packagePath, packageURL string) (err e } // unpack extracts the files from the downloaded archive. -func (u *CoreUpdater) unpack(updateDir, packagePath string) error { +func (u *CoreUpdater) unpack(updateDir, packagePath string, fileMode os.FileMode) error { log.Infoln("updater: unpacking package") if strings.HasSuffix(packagePath, ".zip") { - _, err := u.zipFileUnpack(packagePath, updateDir) + _, err := u.zipFileUnpack(packagePath, updateDir, fileMode) if err != nil { return fmt.Errorf(".zip unpack failed: %w", err) } } else if strings.HasSuffix(packagePath, ".gz") { - _, err := u.gzFileUnpack(packagePath, updateDir) + _, err := u.gzFileUnpack(packagePath, updateDir, fileMode) if err != nil { return fmt.Errorf(".gz unpack failed: %w", err) } @@ -271,21 +285,6 @@ func (u *CoreUpdater) backup(currentExePath, backupExePath, backupDir string) (e return nil } -// replace moves the current executable with the updated one -func (u *CoreUpdater) replace(updateExePath, currentExePath string) error { - log.Infoln("replacing: %s to %s", updateExePath, currentExePath) - - // Use copyFile to retain the original file attributes - err := u.copyFile(updateExePath, currentExePath) - if err != nil { - return err - } - - log.Infoln("updater: copy: %s to %s", updateExePath, currentExePath) - - return nil -} - // clean removes the temporary directory itself and all it's contents. func (u *CoreUpdater) clean(updateDir string) { _ = os.RemoveAll(updateDir) @@ -295,7 +294,7 @@ func (u *CoreUpdater) clean(updateDir string) { // Existing files are overwritten // All files are created inside outDir, subdirectories are not created // Return the output file name -func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, err error) { +func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string, fileMode os.FileMode) (outputName string, err error) { f, err := os.Open(gzfile) if err != nil { return "", fmt.Errorf("os.Open(): %w", err) @@ -330,7 +329,7 @@ func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, er outputName = filepath.Join(outDir, originalName) // Create the output file - wc, err := os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755) + wc, err := os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileMode) if err != nil { return "", fmt.Errorf("os.OpenFile(%s): %w", outputName, err) } @@ -355,7 +354,7 @@ func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, er // Existing files are overwritten // All files are created inside 'outDir', subdirectories are not created // Return the output file name -func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string) (outputName string, err error) { +func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string, fileMode os.FileMode) (outputName string, err error) { zrc, err := zip.OpenReader(zipfile) if err != nil { return "", fmt.Errorf("zip.OpenReader(): %w", err) @@ -394,7 +393,7 @@ func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string) (outputName string, } var wc io.WriteCloser - wc, err = os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fi.Mode()) + wc, err = os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileMode) if err != nil { return "", fmt.Errorf("os.OpenFile(): %w", err) } @@ -437,7 +436,16 @@ func (u *CoreUpdater) copyFile(src, dst string) (err error) { // otherwise truncates it before writing, without changing permissions. wc, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, info.Mode()) if err != nil { - return fmt.Errorf("os.OpenFile(%s): %w", dst, err) + // On some file system (such as Android's /data) maybe return error: "text file busy" + // Let's delete the target file and recreate it + err = os.Remove(dst) + if err != nil { + return fmt.Errorf("os.Remove(%s): %w", dst, err) + } + wc, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, info.Mode()) + if err != nil { + return fmt.Errorf("os.OpenFile(%s): %w", dst, err) + } } defer func() { @@ -452,5 +460,13 @@ func (u *CoreUpdater) copyFile(src, dst string) (err error) { return fmt.Errorf("io.Copy(): %w", err) } + if runtime.GOOS == "darwin" { + err = exec.Command("/usr/bin/codesign", "--sign", "-", dst).Run() + if err != nil { + log.Warnln("codesign failed: %v", err) + } + } + + log.Infoln("updater: copy: %s to %s", src, dst) return nil } diff --git a/clash-meta-android/core/src/foss/golang/clash/component/wildcard/wildcard.go b/clash-meta-android/core/src/foss/golang/clash/component/wildcard/wildcard.go index 7fcf15ba34..c22eedf90a 100644 --- a/clash-meta-android/core/src/foss/golang/clash/component/wildcard/wildcard.go +++ b/clash-meta-android/core/src/foss/golang/clash/component/wildcard/wildcard.go @@ -1,3 +1,12 @@ +// Package wildcard modified IGLOU-EU/go-wildcard to support: +// +// `*` matches zero or more characters +// `?` matches exactly one character +// +// The original go-wildcard library used `.` to match exactly one character, and `?` to match zero or one character. +// `.` is a valid delimiter in domain name matching and should not be used as a wildcard. +// The `?` matching logic strictly matches only one character in most scenarios. +// So, the `?` matching logic in the original go-wildcard library has been removed and its wildcard `.` has been replaced with `?`. package wildcard // copy and modified from https://github.com/IGLOU-EU/go-wildcard/tree/ce22b7af48e487517a492d3727d9386492043e21 @@ -16,12 +25,10 @@ func Match(pattern, s string) bool { } func matchByString(pattern, s string) bool { - var lastErotemeCluster byte - var patternIndex, sIndex, lastStar, lastEroteme int + var patternIndex, sIndex, lastStar int patternLen := len(pattern) sLen := len(s) star := -1 - eroteme := -1 Loop: if sIndex >= sLen { @@ -38,14 +45,8 @@ Loop: return false } switch pattern[patternIndex] { - // Removed dot matching as it conflicts with dot in domains. - // case '.': - // It matches any single character. So, we don't need to check anything. case '?': - // '?' matches one character. Store its position and match exactly one character in the string. - eroteme = patternIndex - lastEroteme = sIndex - lastErotemeCluster = byte(s[sIndex]) + // It matches any single character. So, we don't need to check anything. case '*': // '*' matches zero or more characters. Store its position and increment the pattern index. star = patternIndex @@ -53,15 +54,8 @@ Loop: patternIndex++ goto Loop default: - // If the characters don't match, check if there was a previous '?' or '*' to backtrack. + // If the characters don't match, check if there was a previous '*' to backtrack. if pattern[patternIndex] != s[sIndex] { - if eroteme != -1 { - patternIndex = eroteme + 1 - sIndex = lastEroteme - eroteme = -1 - goto Loop - } - if star != -1 { patternIndex = star + 1 lastStar++ @@ -71,29 +65,18 @@ Loop: return false } - - // If the characters match, check if it was not the same to validate the eroteme. - if eroteme != -1 && lastErotemeCluster != byte(s[sIndex]) { - eroteme = -1 - } } patternIndex++ sIndex++ goto Loop - // Check if the remaining pattern characters are '*' or '?', which can match the end of the string. + // Check if the remaining pattern characters are '*', which can match the end of the string. checkPattern: if patternIndex < patternLen { if pattern[patternIndex] == '*' { patternIndex++ goto checkPattern - } else if pattern[patternIndex] == '?' { - if sIndex >= sLen { - sIndex-- - } - patternIndex++ - goto checkPattern } } diff --git a/clash-meta-android/core/src/foss/golang/clash/component/wildcard/wildcard_test.go b/clash-meta-android/core/src/foss/golang/clash/component/wildcard/wildcard_test.go index 719a4979ff..64b833d79d 100644 --- a/clash-meta-android/core/src/foss/golang/clash/component/wildcard/wildcard_test.go +++ b/clash-meta-android/core/src/foss/golang/clash/component/wildcard/wildcard_test.go @@ -25,31 +25,17 @@ func TestMatch(t *testing.T) { {"", "", true}, {"", "*", true}, {"", "**", true}, - {"", "?", true}, - {"", "??", true}, - {"", "?*", true}, - {"", "*?", true}, - {"", ".", false}, - {"", ".?", false}, - {"", "?.", false}, - {"", ".*", false}, - {"", "*.", false}, - {"", "*.?", false}, - {"", "?.*", false}, + {"", "?", false}, + {"", "?*", false}, + {"", "*?", false}, {"a", "", false}, {"a", "a", true}, {"a", "*", true}, {"a", "**", true}, {"a", "?", true}, - {"a", "??", true}, - {"a", ".", false}, - {"a", ".?", false}, - {"a", "?.", false}, - {"a", ".*", false}, - {"a", "*.", false}, - {"a", "*.?", false}, - {"a", "?.*", false}, + {"a", "?*", true}, + {"a", "*?", true}, {"match the exact string", "match the exact string", true}, {"do not match a different string", "this is a different string", false}, @@ -68,22 +54,27 @@ func TestMatch(t *testing.T) { {"match a string with a ?", "match ? string with a ?", true}, {"match a string with a ? at the beginning", "?atch a string with a ? at the beginning", true}, - {"match a string with two ?", "match a string with two ??", true}, - {"match a optional char with a ?", "match a optional? char with a ?", true}, - {"match a optional char with a ?", "match a optional? char with a ?", true}, - {"do not match a string with extra and a ?", "do not match ? string with extra and a ? like this", false}, + {"match a string with two ?", "match a ??ring with two ?", true}, + {"do not match a string with extra ?", "do not match a string with extra ??", false}, - {"do not match a string with a .", "do not match . string with a .", false}, - {"do not match a string with a . at the beginning", "do not .atch a string with a . at the beginning", false}, - {"do not match a string with two .", "do not match a ..ring with two .", false}, - {"do not match a string with extra .", "do not match a string with extra ..", false}, + {"abc.edf.hjg", "abc.edf.hjg", true}, + {"abc.edf.hjg", "ab.cedf.hjg", false}, + {"abc.edf.hjg", "abc.edfh.jg", false}, + {"abc.edf.hjg", "abc.edf.hjq", false}, - {"A big brown fox jumps over the lazy dog, with all there wildcards friends", ". big?brown fox jumps over * wildcard. friend??", false}, - {"A big brown fox fails to jump over the lazy dog, with all there wildcards friends", ". big?brown fox jumps over * wildcard. friend??", false}, + {"abc.edf.hjg", "abc.*.hjg", true}, + {"abc.edf.hjg", "abc.*.hjq", false}, + {"abc.edf.hjg", "abc*hjg", true}, + {"abc.edf.hjg", "abc*hjq", false}, + {"abc.edf.hjg", "a*g", true}, + {"abc.edf.hjg", "a*q", false}, - {"domain a.b.c", "domain a.b.c", true}, - {"domain adb.c", "domain a.b.c", false}, - {"aaaa", "a*a", true}, + {"abc.edf.hjg", "ab?.edf.hjg", true}, + {"abc.edf.hjg", "?b?.edf.hjg", true}, + {"abc.edf.hjg", "??c.edf.hjg", true}, + {"abc.edf.hjg", "a??.edf.hjg", true}, + {"abc.edf.hjg", "ab??.edf.hjg", false}, + {"abc.edf.hjg", "??.edf.hjg", false}, } for i, c := range cases { @@ -96,10 +87,106 @@ func TestMatch(t *testing.T) { } } +func match(pattern, name string) bool { // https://research.swtch.com/glob + px := 0 + nx := 0 + nextPx := 0 + nextNx := 0 + for px < len(pattern) || nx < len(name) { + if px < len(pattern) { + c := pattern[px] + switch c { + default: // ordinary character + if nx < len(name) && name[nx] == c { + px++ + nx++ + continue + } + case '?': // single-character wildcard + if nx < len(name) { + px++ + nx++ + continue + } + case '*': // zero-or-more-character wildcard + // Try to match at nx. + // If that doesn't work out, + // restart at nx+1 next. + nextPx = px + nextNx = nx + 1 + px++ + continue + } + } + // Mismatch. Maybe restart. + if 0 < nextNx && nextNx <= len(name) { + px = nextPx + nx = nextNx + continue + } + return false + } + // Matched all of pattern to all of name. Success. + return true +} + func FuzzMatch(f *testing.F) { - f.Fuzz(func(t *testing.T, s string) { - if !Match(string(s), string(s)) { - t.Fatalf("%s does not match %s", s, s) + f.Fuzz(func(t *testing.T, pattern, name string) { + result1 := Match(pattern, name) + result2 := match(pattern, name) + if result1 != result2 { + t.Fatalf("Match failed for pattern `%s` and name `%s`", pattern, name) + } + }) +} + +func BenchmarkMatch(b *testing.B) { + cases := []struct { + s string + pattern string + result bool + }{ + {"abc.edf.hjg", "abc.edf.hjg", true}, + {"abc.edf.hjg", "ab.cedf.hjg", false}, + {"abc.edf.hjg", "abc.edfh.jg", false}, + {"abc.edf.hjg", "abc.edf.hjq", false}, + + {"abc.edf.hjg", "abc.*.hjg", true}, + {"abc.edf.hjg", "abc.*.hjq", false}, + {"abc.edf.hjg", "abc*hjg", true}, + {"abc.edf.hjg", "abc*hjq", false}, + {"abc.edf.hjg", "a*g", true}, + {"abc.edf.hjg", "a*q", false}, + + {"abc.edf.hjg", "ab?.edf.hjg", true}, + {"abc.edf.hjg", "?b?.edf.hjg", true}, + {"abc.edf.hjg", "??c.edf.hjg", true}, + {"abc.edf.hjg", "a??.edf.hjg", true}, + {"abc.edf.hjg", "ab??.edf.hjg", false}, + {"abc.edf.hjg", "??.edf.hjg", false}, + + {"r4.cdn-aa-wow-this-is-long-a1.video-yajusenpai1145141919810-oh-hell-yeah-this-is-also-very-long-and-sukka-the-fox-has-a-very-big-fluffy-fox-tail-ao-wu-ao-wu-regex-and-wildcard-both-might-have-deadly-back-tracing-issue-be-careful-or-use-linear-matching.com", "*.cdn-*-*.video**.com", true}, + } + + b.Run("Match", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, c := range cases { + result := Match(c.pattern, c.s) + if c.result != result { + b.Errorf("Test %d: Expected `%v`, found `%v`; With Pattern: `%s` and String: `%s`", i+1, c.result, result, c.pattern, c.s) + } + } + } + }) + + b.Run("match", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, c := range cases { + result := match(c.pattern, c.s) + if c.result != result { + b.Errorf("Test %d: Expected `%v`, found `%v`; With Pattern: `%s` and String: `%s`", i+1, c.result, result, c.pattern, c.s) + } + } } }) } diff --git a/clash-meta-android/core/src/foss/golang/clash/dns/enhancer.go b/clash-meta-android/core/src/foss/golang/clash/dns/enhancer.go index a8c0a5ac0d..9ea3ae84ac 100644 --- a/clash-meta-android/core/src/foss/golang/clash/dns/enhancer.go +++ b/clash-meta-android/core/src/foss/golang/clash/dns/enhancer.go @@ -81,8 +81,8 @@ func (h *ResolverEnhancer) InsertHostByIP(ip netip.Addr, host string) { } func (h *ResolverEnhancer) FlushFakeIP() error { - if h.fakePool != nil { - return h.fakePool.FlushFakeIP() + if pool := h.fakePool; pool != nil { + return pool.FlushFakeIP() } return nil } diff --git a/clash-meta-android/core/src/foss/golang/clash/docs/config.yaml b/clash-meta-android/core/src/foss/golang/clash/docs/config.yaml index d458d60dbc..aa105ff671 100644 --- a/clash-meta-android/core/src/foss/golang/clash/docs/config.yaml +++ b/clash-meta-android/core/src/foss/golang/clash/docs/config.yaml @@ -632,6 +632,21 @@ proxies: # socks5 # fingerprint: xxxx # skip-cert-verify: true + - name: "vless-encryption" + type: vless + server: server + port: 443 + uuid: uuid + network: tcp + # ------------------------- + # vless encryption客户端配置: + # (native/xorpub 的 XTLS 可以 Splice。只使用 1-RTT 模式 / 若服务端发的 ticket 中秒数不为零则 0-RTT 复用) + # / 是只能选一个,后面 base64 至少一个,无限串联,使用 mihomo generate vless-x25519 和 mihomo generate vless-mlkem768 生成,替换值时需去掉括号 + # ------------------------- + encryption: "mlkem768x25519plus.native/xorpub/random.1rtt/0rtt.(X25519 Password).(ML-KEM-768 Client)..." + tls: false #可以不开启tls + udp: true + - name: "vless-reality-vision" type: vless server: server @@ -846,6 +861,16 @@ proxies: # socks5 # h2: 67543 # h4: 32345 # h3: 123123 + # # AmneziaWG v1.5 + # i1: + # i2: + # i3: "" + # i4: "" + # i5: "" + # j1: + # j2: + # j3: + # itime: 60 # tuic - name: tuic @@ -922,6 +947,8 @@ proxies: # socks5 password: password # 可以使用的值包括 MULTIPLEXING_OFF, MULTIPLEXING_LOW, MULTIPLEXING_MIDDLE, MULTIPLEXING_HIGH。其中 MULTIPLEXING_OFF 会关闭多路复用功能。默认值为 MULTIPLEXING_LOW。 # multiplexing: MULTIPLEXING_LOW + # 如果想开启 0-RTT 握手,请设置为 HANDSHAKE_NO_WAIT,否则请设置为 HANDSHAKE_STANDARD。默认值为 HANDSHAKE_STANDARD + # handshake-mode: HANDSHAKE_STANDARD # anytls - name: anytls @@ -1336,6 +1363,12 @@ listeners: flow: xtls-rprx-vision # ws-path: "/" # 如果不为空则开启 websocket 传输层 # grpc-service-name: "GunService" # 如果不为空则开启 grpc 传输层 + # ------------------------- + # vless encryption服务端配置: + # (原生外观 / 只 XOR 公钥 / 全随机数。只允许 1-RTT 模式 / 同时允许 1-RTT 模式与 600 秒复用的 0-RTT 模式) + # / 是只能选一个,后面 base64 至少一个,无限串联,使用 mihomo generate vless-x25519 和 mihomo generate vless-mlkem768 生成,替换值时需去掉括号 + # ------------------------- + # decryption: "mlkem768x25519plus.native/xorpub/random.1rtt/600s.(X25519 PrivateKey).(ML-KEM-768 Seed)..." # 下面两项如果填写则开启 tls(需要同时填写) # certificate: ./server.crt # private-key: ./server.key @@ -1364,7 +1397,7 @@ listeners: after-bytes: 0 # 传输指定字节后开始限速 bytes-per-sec: 0 # 基准速率(字节/秒) burst-bytes-per-sec: 0 # 突发速率(字节/秒),大于 bytesPerSec 时生效 - ### 注意,对于vless listener, 至少需要填写 “certificate和private-key” 或 “reality-config” 的其中一项 ### + ### 注意,对于vless listener, 至少需要填写 “certificate和private-key” 或 “reality-config” 或 “decryption” 的其中一项 ### - name: anytls-in-1 type: anytls @@ -1462,6 +1495,7 @@ listeners: # masquerade: http://127.0.0.1:8080 #作为反向代理 # masquerade: https://127.0.0.1:8080 #作为反向代理 + # 注意,listeners中的tun仅提供给高级用户使用,普通用户应使用顶层配置中的tun - name: tun-in-1 type: tun # rule: sub-rule-name1 # 默认使用 rules,如果未找到 sub-rule 则直接使用 rules diff --git a/clash-meta-android/core/src/foss/golang/clash/go.mod b/clash-meta-android/core/src/foss/golang/clash/go.mod index 125805440a..834bac83cf 100644 --- a/clash-meta-android/core/src/foss/golang/clash/go.mod +++ b/clash-meta-android/core/src/foss/golang/clash/go.mod @@ -3,40 +3,40 @@ module github.com/metacubex/mihomo go 1.20 require ( - github.com/3andne/restls-client-go v0.1.6 github.com/bahlo/generic-list-go v0.2.0 github.com/coreos/go-iptables v0.8.0 github.com/dlclark/regexp2 v1.11.5 - github.com/enfein/mieru/v3 v3.16.1 - github.com/go-chi/chi/v5 v5.2.2 + github.com/enfein/mieru/v3 v3.19.1 + github.com/go-chi/chi/v5 v5.2.3 github.com/go-chi/render v1.0.3 github.com/gobwas/ws v1.4.0 github.com/gofrs/uuid/v5 v5.3.2 github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 github.com/klauspost/compress v1.17.9 // lastest version compatible with golang1.20 - github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 github.com/mdlayher/netlink v1.7.2 - github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab + github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a github.com/metacubex/bart v0.20.5 github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b + github.com/metacubex/blake3 v0.1.0 github.com/metacubex/chacha v0.1.5 github.com/metacubex/fswatch v0.1.1 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 - github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c + github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 github.com/metacubex/randv2 v0.2.0 - github.com/metacubex/sing v0.5.4 - github.com/metacubex/sing-mux v0.3.2 + github.com/metacubex/restls-client-go v0.1.7 + github.com/metacubex/sing v0.5.5 + github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb - github.com/metacubex/sing-shadowsocks v0.2.11 - github.com/metacubex/sing-shadowsocks2 v0.2.5 + github.com/metacubex/sing-shadowsocks v0.2.12 + github.com/metacubex/sing-shadowsocks2 v0.2.6 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 - github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97 - github.com/metacubex/sing-vmess v0.2.3 + github.com/metacubex/sing-tun v0.4.7 + github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20250503055512-501391591dee - github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 - github.com/metacubex/utls v1.8.0 - github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 + github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617 + github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142 + github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20 github.com/mroth/weightedrand/v2 v2.1.0 github.com/openacid/low v0.1.21 @@ -46,7 +46,7 @@ require ( github.com/samber/lo v1.51.0 github.com/shirou/gopsutil/v4 v4.25.1 // lastest version compatible with golang1.20 github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.0 github.com/vmihailenco/msgpack/v5 v5.4.1 github.com/wk8/go-ordered-map/v2 v2.1.8 gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7 @@ -59,7 +59,6 @@ require ( golang.org/x/sys v0.30.0 // lastest version compatible with golang1.20 google.golang.org/protobuf v1.34.2 // lastest version compatible with golang1.20 gopkg.in/yaml.v3 v3.0.1 - lukechampine.com/blake3 v1.3.0 // lastest version compatible with golang1.20 ) require ( @@ -69,7 +68,7 @@ require ( github.com/andybalholm/brotli v1.0.6 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/ebitengine/purego v0.8.3 // indirect + github.com/ebitengine/purego v0.8.4 // indirect github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 // indirect github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect @@ -85,11 +84,11 @@ require ( github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/hashicorp/yamux v0.1.2 // indirect github.com/josharian/native v1.1.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mdlayher/socket v0.4.1 // indirect + github.com/metacubex/ascon v0.1.0 // indirect github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect diff --git a/clash-meta-android/core/src/foss/golang/clash/go.sum b/clash-meta-android/core/src/foss/golang/clash/go.sum index b539dbd5ad..15b38771a1 100644 --- a/clash-meta-android/core/src/foss/golang/clash/go.sum +++ b/clash-meta-android/core/src/foss/golang/clash/go.sum @@ -1,5 +1,3 @@ -github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08= -github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY= github.com/RyuaNerin/go-krypto v1.3.0 h1:smavTzSMAx8iuVlGb4pEwl9MD2qicqMzuXR2QWp2/Pg= github.com/RyuaNerin/go-krypto v1.3.0/go.mod h1:9R9TU936laAIqAmjcHo/LsaXYOZlymudOAxjaBf62UM= github.com/RyuaNerin/testingutil v0.1.0 h1:IYT6JL57RV3U2ml3dLHZsVtPOP6yNK7WUVdzzlpNrss= @@ -25,10 +23,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc= -github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/enfein/mieru/v3 v3.16.1 h1:CfIt1pQCCQbohkw+HBD2o8V9tnhZvB5yuXGGQIXTLOs= -github.com/enfein/mieru/v3 v3.16.1/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/enfein/mieru/v3 v3.19.1 h1:19b9kgFC7oJXX9RLEO5Pi1gO6yek5cWlpK7IJVUoE8I= +github.com/enfein/mieru/v3 v3.19.1/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM= github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 h1:kXYqH/sL8dS/FdoFjr12ePjnLPorPo2FsnrHNuXSDyo= github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I= github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g= @@ -42,8 +40,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= -github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= -github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= +github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -81,27 +79,27 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= -github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= -github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= -github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab h1:Chbw+/31UC14YFNr78pESt5Vowlc62zziw05JCUqoL4= -github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab/go.mod h1:xVKK8jC5Sd3hfh7WjmCq+HorehIbrBijaUWmcuKjPcI= +github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a h1:c1QSGpacSeQdBdWcEKZKGuWLcqIG2wxHEygAcXuDwS4= +github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a/go.mod h1:MsM/5czONyXMJ3PRr5DbQ4O/BxzAnJWOIcJdLzW6qHY= +github.com/metacubex/ascon v0.1.0 h1:6ZWxmXYszT1XXtwkf6nxfFhc/OTtQ9R3Vyj1jN32lGM= +github.com/metacubex/ascon v0.1.0/go.mod h1:eV5oim4cVPPdEL8/EYaTZ0iIKARH9pnhAK/fcT5Kacc= github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM= github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI= github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b h1:j7dadXD8I2KTmMt8jg1JcaP1ANL3JEObJPdANKcSYPY= github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b/go.mod h1:+WmP0VJZDkDszvpa83HzfUp6QzARl/IKkMorH4+nODw= +github.com/metacubex/blake3 v0.1.0 h1:KGnjh/56REO7U+cgZA8dnBhxdP7jByrG7hTP+bu6cqY= +github.com/metacubex/blake3 v0.1.0/go.mod h1:CCkLdzFrqf7xmxCdhQFvJsRRV2mwOLDoSPg6vUTB9Uk= github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M= github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8= github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU= @@ -112,37 +110,39 @@ github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= -github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c h1:ABQzmOaZddM3q0OYeoZEc0XF+KW+dUdPNvY/c5rsunI= -github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c/go.mod h1:eWlAK3zsKI0P8UhYpXlIsl3mtW4D6MpMNuYLIu8CKWI= +github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs= +github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= +github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k= +github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing v0.5.4 h1:a4kAOZmF+OXosbzPEcrSc5QD35/ex+MNuZsrcuWskHk= -github.com/metacubex/sing v0.5.4/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing-mux v0.3.2 h1:nJv52pyRivHcaZJKk2JgxpaVvj1GAXG81scSa9N7ncw= -github.com/metacubex/sing-mux v0.3.2/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= +github.com/metacubex/sing v0.5.5 h1:m5U8iHvRAUxlme3FZlE/LPIGHjU8oMCUzXWGbQQAC1E= +github.com/metacubex/sing v0.5.5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= +github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs= +github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb/go.mod h1:B60FxaPHjR1SeQB0IiLrgwgvKsaoASfOWdiqhLjmMGA= -github.com/metacubex/sing-shadowsocks v0.2.11 h1:p2NGNOdF95e6XvdDKipLj1FRRqR8dnbfC/7pw2CCTlw= -github.com/metacubex/sing-shadowsocks v0.2.11/go.mod h1:bT1PCTV316zFnlToRMk5zt9HmIQYRBveiT71mplYPfc= -github.com/metacubex/sing-shadowsocks2 v0.2.5 h1:MnPn0hbcDkSJt6TlpI15XImHKK6IqaOwBUGPKyMnJnE= -github.com/metacubex/sing-shadowsocks2 v0.2.5/go.mod h1:Zyh+rAQRyevYfG/COCvDs1c/YMhGqCuknn7QrGmoQIw= +github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE= +github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU= +github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7kjgRdMm0SB98= +github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97 h1:YYpc60UZE2G0pUeHbRw9erDrUDZrPQy8QzWFqA3kHsk= -github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64= -github.com/metacubex/sing-vmess v0.2.3 h1:QKLdIk5A2FcR3Y7m2/JO1XhfzgDA8tF4W9/ffsH9opo= -github.com/metacubex/sing-vmess v0.2.3/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= +github.com/metacubex/sing-tun v0.4.7 h1:ZDY/W+1c7PeWWKeKRyUo18fySF/TWjB0i5ui81Ar778= +github.com/metacubex/sing-tun v0.4.7/go.mod h1:xHecZRwBnKWe6zG9amAK9cXf91lF6blgjBqm+VvOrmU= +github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 h1:WZepq4TOZa6WewB8tGAZrrL+bL2R2ivoBzuEgAeolWc= +github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113awp7P6odM2okB5s60HUyF0FMqKmo= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= -github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc= -github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= -github.com/metacubex/utls v1.8.0 h1:mSYi6FMnmc5riARl5UZDmWVy710z+P5b7xuGW0lV9ac= -github.com/metacubex/utls v1.8.0/go.mod h1:FdjYzVfCtgtna19hX0ER1Xsa5uJInwdQ4IcaaI98lEQ= -github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ= -github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y= +github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617 h1:yN3mQ4cT9sPUciw/rO0Isc/8QlO86DB6g9SEMRgQ8Cw= +github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= +github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142 h1:csEbKOzRAxJXffOeZnnS3/kA/F55JiTbKv5jcYqCXms= +github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142/go.mod h1:67I3skhEY4Sya8f1YxELwWPoeQdXqZCrWNYLvq8gn2U= +github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk= +github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f/go.mod h1:oPGcV994OGJedmmxrcK9+ni7jUEMGhR+uVQAdaduIP4= github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU= @@ -196,8 +196,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= +github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -279,5 +279,3 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= -lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/clash-meta-android/core/src/foss/golang/clash/hub/route/upgrade.go b/clash-meta-android/core/src/foss/golang/clash/hub/route/upgrade.go index 27679a9597..b2bcecd20a 100644 --- a/clash-meta-android/core/src/foss/golang/clash/hub/route/upgrade.go +++ b/clash-meta-android/core/src/foss/golang/clash/hub/route/upgrade.go @@ -32,7 +32,11 @@ func upgradeCore(w http.ResponseWriter, r *http.Request) { return } - err = updater.DefaultCoreUpdater.Update(execPath) + query := r.URL.Query() + channel := query.Get("channel") + force := query.Get("force") == "true" + + err = updater.DefaultCoreUpdater.Update(execPath, channel, force) if err != nil { log.Warnln("%s", err) render.Status(r, http.StatusInternalServerError) diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/anytls/server.go b/clash-meta-android/core/src/foss/golang/clash/listener/anytls/server.go index ae6af171e2..ccbc47a2c0 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/anytls/server.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/anytls/server.go @@ -7,9 +7,9 @@ import ( "errors" "net" "strings" + "sync/atomic" "github.com/metacubex/mihomo/adapter/inbound" - "github.com/metacubex/mihomo/common/atomic" "github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ech" @@ -31,7 +31,7 @@ type Listener struct { listeners []net.Listener tlsConfig *tlsC.Config userMap map[[32]byte]string - padding atomic.TypedValue[*padding.PaddingFactory] + padding atomic.Pointer[padding.PaddingFactory] } func New(config LC.AnyTLSServer, tunnel C.Tunnel, additions ...inbound.Addition) (sl *Listener, err error) { diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/config/vless.go b/clash-meta-android/core/src/foss/golang/clash/listener/config/vless.go index 52ee3754a9..135747da42 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/config/vless.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/config/vless.go @@ -17,6 +17,7 @@ type VlessServer struct { Enable bool Listen string Users []VlessUser + Decryption string WsPath string GrpcServiceName string Certificate string diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/inbound/common_test.go b/clash-meta-android/core/src/foss/golang/clash/listener/inbound/common_test.go index 5b8a6f17e6..79e382fa81 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/inbound/common_test.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/inbound/common_test.go @@ -1,6 +1,7 @@ package inbound_test import ( + "bytes" "context" "crypto/rand" "crypto/tls" @@ -10,16 +11,18 @@ import ( "net" "net/http" "net/netip" + "strconv" "sync" "testing" "time" N "github.com/metacubex/mihomo/common/net" + "github.com/metacubex/mihomo/common/pool" "github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/ech" - "github.com/metacubex/mihomo/component/generater" + "github.com/metacubex/mihomo/component/generator" tlsC "github.com/metacubex/mihomo/component/tls" C "github.com/metacubex/mihomo/constant" @@ -30,7 +33,7 @@ import ( ) var httpPath = "/inbound_test" -var httpData = make([]byte, 10240) +var httpData = make([]byte, 2*pool.RelayBufferSize) var remoteAddr = netip.MustParseAddr("1.2.3.4") var userUUID = utils.NewUUIDV4().String() var tlsCertificate, tlsPrivateKey, tlsFingerprint, _ = ca.NewRandomTLSKeyPair(ca.KeyPairTypeP256) @@ -46,13 +49,12 @@ var echConfigBase64, echKeyPem, _ = ech.GenECHConfig(echPublicSni) func init() { rand.Read(httpData) - privateKey, err := generater.GeneratePrivateKey() + privateKey, err := generator.GenX25519PrivateKey() if err != nil { panic(err) } - publicKey := privateKey.PublicKey() - realityPrivateKey = base64.RawURLEncoding.EncodeToString(privateKey[:]) - realityPublickey = base64.RawURLEncoding.EncodeToString(publicKey[:]) + realityPrivateKey = base64.RawURLEncoding.EncodeToString(privateKey.Bytes()) + realityPublickey = base64.RawURLEncoding.EncodeToString(privateKey.PublicKey().Bytes()) } type TestTunnel struct { @@ -134,14 +136,22 @@ func NewHttpTestTunnel() *TestTunnel { r := chi.NewRouter() r.Get(httpPath, func(w http.ResponseWriter, r *http.Request) { - render.Data(w, r, httpData) + query := r.URL.Query() + size, err := strconv.Atoi(query.Get("size")) + if err != nil { + render.Status(r, http.StatusBadRequest) + render.PlainText(w, r, err.Error()) + return + } + io.Copy(io.Discard, r.Body) + render.Data(w, r, httpData[:size]) }) h2Server := &http2.Server{} server := http.Server{Handler: r} _ = http2.ConfigureServer(&server, h2Server) go server.Serve(ln) - testFn := func(t *testing.T, proxy C.ProxyAdapter, proto string) { - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s://%s%s", proto, remoteAddr, httpPath), nil) + testFn := func(t *testing.T, proxy C.ProxyAdapter, proto string, size int) { + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s://%s%s?size=%d", proto, remoteAddr, httpPath, size), bytes.NewReader(httpData[:size])) if !assert.NoError(t, err) { return } @@ -200,7 +210,7 @@ func NewHttpTestTunnel() *TestTunnel { if !assert.NoError(t, err) { return } - assert.Equal(t, httpData, data) + assert.Equal(t, httpData[:size], data) } tunnel := &TestTunnel{ HandleTCPConnFn: func(conn net.Conn, metadata *C.Metadata) { @@ -241,27 +251,30 @@ func NewHttpTestTunnel() *TestTunnel { }, CloseFn: ln.Close, DoTestFn: func(t *testing.T, proxy C.ProxyAdapter) { + // Sequential testing for debugging t.Run("Sequential", func(t *testing.T) { - testFn(t, proxy, "http") - testFn(t, proxy, "https") + testFn(t, proxy, "http", len(httpData)) + testFn(t, proxy, "https", len(httpData)) }) // Concurrent testing to detect stress t.Run("Concurrent", func(t *testing.T) { wg := sync.WaitGroup{} - const num = 50 - for i := 0; i < num; i++ { + num := len(httpData) / 1024 + for i := 1; i <= num; i++ { + i := i wg.Add(1) go func() { - testFn(t, proxy, "https") + testFn(t, proxy, "https", i*1024) defer wg.Done() }() } - for i := 0; i < num; i++ { + for i := 1; i <= num; i++ { + i := i wg.Add(1) go func() { - testFn(t, proxy, "http") + testFn(t, proxy, "http", i*1024) defer wg.Done() }() } diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/inbound/mux_test.go b/clash-meta-android/core/src/foss/golang/clash/listener/inbound/mux_test.go index 4e676e6d96..a7c0208dd8 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/inbound/mux_test.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/inbound/mux_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" ) -var singMuxProtocolList = []string{"h2mux", "smux"} // don't test "yamux" because it has some confused bugs +var singMuxProtocolList = []string{"smux"} // don't test "h2mux" and "yamux" because it has some confused bugs // notCloseProxyAdapter is a proxy adapter that does not close the underlying outbound.ProxyAdapter. // The outbound.SingMux will close the underlying outbound.ProxyAdapter when it is closed, but we don't want to close it. diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/inbound/vless.go b/clash-meta-android/core/src/foss/golang/clash/listener/inbound/vless.go index 947e3a53e7..305df50ac8 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/inbound/vless.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/inbound/vless.go @@ -12,6 +12,7 @@ import ( type VlessOption struct { BaseOption Users []VlessUser `inbound:"users"` + Decryption string `inbound:"decryption,omitempty"` WsPath string `inbound:"ws-path,omitempty"` GrpcServiceName string `inbound:"grpc-service-name,omitempty"` Certificate string `inbound:"certificate,omitempty"` @@ -58,6 +59,7 @@ func NewVless(options *VlessOption) (*Vless, error) { Enable: true, Listen: base.RawAddress(), Users: users, + Decryption: options.Decryption, WsPath: options.WsPath, GrpcServiceName: options.GrpcServiceName, Certificate: options.Certificate, diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/inbound/vless_test.go b/clash-meta-android/core/src/foss/golang/clash/listener/inbound/vless_test.go index 1bec3d5574..9a7fed59eb 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/inbound/vless_test.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/inbound/vless_test.go @@ -7,6 +7,7 @@ import ( "github.com/metacubex/mihomo/adapter/outbound" "github.com/metacubex/mihomo/listener/inbound" + "github.com/metacubex/mihomo/transport/vless/encryption" "github.com/stretchr/testify/assert" ) @@ -87,6 +88,41 @@ func TestInboundVless_TLS(t *testing.T) { }) } +func TestInboundVless_Encryption(t *testing.T) { + seedBase64, clientBase64, _, err := encryption.GenMLKEM768("") + if err != nil { + t.Fatal(err) + return + } + privateKeyBase64, passwordBase64, _, err := encryption.GenX25519("") + if err != nil { + t.Fatal(err) + return + } + var modes = []string{ + "native", + "xorpub", + "random", + } + for i := range modes { + mode := modes[i] + t.Run(mode, func(t *testing.T) { + inboundOptions := inbound.VlessOption{ + Decryption: "mlkem768x25519plus." + mode + ".600s." + privateKeyBase64 + "." + seedBase64, + } + outboundOptions := outbound.VlessOption{ + Encryption: "mlkem768x25519plus." + mode + ".0rtt." + passwordBase64 + "." + clientBase64, + } + testInboundVless(t, inboundOptions, outboundOptions) + t.Run("xtls-rprx-vision", func(t *testing.T) { + outboundOptions := outboundOptions + outboundOptions.Flow = "xtls-rprx-vision" + testInboundVless(t, inboundOptions, outboundOptions) + }) + }) + } +} + func TestInboundVless_Wss1(t *testing.T) { inboundOptions := inbound.VlessOption{ Certificate: tlsCertificate, diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/reality/reality.go b/clash-meta-android/core/src/foss/golang/clash/listener/reality/reality.go index d91055f8ed..256dbcf6a9 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/reality/reality.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/reality/reality.go @@ -113,3 +113,11 @@ func (c realityConnWrapper) Upstream() any { func (c realityConnWrapper) CloseWrite() error { return c.Close() } + +func (c realityConnWrapper) ReaderReplaceable() bool { + return true +} + +func (c realityConnWrapper) WriterReplaceable() bool { + return true +} diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/sing/sing.go b/clash-meta-android/core/src/foss/golang/clash/listener/sing/sing.go index 2742da76d0..d2108fea6d 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/sing/sing.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/sing/sing.go @@ -16,6 +16,7 @@ import ( mux "github.com/metacubex/sing-mux" vmess "github.com/metacubex/sing-vmess" + "github.com/metacubex/sing-vmess/packetaddr" "github.com/metacubex/sing/common" "github.com/metacubex/sing/common/buf" "github.com/metacubex/sing/common/bufio" @@ -145,6 +146,10 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta } func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, metadata M.Metadata) error { + if metadata.Destination.Fqdn == packetaddr.SeqPacketMagicAddress { + conn = packetaddr.NewConn(bufio.NewNetPacketConn(conn), M.Socksaddr{}) + } + defer func() { _ = conn.Close() }() mutex := sync.Mutex{} writer := bufio.NewNetPacketWriter(conn) // a new interface to set nil in defer diff --git a/clash-meta-android/core/src/foss/golang/clash/listener/sing_vless/server.go b/clash-meta-android/core/src/foss/golang/clash/listener/sing_vless/server.go index 16aa1c654a..5280aa1376 100644 --- a/clash-meta-android/core/src/foss/golang/clash/listener/sing_vless/server.go +++ b/clash-meta-android/core/src/foss/golang/clash/listener/sing_vless/server.go @@ -19,16 +19,18 @@ import ( "github.com/metacubex/mihomo/listener/sing" "github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/transport/gun" + "github.com/metacubex/mihomo/transport/vless/encryption" mihomoVMess "github.com/metacubex/mihomo/transport/vmess" "github.com/metacubex/sing-vmess/vless" "github.com/metacubex/sing/common" "github.com/metacubex/sing/common/metadata" + "github.com/metacubex/sing/common/network" ) func init() { vless.RegisterTLS(func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer unsafe.Pointer) { - tlsConn, loaded := common.Cast[*reality.Conn](conn) // *utls.Conn + tlsConn, loaded := network.CastReader[*reality.Conn](conn) // *utls.Conn if !loaded { return } @@ -36,19 +38,28 @@ func init() { }) vless.RegisterTLS(func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer unsafe.Pointer) { - tlsConn, loaded := common.Cast[*tlsC.UConn](conn) // *utls.UConn + tlsConn, loaded := network.CastReader[*tlsC.UConn](conn) // *utls.UConn if !loaded { return } return true, tlsConn.NetConn(), reflect.TypeOf(tlsConn.Conn).Elem(), unsafe.Pointer(tlsConn.Conn) }) + + vless.RegisterTLS(func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer unsafe.Pointer) { + tlsConn, loaded := network.CastReader[*encryption.CommonConn](conn) + if !loaded { + return + } + return true, tlsConn.Conn, reflect.TypeOf(tlsConn).Elem(), unsafe.Pointer(tlsConn) + }) } type Listener struct { - closed bool - config LC.VlessServer - listeners []net.Listener - service *vless.Service[string] + closed bool + config LC.VlessServer + listeners []net.Listener + service *vless.Service[string] + decryption *encryption.ServerInstance } func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition) (sl *Listener, err error) { @@ -80,7 +91,20 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition) return it.Flow })) - sl = &Listener{false, config, nil, service} + sl = &Listener{config: config, service: service} + + sl.decryption, err = encryption.NewServer(config.Decryption) + if err != nil { + return nil, err + } + if sl.decryption != nil { + defer func() { // decryption must be closed to avoid the goroutine leak + if err != nil { + _ = sl.decryption.Close() + sl.decryption = nil + } + }() + } tlsConfig := &tlsC.Config{} var realityBuilder *reality.Builder @@ -149,8 +173,8 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition) } else { l = tlsC.NewListener(l, tlsConfig) } - } else { - return nil, errors.New("disallow using Vless without both certificates/reality config") + } else if sl.decryption == nil { + return nil, errors.New("disallow using Vless without any certificates/reality/decryption config") } sl.listeners = append(sl.listeners, l) @@ -185,6 +209,9 @@ func (l *Listener) Close() error { retErr = err } } + if l.decryption != nil { + _ = l.decryption.Close() + } return retErr } @@ -201,6 +228,13 @@ func (l *Listener) AddrList() (addrList []net.Addr) { func (l *Listener) HandleConn(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { ctx := sing.WithAdditions(context.TODO(), additions...) + if l.decryption != nil { + var err error + conn, err = l.decryption.Handshake(conn) + if err != nil { + return + } + } err := l.service.NewConnection(ctx, conn, metadata.Metadata{ Protocol: "vless", Source: metadata.SocksaddrFromNet(conn.RemoteAddr()), diff --git a/clash-meta-android/core/src/foss/golang/clash/main.go b/clash-meta-android/core/src/foss/golang/clash/main.go index 3bc3d74f73..6a85e5df79 100644 --- a/clash-meta-android/core/src/foss/golang/clash/main.go +++ b/clash-meta-android/core/src/foss/golang/clash/main.go @@ -14,7 +14,7 @@ import ( "strings" "syscall" - "github.com/metacubex/mihomo/component/generater" + "github.com/metacubex/mihomo/component/generator" "github.com/metacubex/mihomo/component/geodata" "github.com/metacubex/mihomo/component/updater" "github.com/metacubex/mihomo/config" @@ -73,7 +73,7 @@ func main() { } if len(os.Args) > 1 && os.Args[1] == "generate" { - generater.Main(os.Args[2:]) + generator.Main(os.Args[2:]) return } diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/anytls/client.go b/clash-meta-android/core/src/foss/golang/clash/transport/anytls/client.go index 44633ae345..4e74c9272c 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/anytls/client.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/anytls/client.go @@ -5,9 +5,9 @@ import ( "crypto/sha256" "encoding/binary" "net" + "sync/atomic" "time" - "github.com/metacubex/mihomo/common/atomic" "github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/transport/anytls/padding" "github.com/metacubex/mihomo/transport/anytls/session" @@ -33,7 +33,7 @@ type Client struct { dialer N.Dialer server M.Socksaddr sessionClient *session.Client - padding atomic.TypedValue[*padding.PaddingFactory] + padding atomic.Pointer[padding.PaddingFactory] } func NewClient(ctx context.Context, config ClientConfig) *Client { diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/anytls/padding/padding.go b/clash-meta-android/core/src/foss/golang/clash/transport/anytls/padding/padding.go index 498feb05c0..76b3c0ef91 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/anytls/padding/padding.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/anytls/padding/padding.go @@ -7,8 +7,8 @@ import ( "math/big" "strconv" "strings" + "sync/atomic" - "github.com/metacubex/mihomo/common/atomic" "github.com/metacubex/mihomo/transport/anytls/util" ) @@ -31,7 +31,7 @@ type PaddingFactory struct { Md5 string } -func UpdatePaddingScheme(rawScheme []byte, to *atomic.TypedValue[*PaddingFactory]) bool { +func UpdatePaddingScheme(rawScheme []byte, to *atomic.Pointer[PaddingFactory]) bool { if p := NewPaddingFactory(rawScheme); p != nil { to.Store(p) return true diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/anytls/session/client.go b/clash-meta-android/core/src/foss/golang/clash/transport/anytls/session/client.go index 50fd7b42ef..0698bd5006 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/anytls/session/client.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/anytls/session/client.go @@ -7,9 +7,9 @@ import ( "math" "net" "sync" + "sync/atomic" "time" - "github.com/metacubex/mihomo/common/atomic" "github.com/metacubex/mihomo/transport/anytls/padding" "github.com/metacubex/mihomo/transport/anytls/skiplist" "github.com/metacubex/mihomo/transport/anytls/util" @@ -29,13 +29,13 @@ type Client struct { sessions map[uint64]*Session sessionsLock sync.Mutex - padding *atomic.TypedValue[*padding.PaddingFactory] + padding *atomic.Pointer[padding.PaddingFactory] idleSessionTimeout time.Duration minIdleSession int } -func NewClient(ctx context.Context, dialOut util.DialOutFunc, _padding *atomic.TypedValue[*padding.PaddingFactory], idleSessionCheckInterval, idleSessionTimeout time.Duration, minIdleSession int) *Client { +func NewClient(ctx context.Context, dialOut util.DialOutFunc, _padding *atomic.Pointer[padding.PaddingFactory], idleSessionCheckInterval, idleSessionTimeout time.Duration, minIdleSession int) *Client { c := &Client{ sessions: make(map[uint64]*Session), dialOut: dialOut, diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/anytls/session/session.go b/clash-meta-android/core/src/foss/golang/clash/transport/anytls/session/session.go index c80639ce3b..23c3a087dc 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/anytls/session/session.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/anytls/session/session.go @@ -9,9 +9,9 @@ import ( "runtime/debug" "strconv" "sync" + "sync/atomic" "time" - "github.com/metacubex/mihomo/common/atomic" "github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/common/pool" "github.com/metacubex/mihomo/constant" @@ -38,7 +38,7 @@ type Session struct { // pool seq uint64 idleSince time.Time - padding *atomic.TypedValue[*padding.PaddingFactory] + padding *atomic.Pointer[padding.PaddingFactory] peerVersion byte @@ -53,7 +53,7 @@ type Session struct { onNewStream func(stream *Stream) } -func NewClientSession(conn net.Conn, _padding *atomic.TypedValue[*padding.PaddingFactory]) *Session { +func NewClientSession(conn net.Conn, _padding *atomic.Pointer[padding.PaddingFactory]) *Session { s := &Session{ conn: conn, isClient: true, @@ -65,7 +65,7 @@ func NewClientSession(conn net.Conn, _padding *atomic.TypedValue[*padding.Paddin return s } -func NewServerSession(conn net.Conn, onNewStream func(stream *Stream), _padding *atomic.TypedValue[*padding.PaddingFactory]) *Session { +func NewServerSession(conn net.Conn, onNewStream func(stream *Stream), _padding *atomic.Pointer[padding.PaddingFactory]) *Session { s := &Session{ conn: conn, onNewStream: onNewStream, diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/client.go b/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/client.go index 89f1eff66a..13c8db7502 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/client.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/client.go @@ -1,7 +1,6 @@ package core import ( - "bytes" "context" "errors" "fmt" @@ -16,7 +15,6 @@ import ( "github.com/metacubex/mihomo/transport/hysteria/transport" "github.com/metacubex/mihomo/transport/hysteria/utils" - "github.com/lunixbochs/struc" "github.com/metacubex/quic-go" "github.com/metacubex/quic-go/congestion" "github.com/metacubex/randv2" @@ -104,31 +102,23 @@ func (c *Client) connectToServer(dialer utils.PacketDialer) error { } func (c *Client) handleControlStream(qs *quic.Conn, stream *quic.Stream) (bool, string, error) { - // Send protocol version - _, err := stream.Write([]byte{protocolVersion}) - if err != nil { - return false, "", err - } // Send client hello - err = struc.Pack(stream, &clientHello{ - Rate: transmissionRate{ - SendBPS: c.sendBPS, - RecvBPS: c.recvBPS, - }, - Auth: c.auth, + err := WriteClientHello(stream, ClientHello{ + SendBPS: c.sendBPS, + RecvBPS: c.recvBPS, + Auth: c.auth, }) if err != nil { return false, "", err } // Receive server hello - var sh serverHello - err = struc.Unpack(stream, &sh) + sh, err := ReadServerHello(stream) if err != nil { return false, "", err } // Set the congestion accordingly if sh.OK && c.congestionFactory != nil { - qs.SetCongestionControl(c.congestionFactory(sh.Rate.RecvBPS)) + qs.SetCongestionControl(c.congestionFactory(sh.RecvBPS)) } return sh.OK, sh.Message, nil } @@ -140,7 +130,7 @@ func (c *Client) handleMessage(qs *quic.Conn) { break } var udpMsg udpMessage - err = struc.Unpack(bytes.NewBuffer(msg), &udpMsg) + err = udpMsg.Unpack(msg) if err != nil { continue } @@ -200,7 +190,7 @@ func (c *Client) DialTCP(host string, port uint16, dialer utils.PacketDialer) (n return nil, err } // Send request - err = struc.Pack(stream, &clientRequest{ + err = WriteClientRequest(stream, ClientRequest{ UDP: false, Host: host, Port: port, @@ -213,8 +203,8 @@ func (c *Client) DialTCP(host string, port uint16, dialer utils.PacketDialer) (n // and defer the response handling to the first Read() call if !c.fastOpen { // Read response - var sr serverResponse - err = struc.Unpack(stream, &sr) + var sr *ServerResponse + sr, err = ReadServerResponse(stream) if err != nil { _ = stream.Close() return nil, err @@ -239,16 +229,16 @@ func (c *Client) DialUDP(dialer utils.PacketDialer) (UDPConn, error) { return nil, err } // Send request - err = struc.Pack(stream, &clientRequest{ - UDP: true, + err = WriteClientRequest(stream, ClientRequest{ + UDP: false, }) if err != nil { _ = stream.Close() return nil, err } // Read response - var sr serverResponse - err = struc.Unpack(stream, &sr) + var sr *ServerResponse + sr, err = ReadServerResponse(stream) if err != nil { _ = stream.Close() return nil, err @@ -306,8 +296,8 @@ type quicConn struct { func (w *quicConn) Read(b []byte) (n int, err error) { if !w.Established { - var sr serverResponse - err := struc.Unpack(w.Orig, &sr) + var sr *ServerResponse + sr, err = ReadServerResponse(w.Orig) if err != nil { _ = w.Close() return 0, err @@ -401,9 +391,7 @@ func (c *quicPktConn) WriteTo(p []byte, addr string) error { Data: p, } // try no frag first - var msgBuf bytes.Buffer - _ = struc.Pack(&msgBuf, &msg) - err = c.Session.SendDatagram(msgBuf.Bytes()) + err = c.Session.SendDatagram(msg.Pack()) if err != nil { var errSize *quic.DatagramTooLargeError if errors.As(err, &errSize) { @@ -411,9 +399,7 @@ func (c *quicPktConn) WriteTo(p []byte, addr string) error { msg.MsgID = uint16(randv2.IntN(0xFFFF)) + 1 // msgID must be > 0 when fragCount > 1 fragMsgs := fragUDPMessage(msg, int(errSize.MaxDatagramPayloadSize)) for _, fragMsg := range fragMsgs { - msgBuf.Reset() - _ = struc.Pack(&msgBuf, &fragMsg) - err = c.Session.SendDatagram(msgBuf.Bytes()) + err = c.Session.SendDatagram(fragMsg.Pack()) if err != nil { return err } diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/frag.go b/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/frag.go index 7a38774768..fdcb1fd4a5 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/frag.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/frag.go @@ -18,7 +18,6 @@ func fragUDPMessage(m udpMessage, maxSize int) []udpMessage { frag := m frag.FragID = fragID frag.FragCount = fragCount - frag.DataLen = uint16(payloadSize) frag.Data = fullPayload[off : off+payloadSize] frags = append(frags, frag) off += payloadSize @@ -56,7 +55,6 @@ func (d *defragger) Feed(m udpMessage) *udpMessage { for _, frag := range d.frags { data = append(data, frag.Data...) } - m.DataLen = uint16(len(data)) m.Data = data m.FragID = 0 m.FragCount = 1 diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/frag_test.go b/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/frag_test.go index f2f246259e..f5c05cf399 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/frag_test.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/frag_test.go @@ -20,13 +20,11 @@ func Test_fragUDPMessage(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 0, FragCount: 1, - DataLen: 5, Data: []byte("hello"), }, 100, @@ -34,13 +32,11 @@ func Test_fragUDPMessage(t *testing.T) { []udpMessage{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 0, FragCount: 1, - DataLen: 5, Data: []byte("hello"), }, }, @@ -50,13 +46,11 @@ func Test_fragUDPMessage(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 0, FragCount: 1, - DataLen: 5, Data: []byte("hello"), }, 22, @@ -64,24 +58,20 @@ func Test_fragUDPMessage(t *testing.T) { []udpMessage{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 0, FragCount: 2, - DataLen: 4, Data: []byte("hell"), }, udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 1, FragCount: 2, - DataLen: 1, Data: []byte("o"), }, }, @@ -91,13 +81,11 @@ func Test_fragUDPMessage(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 0, FragCount: 1, - DataLen: 20, Data: []byte("wow wow wow lol lmao"), }, 23, @@ -105,46 +93,38 @@ func Test_fragUDPMessage(t *testing.T) { []udpMessage{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 0, FragCount: 4, - DataLen: 5, Data: []byte("wow w"), }, udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 1, FragCount: 4, - DataLen: 5, Data: []byte("ow wo"), }, udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 2, FragCount: 4, - DataLen: 5, Data: []byte("w lol"), }, udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 3, FragCount: 4, - DataLen: 5, Data: []byte(" lmao"), }, }, @@ -174,25 +154,21 @@ func Test_defragger_Feed(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 0, FragCount: 1, - DataLen: 5, Data: []byte("hello"), }, }, &udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 123, FragID: 0, FragCount: 1, - DataLen: 5, Data: []byte("hello"), }, }, @@ -201,13 +177,11 @@ func Test_defragger_Feed(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 666, FragID: 0, FragCount: 3, - DataLen: 5, Data: []byte("hello"), }, }, @@ -218,13 +192,11 @@ func Test_defragger_Feed(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 666, FragID: 1, FragCount: 3, - DataLen: 8, Data: []byte(" shitty "), }, }, @@ -235,25 +207,21 @@ func Test_defragger_Feed(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 666, FragID: 2, FragCount: 3, - DataLen: 7, Data: []byte("world!!"), }, }, &udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 666, FragID: 0, FragCount: 1, - DataLen: 20, Data: []byte("hello shitty world!!"), }, }, @@ -262,13 +230,11 @@ func Test_defragger_Feed(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 777, FragID: 0, FragCount: 2, - DataLen: 5, Data: []byte("hello"), }, }, @@ -279,13 +245,11 @@ func Test_defragger_Feed(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 778, FragID: 1, FragCount: 2, - DataLen: 5, Data: []byte(" moto"), }, }, @@ -296,13 +260,11 @@ func Test_defragger_Feed(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 777, FragID: 1, FragCount: 2, - DataLen: 5, Data: []byte(" moto"), }, }, @@ -313,25 +275,21 @@ func Test_defragger_Feed(t *testing.T) { args{ udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 777, FragID: 0, FragCount: 2, - DataLen: 5, Data: []byte("hello"), }, }, &udpMessage{ SessionID: 123, - HostLen: 4, Host: "test", Port: 123, MsgID: 777, FragID: 0, FragCount: 1, - DataLen: 10, Data: []byte("hello moto"), }, }, diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/protocol.go b/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/protocol.go index 7fd64d7cdc..77dfc2e580 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/protocol.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/hysteria/core/protocol.go @@ -1,60 +1,241 @@ package core import ( + "bytes" + "encoding/binary" + "errors" + "io" "time" ) const ( - protocolVersion = uint8(3) - protocolVersionV2 = uint8(2) - protocolTimeout = 10 * time.Second + protocolVersion = uint8(3) + protocolTimeout = 10 * time.Second closeErrorCodeGeneric = 0 closeErrorCodeProtocol = 1 closeErrorCodeAuth = 2 ) -type transmissionRate struct { +type ClientHello struct { SendBPS uint64 RecvBPS uint64 -} - -type clientHello struct { - Rate transmissionRate - AuthLen uint16 `struc:"sizeof=Auth"` Auth []byte } -type serverHello struct { - OK bool - Rate transmissionRate - MessageLen uint16 `struc:"sizeof=Message"` - Message string +func WriteClientHello(stream io.Writer, hello ClientHello) error { + var requestLen int + requestLen += 1 // version + requestLen += 8 // sendBPS + requestLen += 8 // recvBPS + requestLen += 2 // auth len + requestLen += len(hello.Auth) + request := make([]byte, requestLen) + request[0] = protocolVersion + binary.BigEndian.PutUint64(request[1:9], hello.SendBPS) + binary.BigEndian.PutUint64(request[9:17], hello.RecvBPS) + binary.BigEndian.PutUint16(request[17:19], uint16(len(hello.Auth))) + copy(request[19:], hello.Auth) + _, err := stream.Write(request) + return err } -type clientRequest struct { - UDP bool - HostLen uint16 `struc:"sizeof=Host"` - Host string - Port uint16 +func ReadClientHello(stream io.Reader) (*ClientHello, error) { + var responseLen int + responseLen += 1 // ok + responseLen += 8 // sendBPS + responseLen += 8 // recvBPS + responseLen += 2 // auth len + response := make([]byte, responseLen) + _, err := io.ReadFull(stream, response) + if err != nil { + return nil, err + } + + if response[0] != protocolVersion { + return nil, errors.New("unsupported client version") + } + var clientHello ClientHello + clientHello.SendBPS = binary.BigEndian.Uint64(response[1:9]) + clientHello.RecvBPS = binary.BigEndian.Uint64(response[9:17]) + authLen := binary.BigEndian.Uint16(response[17:19]) + + if clientHello.SendBPS == 0 || clientHello.RecvBPS == 0 { + return nil, errors.New("invalid rate from client") + } + + authBytes := make([]byte, authLen) + _, err = io.ReadFull(stream, authBytes) + if err != nil { + return nil, err + } + clientHello.Auth = authBytes + return &clientHello, nil } -type serverResponse struct { +type ServerHello struct { + OK bool + SendBPS uint64 + RecvBPS uint64 + Message string +} + +func ReadServerHello(stream io.Reader) (*ServerHello, error) { + var responseLen int + responseLen += 1 // ok + responseLen += 8 // sendBPS + responseLen += 8 // recvBPS + responseLen += 2 // message len + response := make([]byte, responseLen) + _, err := io.ReadFull(stream, response) + if err != nil { + return nil, err + } + var serverHello ServerHello + serverHello.OK = response[0] == 1 + serverHello.SendBPS = binary.BigEndian.Uint64(response[1:9]) + serverHello.RecvBPS = binary.BigEndian.Uint64(response[9:17]) + messageLen := binary.BigEndian.Uint16(response[17:19]) + if messageLen == 0 { + return &serverHello, nil + } + message := make([]byte, messageLen) + _, err = io.ReadFull(stream, message) + if err != nil { + return nil, err + } + serverHello.Message = string(message) + return &serverHello, nil +} + +func WriteServerHello(stream io.Writer, hello ServerHello) error { + var responseLen int + responseLen += 1 // ok + responseLen += 8 // sendBPS + responseLen += 8 // recvBPS + responseLen += 2 // message len + responseLen += len(hello.Message) + response := make([]byte, responseLen) + if hello.OK { + response[0] = 1 + } else { + response[0] = 0 + } + binary.BigEndian.PutUint64(response[1:9], hello.SendBPS) + binary.BigEndian.PutUint64(response[9:17], hello.RecvBPS) + binary.BigEndian.PutUint16(response[17:19], uint16(len(hello.Message))) + copy(response[19:], hello.Message) + _, err := stream.Write(response) + return err +} + +type ClientRequest struct { + UDP bool + Host string + Port uint16 +} + +func ReadClientRequest(stream io.Reader) (*ClientRequest, error) { + var clientRequest ClientRequest + err := binary.Read(stream, binary.BigEndian, &clientRequest.UDP) + if err != nil { + return nil, err + } + var hostLen uint16 + err = binary.Read(stream, binary.BigEndian, &hostLen) + if err != nil { + return nil, err + } + host := make([]byte, hostLen) + _, err = io.ReadFull(stream, host) + if err != nil { + return nil, err + } + clientRequest.Host = string(host) + err = binary.Read(stream, binary.BigEndian, &clientRequest.Port) + if err != nil { + return nil, err + } + return &clientRequest, nil +} + +func WriteClientRequest(stream io.Writer, request ClientRequest) error { + var requestLen int + requestLen += 1 // udp + requestLen += 2 // host len + requestLen += len(request.Host) + requestLen += 2 // port + buffer := make([]byte, requestLen) + if request.UDP { + buffer[0] = 1 + } else { + buffer[0] = 0 + } + binary.BigEndian.PutUint16(buffer[1:3], uint16(len(request.Host))) + n := copy(buffer[3:], request.Host) + binary.BigEndian.PutUint16(buffer[3+n:3+n+2], request.Port) + _, err := stream.Write(buffer) + return err +} + +type ServerResponse struct { OK bool UDPSessionID uint32 - MessageLen uint16 `struc:"sizeof=Message"` Message string } +func ReadServerResponse(stream io.Reader) (*ServerResponse, error) { + var responseLen int + responseLen += 1 // ok + responseLen += 4 // udp session id + responseLen += 2 // message len + response := make([]byte, responseLen) + _, err := io.ReadFull(stream, response) + if err != nil { + return nil, err + } + var serverResponse ServerResponse + serverResponse.OK = response[0] == 1 + serverResponse.UDPSessionID = binary.BigEndian.Uint32(response[1:5]) + messageLen := binary.BigEndian.Uint16(response[5:7]) + if messageLen == 0 { + return &serverResponse, nil + } + message := make([]byte, messageLen) + _, err = io.ReadFull(stream, message) + if err != nil { + return nil, err + } + serverResponse.Message = string(message) + return &serverResponse, nil +} + +func WriteServerResponse(stream io.Writer, response ServerResponse) error { + var responseLen int + responseLen += 1 // ok + responseLen += 4 // udp session id + responseLen += 2 // message len + responseLen += len(response.Message) + buffer := make([]byte, responseLen) + if response.OK { + buffer[0] = 1 + } else { + buffer[0] = 0 + } + binary.BigEndian.PutUint32(buffer[1:5], response.UDPSessionID) + binary.BigEndian.PutUint16(buffer[5:7], uint16(len(response.Message))) + copy(buffer[7:], response.Message) + _, err := stream.Write(buffer) + return err +} + type udpMessage struct { SessionID uint32 - HostLen uint16 `struc:"sizeof=Host"` Host string Port uint16 MsgID uint16 // doesn't matter when not fragmented, but must not be 0 when fragmented FragID uint8 // doesn't matter when not fragmented, starts at 0 when fragmented FragCount uint8 // must be 1 when not fragmented - DataLen uint16 `struc:"sizeof=Data"` Data []byte } @@ -66,11 +247,62 @@ func (m udpMessage) Size() int { return m.HeaderSize() + len(m.Data) } -type udpMessageV2 struct { - SessionID uint32 - HostLen uint16 `struc:"sizeof=Host"` - Host string - Port uint16 - DataLen uint16 `struc:"sizeof=Data"` - Data []byte +func (m udpMessage) Pack() []byte { + data := make([]byte, m.Size()) + buffer := bytes.NewBuffer(data) + _ = binary.Write(buffer, binary.BigEndian, m.SessionID) + _ = binary.Write(buffer, binary.BigEndian, uint16(len(m.Host))) + buffer.WriteString(m.Host) + _ = binary.Write(buffer, binary.BigEndian, m.Port) + _ = binary.Write(buffer, binary.BigEndian, m.MsgID) + _ = binary.Write(buffer, binary.BigEndian, m.FragID) + _ = binary.Write(buffer, binary.BigEndian, m.FragCount) + _ = binary.Write(buffer, binary.BigEndian, uint16(len(m.Data))) + buffer.Write(m.Data) + return buffer.Bytes() +} + +func (m *udpMessage) Unpack(data []byte) error { + reader := bytes.NewReader(data) + err := binary.Read(reader, binary.BigEndian, &m.SessionID) + if err != nil { + return err + } + var hostLen uint16 + err = binary.Read(reader, binary.BigEndian, &hostLen) + if err != nil { + return err + } + hostBytes := make([]byte, hostLen) + _, err = io.ReadFull(reader, hostBytes) + if err != nil { + return err + } + m.Host = string(hostBytes) + err = binary.Read(reader, binary.BigEndian, &m.Port) + if err != nil { + return err + } + err = binary.Read(reader, binary.BigEndian, &m.MsgID) + if err != nil { + return err + } + err = binary.Read(reader, binary.BigEndian, &m.FragID) + if err != nil { + return err + } + err = binary.Read(reader, binary.BigEndian, &m.FragCount) + if err != nil { + return err + } + var dataLen uint16 + err = binary.Read(reader, binary.BigEndian, &dataLen) + if err != nil { + return err + } + if reader.Len() != int(dataLen) { + return errors.New("invalid data length") + } + m.Data = data[len(data)-reader.Len():] + return nil } diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/restls/restls.go b/clash-meta-android/core/src/foss/golang/clash/transport/restls/restls.go index 95ac698907..200c9dad83 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/restls/restls.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/restls/restls.go @@ -4,7 +4,7 @@ import ( "context" "net" - tls "github.com/3andne/restls-client-go" + tls "github.com/metacubex/restls-client-go" ) const ( diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/tuic/v4/protocol.go b/clash-meta-android/core/src/foss/golang/clash/transport/tuic/v4/protocol.go index cb04fad595..bea1b2f3bb 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/tuic/v4/protocol.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/tuic/v4/protocol.go @@ -8,8 +8,8 @@ import ( "net/netip" "strconv" + "github.com/metacubex/blake3" "github.com/metacubex/quic-go" - "lukechampine.com/blake3" C "github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/transport/socks5" diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/conn.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/conn.go index 02224892e2..94ae71eee0 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/vless/conn.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/conn.go @@ -30,26 +30,22 @@ type Conn struct { } func (vc *Conn) Read(b []byte) (int, error) { - if vc.received { - return vc.ExtendedReader.Read(b) + if !vc.received { + if err := vc.recvResponse(); err != nil { + return 0, err + } + vc.received = true } - - if err := vc.recvResponse(); err != nil { - return 0, err - } - vc.received = true return vc.ExtendedReader.Read(b) } func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error { - if vc.received { - return vc.ExtendedReader.ReadBuffer(buffer) + if !vc.received { + if err := vc.recvResponse(); err != nil { + return err + } + vc.received = true } - - if err := vc.recvResponse(); err != nil { - return err - } - vc.received = true return vc.ExtendedReader.ReadBuffer(buffer) } @@ -105,26 +101,20 @@ func (vc *Conn) sendRequest(p []byte) bool { } } - var buffer *buf.Buffer - if vc.IsXTLSVisionEnabled() { - buffer = buf.New() - defer buffer.Release() - } else { - requestLen := 1 // protocol version - requestLen += 16 // UUID - requestLen += 1 // addons length - requestLen += len(addonsBytes) - requestLen += 1 // command - if !vc.dst.Mux { - requestLen += 2 // port - requestLen += 1 // addr type - requestLen += len(vc.dst.Addr) - } - requestLen += len(p) - - buffer = buf.NewSize(requestLen) - defer buffer.Release() + requestLen := 1 // protocol version + requestLen += 16 // UUID + requestLen += 1 // addons length + requestLen += len(addonsBytes) + requestLen += 1 // command + if !vc.dst.Mux { + requestLen += 2 // port + requestLen += 1 // addr type + requestLen += len(vc.dst.Addr) } + requestLen += len(p) + + buffer := buf.NewSize(requestLen) + defer buffer.Release() buf.Must( buffer.WriteByte(Version), // protocol version @@ -182,10 +172,6 @@ func (vc *Conn) NeedHandshake() bool { return vc.needHandshake } -func (vc *Conn) IsXTLSVisionEnabled() bool { - return vc.addons != nil && vc.addons.Flow == XRV -} - // newConn return a Conn instance func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) { c := &Conn{ @@ -200,7 +186,7 @@ func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) { if client.Addons != nil { switch client.Addons.Flow { case XRV: - visionConn, err := vision.NewConn(c, c.id) + visionConn, err := vision.NewConn(c, conn, c.id) if err != nil { return nil, err } diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/client.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/client.go new file mode 100644 index 0000000000..465f16260f --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/client.go @@ -0,0 +1,201 @@ +package encryption + +import ( + "crypto/cipher" + "crypto/ecdh" + "crypto/rand" + "errors" + "io" + "net" + "sync" + "time" + + "github.com/metacubex/blake3" + "github.com/metacubex/utls/mlkem" +) + +type ClientInstance struct { + NfsPKeys []any + NfsPKeysBytes [][]byte + Hash32s [][32]byte + RelaysLength int + XorMode uint32 + Seconds uint32 + + RWLock sync.RWMutex + Expire time.Time + PfsKey []byte + Ticket []byte +} + +func (i *ClientInstance) Init(nfsPKeysBytes [][]byte, xorMode, seconds uint32) (err error) { + if i.NfsPKeys != nil { + err = errors.New("already initialized") + return + } + l := len(nfsPKeysBytes) + if l == 0 { + err = errors.New("empty nfsPKeysBytes") + return + } + i.NfsPKeys = make([]any, l) + i.NfsPKeysBytes = nfsPKeysBytes + i.Hash32s = make([][32]byte, l) + for j, k := range nfsPKeysBytes { + if len(k) == 32 { + if i.NfsPKeys[j], err = ecdh.X25519().NewPublicKey(k); err != nil { + return + } + i.RelaysLength += 32 + 32 + } else { + if i.NfsPKeys[j], err = mlkem.NewEncapsulationKey768(k); err != nil { + return + } + i.RelaysLength += 1088 + 32 + } + i.Hash32s[j] = blake3.Sum256(k) + } + i.RelaysLength -= 32 + i.XorMode = xorMode + i.Seconds = seconds + return +} + +func (i *ClientInstance) Handshake(conn net.Conn) (*CommonConn, error) { + if i.NfsPKeys == nil { + return nil, errors.New("uninitialized") + } + c := &CommonConn{Conn: conn} + + ivAndRealysLength := 16 + i.RelaysLength + pfsKeyExchangeLength := 18 + 1184 + 32 + 16 + paddingLength := int(randBetween(100, 1000)) + clientHello := make([]byte, ivAndRealysLength+pfsKeyExchangeLength+paddingLength) + + iv := clientHello[:16] + rand.Read(iv) + relays := clientHello[16:ivAndRealysLength] + var nfsKey []byte + var lastCTR cipher.Stream + for j, k := range i.NfsPKeys { + var index = 32 + if k, ok := k.(*ecdh.PublicKey); ok { + privateKey, _ := ecdh.X25519().GenerateKey(rand.Reader) + copy(relays, privateKey.PublicKey().Bytes()) + var err error + nfsKey, err = privateKey.ECDH(k) + if err != nil { + return nil, err + } + } + if k, ok := k.(*mlkem.EncapsulationKey768); ok { + var ciphertext []byte + nfsKey, ciphertext = k.Encapsulate() + copy(relays, ciphertext) + index = 1088 + } + if i.XorMode > 0 { // this xor can (others can't) be recovered by client's config, revealing an X25519 public key / ML-KEM-768 ciphertext, that's why "native" values + NewCTR(i.NfsPKeysBytes[j], iv).XORKeyStream(relays, relays[:index]) // make X25519 public key / ML-KEM-768 ciphertext distinguishable from random bytes + } + if lastCTR != nil { + lastCTR.XORKeyStream(relays, relays[:32]) // make this relay irreplaceable + } + if j == len(i.NfsPKeys)-1 { + break + } + lastCTR = NewCTR(nfsKey, iv) + lastCTR.XORKeyStream(relays[index:], i.Hash32s[j+1][:]) + relays = relays[index+32:] + } + nfsGCM := NewGCM(iv, nfsKey) + + if i.Seconds > 0 { + i.RWLock.RLock() + if time.Now().Before(i.Expire) { + c.Client = i + c.UnitedKey = append(i.PfsKey, nfsKey...) // different unitedKey for each connection + nfsGCM.Seal(clientHello[:ivAndRealysLength], nil, EncodeLength(32), nil) + nfsGCM.Seal(clientHello[:ivAndRealysLength+18], nil, i.Ticket, nil) + i.RWLock.RUnlock() + c.PreWrite = clientHello[:ivAndRealysLength+18+32] + c.GCM = NewGCM(clientHello[ivAndRealysLength+18:ivAndRealysLength+18+32], c.UnitedKey) + if i.XorMode == 2 { + c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, iv), nil, len(c.PreWrite), 16) + } + return c, nil + } + i.RWLock.RUnlock() + } + + pfsKeyExchange := clientHello[ivAndRealysLength : ivAndRealysLength+pfsKeyExchangeLength] + nfsGCM.Seal(pfsKeyExchange[:0], nil, EncodeLength(pfsKeyExchangeLength-18), nil) + mlkem768DKey, _ := mlkem.GenerateKey768() + x25519SKey, _ := ecdh.X25519().GenerateKey(rand.Reader) + pfsPublicKey := append(mlkem768DKey.EncapsulationKey().Bytes(), x25519SKey.PublicKey().Bytes()...) + nfsGCM.Seal(pfsKeyExchange[:18], nil, pfsPublicKey, nil) + + padding := clientHello[ivAndRealysLength+pfsKeyExchangeLength:] + nfsGCM.Seal(padding[:0], nil, EncodeLength(paddingLength-18), nil) + nfsGCM.Seal(padding[:18], nil, padding[18:paddingLength-16], nil) + + if _, err := conn.Write(clientHello); err != nil { + return nil, err + } + // padding can be sent in a fragmented way, to create variable traffic pattern, before inner VLESS flow takes control + + encryptedPfsPublicKey := make([]byte, 1088+32+16) + if _, err := io.ReadFull(conn, encryptedPfsPublicKey); err != nil { + return nil, err + } + nfsGCM.Open(encryptedPfsPublicKey[:0], MaxNonce, encryptedPfsPublicKey, nil) + mlkem768Key, err := mlkem768DKey.Decapsulate(encryptedPfsPublicKey[:1088]) + if err != nil { + return nil, err + } + peerX25519PKey, err := ecdh.X25519().NewPublicKey(encryptedPfsPublicKey[1088 : 1088+32]) + if err != nil { + return nil, err + } + x25519Key, err := x25519SKey.ECDH(peerX25519PKey) + if err != nil { + return nil, err + } + pfsKey := make([]byte, 32+32) // no more capacity + copy(pfsKey, mlkem768Key) + copy(pfsKey[32:], x25519Key) + c.UnitedKey = append(pfsKey, nfsKey...) + c.GCM = NewGCM(pfsPublicKey, c.UnitedKey) + c.PeerGCM = NewGCM(encryptedPfsPublicKey[:1088+32], c.UnitedKey) + + encryptedTicket := make([]byte, 32) + if _, err := io.ReadFull(conn, encryptedTicket); err != nil { + return nil, err + } + if _, err := c.PeerGCM.Open(encryptedTicket[:0], nil, encryptedTicket, nil); err != nil { + return nil, err + } + seconds := DecodeLength(encryptedTicket) + + if i.Seconds > 0 && seconds > 0 { + i.RWLock.Lock() + i.Expire = time.Now().Add(time.Duration(seconds) * time.Second) + i.PfsKey = pfsKey + i.Ticket = encryptedTicket[:16] + i.RWLock.Unlock() + } + + encryptedLength := make([]byte, 18) + if _, err := io.ReadFull(conn, encryptedLength); err != nil { + return nil, err + } + if _, err := c.PeerGCM.Open(encryptedLength[:0], nil, encryptedLength, nil); err != nil { + return nil, err + } + length := DecodeLength(encryptedLength[:2]) + c.PeerPadding = make([]byte, length) // important: allows server sends padding slowly, eliminating 1-RTT's traffic pattern + + if i.XorMode == 2 { + c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, iv), NewCTR(c.UnitedKey, encryptedTicket[:16]), 0, length) + } + return c, nil +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/common.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/common.go new file mode 100644 index 0000000000..1b2aa18201 --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/common.go @@ -0,0 +1,220 @@ +package encryption + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "errors" + "fmt" + "io" + "math/big" + "net" + "strings" + "time" + + "github.com/metacubex/blake3" +) + +type CommonConn struct { + net.Conn + Client *ClientInstance + UnitedKey []byte + PreWrite []byte + GCM *GCM + PeerPadding []byte + PeerGCM *GCM + input bytes.Reader // PeerCache +} + +func (c *CommonConn) Write(b []byte) (int, error) { + if len(b) == 0 { + return 0, nil + } + var data []byte + for n := 0; n < len(b); { + b := b[n:] + if len(b) > 8192 { + b = b[:8192] // for avoiding another copy() in peer's Read() + } + n += len(b) + data = make([]byte, 5+len(b)+16) + EncodeHeader(data, len(b)+16) + max := false + if bytes.Equal(c.GCM.Nonce[:], MaxNonce) { + max = true + } + c.GCM.Seal(data[:5], nil, b, data[:5]) + if max { + c.GCM = NewGCM(data[5:], c.UnitedKey) + } + if c.PreWrite != nil { + data = append(c.PreWrite, data...) + c.PreWrite = nil + } + if _, err := c.Conn.Write(data); err != nil { + return 0, err + } + } + return len(b), nil +} + +func (c *CommonConn) Read(b []byte) (int, error) { + if len(b) == 0 { + return 0, nil + } + if c.PeerGCM == nil { // client's 0-RTT + serverRandom := make([]byte, 16) + if _, err := io.ReadFull(c.Conn, serverRandom); err != nil { + return 0, err + } + c.PeerGCM = NewGCM(serverRandom, c.UnitedKey) + if xorConn, ok := c.Conn.(*XorConn); ok { + xorConn.PeerCTR = NewCTR(c.UnitedKey, serverRandom) + } + } + if c.PeerPadding != nil { // client's 1-RTT + if _, err := io.ReadFull(c.Conn, c.PeerPadding); err != nil { + return 0, err + } + if _, err := c.PeerGCM.Open(c.PeerPadding[:0], nil, c.PeerPadding, nil); err != nil { + return 0, err + } + c.PeerPadding = nil + } + if c.input.Len() > 0 { + return c.input.Read(b) + } + h, l, err := ReadAndDecodeHeader(c.Conn) // l: 17~17000 + if err != nil { + if c.Client != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // client's 0-RTT + c.Client.RWLock.Lock() + if bytes.HasPrefix(c.UnitedKey, c.Client.PfsKey) { + c.Client.Expire = time.Now() // expired + } + c.Client.RWLock.Unlock() + return 0, errors.New("new handshake needed") + } + return 0, err + } + c.Client = nil + peerData := make([]byte, l) + if _, err := io.ReadFull(c.Conn, peerData); err != nil { + return 0, err + } + dst := peerData[:l-16] + if len(dst) <= len(b) { + dst = b[:len(dst)] // avoids another copy() + } + var newGCM *GCM + if bytes.Equal(c.PeerGCM.Nonce[:], MaxNonce) { + newGCM = NewGCM(peerData, c.UnitedKey) + } + _, err = c.PeerGCM.Open(dst[:0], nil, peerData, h) + if newGCM != nil { + c.PeerGCM = newGCM + } + if err != nil { + return 0, err + } + if len(dst) > len(b) { + c.input.Reset(dst[copy(b, dst):]) + dst = b // for len(dst) + } + return len(dst), nil +} + +type GCM struct { + cipher.AEAD + Nonce [12]byte +} + +func NewGCM(ctx, key []byte) *GCM { + k := make([]byte, 32) + blake3.DeriveKey(k, string(ctx), key) + block, _ := aes.NewCipher(k) + aead, _ := cipher.NewGCM(block) + return &GCM{AEAD: aead} + //chacha20poly1305.New() +} + +func (a *GCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if nonce == nil { + nonce = IncreaseNonce(a.Nonce[:]) + } + return a.AEAD.Seal(dst, nonce, plaintext, additionalData) +} + +func (a *GCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if nonce == nil { + nonce = IncreaseNonce(a.Nonce[:]) + } + return a.AEAD.Open(dst, nonce, ciphertext, additionalData) +} + +func IncreaseNonce(nonce []byte) []byte { + for i := 0; i < 12; i++ { + nonce[11-i]++ + if nonce[11-i] != 0 { + break + } + } + return nonce +} + +var MaxNonce = bytes.Repeat([]byte{255}, 12) + +func EncodeLength(l int) []byte { + return []byte{byte(l >> 8), byte(l)} +} + +func DecodeLength(b []byte) int { + return int(b[0])<<8 | int(b[1]) +} + +func EncodeHeader(h []byte, l int) { + h[0] = 23 + h[1] = 3 + h[2] = 3 + h[3] = byte(l >> 8) + h[4] = byte(l) +} + +func DecodeHeader(h []byte) (l int, err error) { + l = int(h[3])<<8 | int(h[4]) + if h[0] != 23 || h[1] != 3 || h[2] != 3 { + l = 0 + } + if l < 17 || l > 17000 { // TODO: TLSv1.3 max length + err = fmt.Errorf("invalid header: %v", h[:5]) // DO NOT CHANGE: relied by client's Read() + } + return +} + +func ReadAndDecodeHeader(conn net.Conn) (h []byte, l int, err error) { + h = make([]byte, 5) + if _, err = io.ReadFull(conn, h); err != nil { + return + } + l, err = DecodeHeader(h) + return +} + +func ReadAndDiscardPaddings(conn net.Conn) (h []byte, l int, err error) { + for { + if h, l, err = ReadAndDecodeHeader(conn); err != nil { + return + } + if _, err = io.ReadFull(conn, make([]byte, l)); err != nil { + return + } + } +} + +func randBetween(from int64, to int64) int64 { + if from == to { + return from + } + bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from)) + return from + bigInt.Int64() +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/doc.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/doc.go new file mode 100644 index 0000000000..177839c64a --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/doc.go @@ -0,0 +1,23 @@ +// Package encryption copy and modify from xray-core +// https://github.com/XTLS/Xray-core/commit/f61c14e9c63dc41a8a09135db3aea337974f3f37 +// https://github.com/XTLS/Xray-core/commit/3e19bf9233bdd9bafc073a71c65b737cc1ffba5e +// https://github.com/XTLS/Xray-core/commit/7ffb555fc8ec51bd1e3e60f26f1d6957984dba80 +// https://github.com/XTLS/Xray-core/commit/ec1cc35188c1a5f38a2ff75e88b5d043ffdc59da +// https://github.com/XTLS/Xray-core/commit/5c611420487a92f931faefc01d4bf03869f477f6 +// https://github.com/XTLS/Xray-core/commit/23d7aad461d232bc5bed52dd6aaa731ecd88ad35 +// https://github.com/XTLS/Xray-core/commit/3c20bddfcfd8999be5f9a2ac180dc959950e4c61 +// https://github.com/XTLS/Xray-core/commit/1720be168fa069332c418503d30341fc6e01df7f +// https://github.com/XTLS/Xray-core/commit/0fd7691d6b28e05922d7a5a9313d97745a51ea63 +// https://github.com/XTLS/Xray-core/commit/09cc92c61d9067e0d65c1cae9124664ecfc78f43 +// https://github.com/XTLS/Xray-core/commit/2807ee432a1fbeb301815647189eacd650b12a8b +// https://github.com/XTLS/Xray-core/commit/bfe4820f2f086daf639b1957eb23dc13c843cad1 +// https://github.com/XTLS/Xray-core/commit/d1fb48521271251a8c74bd64fcc2fc8700717a3b +// https://github.com/XTLS/Xray-core/commit/49580705f6029648399304b816a2737f991582a8 +// https://github.com/XTLS/Xray-core/commit/84835bec7d0d8555d0dd30953ed26a272de814c4 +// https://github.com/XTLS/Xray-core/commit/373558ed7abdbac3de41745cf30ec04c9adde604 +// https://github.com/XTLS/Xray-core/commit/38cc306c955c362f044e074049a5e67b6b9fb389 +// https://github.com/XTLS/Xray-core/commit/b33555cc0a52d0af3c23d2af8fca42f8a685d9af +// https://github.com/XTLS/Xray-core/commit/ad7140641c44239c9dcdc3d7215ea639b1f0841c +// https://github.com/XTLS/Xray-core/commit/0199dea39988a1a1b846d0bf8598631bade40902 +// https://github.com/XTLS/Xray-core/commit/fce1195b60f48ca18a953dbd5c7d991869de9a5e +package encryption diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/factory.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/factory.go new file mode 100644 index 0000000000..c344fbf1b1 --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/factory.go @@ -0,0 +1,104 @@ +package encryption + +import ( + "encoding/base64" + "fmt" + "strconv" + "strings" +) + +// NewClient new client from encryption string +// maybe return a nil *ClientInstance without any error, that means don't need to encrypt +func NewClient(encryption string) (*ClientInstance, error) { + switch encryption { + case "", "none": // We will not reject empty string like xray-core does, because we need to ensure compatibility + return nil, nil + } + if s := strings.Split(encryption, "."); len(s) >= 4 && s[0] == "mlkem768x25519plus" { + var xorMode uint32 + switch s[1] { + case "native": + case "xorpub": + xorMode = 1 + case "random": + xorMode = 2 + default: + return nil, fmt.Errorf("invaild vless encryption value: %s", encryption) + } + var seconds uint32 + switch s[2] { + case "1rtt": + case "0rtt": + seconds = 1 + default: + return nil, fmt.Errorf("invaild vless encryption value: %s", encryption) + } + var nfsPKeysBytes [][]byte + for _, r := range s[3:] { + b, err := base64.RawURLEncoding.DecodeString(r) + if err != nil { + return nil, fmt.Errorf("invaild vless encryption value: %s", encryption) + } + if len(b) != X25519PasswordSize && len(b) != MLKEM768ClientLength { + return nil, fmt.Errorf("invaild vless encryption value: %s", encryption) + } + nfsPKeysBytes = append(nfsPKeysBytes, b) + } + client := &ClientInstance{} + if err := client.Init(nfsPKeysBytes, xorMode, seconds); err != nil { + return nil, fmt.Errorf("failed to use encryption: %w", err) + } + return client, nil + } + return nil, fmt.Errorf("invaild vless encryption value: %s", encryption) +} + +// NewServer new server from decryption string +// maybe return a nil *ServerInstance without any error, that means don't need to decrypt +func NewServer(decryption string) (*ServerInstance, error) { + switch decryption { + case "", "none": // We will not reject empty string like xray-core does, because we need to ensure compatibility + return nil, nil + } + if s := strings.Split(decryption, "."); len(s) >= 4 && s[0] == "mlkem768x25519plus" { + var xorMode uint32 + switch s[1] { + case "native": + case "xorpub": + xorMode = 1 + case "random": + xorMode = 2 + default: + return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) + } + var seconds uint32 + if s[2] != "1rtt" { + t := strings.TrimSuffix(s[2], "s") + if t == s[0] { + return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) + } + i, err := strconv.Atoi(t) + if err != nil { + return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) + } + seconds = uint32(i) + } + var nfsSKeysBytes [][]byte + for _, r := range s[3:] { + b, err := base64.RawURLEncoding.DecodeString(r) + if err != nil { + return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) + } + if len(b) != X25519PrivateKeySize && len(b) != MLKEM768SeedLength { + return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) + } + nfsSKeysBytes = append(nfsSKeysBytes, b) + } + server := &ServerInstance{} + if err := server.Init(nfsSKeysBytes, xorMode, seconds); err != nil { + return nil, fmt.Errorf("failed to use decryption: %w", err) + } + return server, nil + } + return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/key.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/key.go new file mode 100644 index 0000000000..af9ac03379 --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/key.go @@ -0,0 +1,79 @@ +package encryption + +import ( + "crypto/ecdh" + "crypto/rand" + "encoding/base64" + "fmt" + + "github.com/metacubex/blake3" + "github.com/metacubex/utls/mlkem" +) + +const MLKEM768SeedLength = mlkem.SeedSize +const MLKEM768ClientLength = mlkem.EncapsulationKeySize768 +const X25519PasswordSize = 32 +const X25519PrivateKeySize = 32 + +func GenMLKEM768(seedStr string) (seedBase64, clientBase64, hash32Base64 string, err error) { + var seed [MLKEM768SeedLength]byte + if len(seedStr) > 0 { + s, _ := base64.RawURLEncoding.DecodeString(seedStr) + if len(s) != MLKEM768SeedLength { + err = fmt.Errorf("invalid length of ML-KEM-768 seed: %s", seedStr) + return + } + seed = [MLKEM768SeedLength]byte(s) + } else { + _, err = rand.Read(seed[:]) + if err != nil { + return + } + } + + key, _ := mlkem.NewDecapsulationKey768(seed[:]) + client := key.EncapsulationKey().Bytes() + hash32 := blake3.Sum256(client) + seedBase64 = base64.RawURLEncoding.EncodeToString(seed[:]) + clientBase64 = base64.RawURLEncoding.EncodeToString(client) + hash32Base64 = base64.RawURLEncoding.EncodeToString(hash32[:]) + return +} + +func GenX25519(privateKeyStr string) (privateKeyBase64, passwordBase64, hash32Base64 string, err error) { + var privateKey [X25519PrivateKeySize]byte + if len(privateKeyStr) > 0 { + s, _ := base64.RawURLEncoding.DecodeString(privateKeyStr) + if len(s) != X25519PrivateKeySize { + err = fmt.Errorf("invalid length of X25519 private key: %s", privateKeyStr) + return + } + privateKey = [X25519PrivateKeySize]byte(s) + } else { + _, err = rand.Read(privateKey[:]) + if err != nil { + return + } + } + + // Avoid generating equivalent X25519 private keys + // https://github.com/XTLS/Xray-core/pull/1747 + // + // Modify random bytes using algorithm described at: + // https://cr.yp.to/ecdh.html. + privateKey[0] &= 248 + privateKey[31] &= 127 + privateKey[31] |= 64 + + key, err := ecdh.X25519().NewPrivateKey(privateKey[:]) + if err != nil { + fmt.Println(err.Error()) + return + } + password := key.PublicKey().Bytes() + hash32 := blake3.Sum256(password) + privateKeyBase64 = base64.RawURLEncoding.EncodeToString(privateKey[:]) + passwordBase64 = base64.RawURLEncoding.EncodeToString(password) + hash32Base64 = base64.RawURLEncoding.EncodeToString(hash32[:]) + return +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/server.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/server.go new file mode 100644 index 0000000000..36ce399ab5 --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/server.go @@ -0,0 +1,281 @@ +package encryption + +import ( + "bytes" + "crypto/cipher" + "crypto/ecdh" + "crypto/rand" + "errors" + "fmt" + "io" + "net" + "sync" + "time" + + "github.com/metacubex/blake3" + "github.com/metacubex/utls/mlkem" +) + +type ServerSession struct { + Expire time.Time + PfsKey []byte + NfsKeys sync.Map +} + +type ServerInstance struct { + NfsSKeys []any + NfsPKeysBytes [][]byte + Hash32s [][32]byte + RelaysLength int + XorMode uint32 + Seconds uint32 + + RWLock sync.RWMutex + Sessions map[[16]byte]*ServerSession + Closed bool +} + +func (i *ServerInstance) Init(nfsSKeysBytes [][]byte, xorMode, seconds uint32) (err error) { + if i.NfsSKeys != nil { + err = errors.New("already initialized") + return + } + l := len(nfsSKeysBytes) + if l == 0 { + err = errors.New("empty nfsSKeysBytes") + return + } + i.NfsSKeys = make([]any, l) + i.NfsPKeysBytes = make([][]byte, l) + i.Hash32s = make([][32]byte, l) + for j, k := range nfsSKeysBytes { + if len(k) == 32 { + if i.NfsSKeys[j], err = ecdh.X25519().NewPrivateKey(k); err != nil { + return + } + i.NfsPKeysBytes[j] = i.NfsSKeys[j].(*ecdh.PrivateKey).PublicKey().Bytes() + i.RelaysLength += 32 + 32 + } else { + if i.NfsSKeys[j], err = mlkem.NewDecapsulationKey768(k); err != nil { + return + } + i.NfsPKeysBytes[j] = i.NfsSKeys[j].(*mlkem.DecapsulationKey768).EncapsulationKey().Bytes() + i.RelaysLength += 1088 + 32 + } + i.Hash32s[j] = blake3.Sum256(i.NfsPKeysBytes[j]) + } + i.RelaysLength -= 32 + i.XorMode = xorMode + if seconds > 0 { + i.Seconds = seconds + i.Sessions = make(map[[16]byte]*ServerSession) + go func() { + for { + time.Sleep(time.Minute) + i.RWLock.Lock() + if i.Closed { + i.RWLock.Unlock() + return + } + now := time.Now() + for ticket, session := range i.Sessions { + if now.After(session.Expire) { + delete(i.Sessions, ticket) + } + } + i.RWLock.Unlock() + } + }() + } + return +} + +func (i *ServerInstance) Close() (err error) { + i.RWLock.Lock() + i.Closed = true + i.RWLock.Unlock() + return +} + +func (i *ServerInstance) Handshake(conn net.Conn) (*CommonConn, error) { + if i.NfsSKeys == nil { + return nil, errors.New("uninitialized") + } + c := &CommonConn{Conn: conn} + + ivAndRelays := make([]byte, 16+i.RelaysLength) + if _, err := io.ReadFull(conn, ivAndRelays); err != nil { + return nil, err + } + iv := ivAndRelays[:16] + relays := ivAndRelays[16:] + var nfsKey []byte + var lastCTR cipher.Stream + for j, k := range i.NfsSKeys { + if lastCTR != nil { + lastCTR.XORKeyStream(relays, relays[:32]) // recover this relay + } + var index = 32 + if _, ok := k.(*mlkem.DecapsulationKey768); ok { + index = 1088 + } + if i.XorMode > 0 { + NewCTR(i.NfsPKeysBytes[j], iv).XORKeyStream(relays, relays[:index]) // we don't use buggy elligator, because we have PSK :) + } + if k, ok := k.(*ecdh.PrivateKey); ok { + publicKey, err := ecdh.X25519().NewPublicKey(relays[:index]) + if err != nil { + return nil, err + } + nfsKey, err = k.ECDH(publicKey) + if err != nil { + return nil, err + } + } + if k, ok := k.(*mlkem.DecapsulationKey768); ok { + var err error + nfsKey, err = k.Decapsulate(relays[:index]) + if err != nil { + return nil, err + } + } + if j == len(i.NfsSKeys)-1 { + break + } + relays = relays[index:] + lastCTR = NewCTR(nfsKey, iv) + lastCTR.XORKeyStream(relays, relays[:32]) + if !bytes.Equal(relays[:32], i.Hash32s[j+1][:]) { + return nil, fmt.Errorf("unexpected hash32: %v", relays[:32]) + } + relays = relays[32:] + } + nfsGCM := NewGCM(iv, nfsKey) + + encryptedLength := make([]byte, 18) + if _, err := io.ReadFull(conn, encryptedLength); err != nil { + return nil, err + } + if _, err := nfsGCM.Open(encryptedLength[:0], nil, encryptedLength, nil); err != nil { + return nil, err + } + length := DecodeLength(encryptedLength[:2]) + + if length == 32 { + if i.Seconds == 0 { + return nil, errors.New("0-RTT is not allowed") + } + encryptedTicket := make([]byte, 32) + if _, err := io.ReadFull(conn, encryptedTicket); err != nil { + return nil, err + } + ticket, err := nfsGCM.Open(nil, nil, encryptedTicket, nil) + if err != nil { + return nil, err + } + i.RWLock.RLock() + s := i.Sessions[[16]byte(ticket)] + i.RWLock.RUnlock() + if s == nil { + noises := make([]byte, randBetween(1268, 2268)) // matches 1-RTT's server hello length for "random", though it is not important, just for example + var err error + for err == nil { + rand.Read(noises) + _, err = DecodeHeader(noises) + } + conn.Write(noises) // make client do new handshake + return nil, errors.New("expired ticket") + } + if _, loaded := s.NfsKeys.LoadOrStore([32]byte(nfsKey), true); loaded { // prevents bad client also + return nil, errors.New("replay detected") + } + c.UnitedKey = append(s.PfsKey, nfsKey...) // the same nfsKey links the upload & download (prevents server -> client's another request) + c.PreWrite = make([]byte, 16) + rand.Read(c.PreWrite) // always trust yourself, not the client (also prevents being parsed as TLS thus causing false interruption for "native" and "xorpub") + c.GCM = NewGCM(c.PreWrite, c.UnitedKey) + c.PeerGCM = NewGCM(encryptedTicket, c.UnitedKey) // unchangeable ctx (prevents server -> server), and different ctx length for upload / download (prevents client -> client) + if i.XorMode == 2 { + c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, c.PreWrite), NewCTR(c.UnitedKey, iv), 16, 0) // it doesn't matter if the attacker sends client's iv back to the client + } + return c, nil + } + + if length < 1184+32+16 { // client may send more public keys in the future's version + return nil, errors.New("too short length") + } + encryptedPfsPublicKey := make([]byte, length) + if _, err := io.ReadFull(conn, encryptedPfsPublicKey); err != nil { + return nil, err + } + if _, err := nfsGCM.Open(encryptedPfsPublicKey[:0], nil, encryptedPfsPublicKey, nil); err != nil { + return nil, err + } + mlkem768EKey, err := mlkem.NewEncapsulationKey768(encryptedPfsPublicKey[:1184]) + if err != nil { + return nil, err + } + mlkem768Key, encapsulatedPfsKey := mlkem768EKey.Encapsulate() + peerX25519PKey, err := ecdh.X25519().NewPublicKey(encryptedPfsPublicKey[1184 : 1184+32]) + if err != nil { + return nil, err + } + x25519SKey, _ := ecdh.X25519().GenerateKey(rand.Reader) + x25519Key, err := x25519SKey.ECDH(peerX25519PKey) + if err != nil { + return nil, err + } + pfsKey := make([]byte, 32+32) // no more capacity + copy(pfsKey, mlkem768Key) + copy(pfsKey[32:], x25519Key) + pfsPublicKey := append(encapsulatedPfsKey, x25519SKey.PublicKey().Bytes()...) + c.UnitedKey = append(pfsKey, nfsKey...) + c.GCM = NewGCM(pfsPublicKey, c.UnitedKey) + c.PeerGCM = NewGCM(encryptedPfsPublicKey[:1184+32], c.UnitedKey) + ticket := make([]byte, 16) + rand.Read(ticket) + copy(ticket, EncodeLength(int(i.Seconds*4/5))) + + pfsKeyExchangeLength := 1088 + 32 + 16 + encryptedTicketLength := 32 + paddingLength := int(randBetween(100, 1000)) + serverHello := make([]byte, pfsKeyExchangeLength+encryptedTicketLength+paddingLength) + nfsGCM.Seal(serverHello[:0], MaxNonce, pfsPublicKey, nil) + c.GCM.Seal(serverHello[:pfsKeyExchangeLength], nil, ticket, nil) + padding := serverHello[pfsKeyExchangeLength+encryptedTicketLength:] + c.GCM.Seal(padding[:0], nil, EncodeLength(paddingLength-18), nil) + c.GCM.Seal(padding[:18], nil, padding[18:paddingLength-16], nil) + + if _, err := conn.Write(serverHello); err != nil { + return nil, err + } + // padding can be sent in a fragmented way, to create variable traffic pattern, before inner VLESS flow takes control + + if i.Seconds > 0 { + i.RWLock.Lock() + i.Sessions[[16]byte(ticket)] = &ServerSession{ + Expire: time.Now().Add(time.Duration(i.Seconds) * time.Second), + PfsKey: pfsKey, + } + i.RWLock.Unlock() + } + + // important: allows client sends padding slowly, eliminating 1-RTT's traffic pattern + if _, err := io.ReadFull(conn, encryptedLength); err != nil { + return nil, err + } + if _, err := nfsGCM.Open(encryptedLength[:0], nil, encryptedLength, nil); err != nil { + return nil, err + } + encryptedPadding := make([]byte, DecodeLength(encryptedLength[:2])) + if _, err := io.ReadFull(conn, encryptedPadding); err != nil { + return nil, err + } + if _, err := nfsGCM.Open(encryptedPadding[:0], nil, encryptedPadding, nil); err != nil { + return nil, err + } + + if i.XorMode == 2 { + c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, ticket), NewCTR(c.UnitedKey, iv), 0, 0) + } + return c, nil +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/xor.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/xor.go new file mode 100644 index 0000000000..d8846f9420 --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/encryption/xor.go @@ -0,0 +1,93 @@ +package encryption + +import ( + "crypto/aes" + "crypto/cipher" + "net" + + "github.com/metacubex/blake3" +) + +func NewCTR(key, iv []byte) cipher.Stream { + k := make([]byte, 32) + blake3.DeriveKey(k, "VLESS", key) // avoids using key directly + block, _ := aes.NewCipher(k) + return cipher.NewCTR(block, iv) + //chacha20.NewUnauthenticatedCipher() +} + +type XorConn struct { + net.Conn + CTR cipher.Stream + PeerCTR cipher.Stream + OutSkip int + OutHeader []byte + InSkip int + InHeader []byte +} + +func NewXorConn(conn net.Conn, ctr, peerCTR cipher.Stream, outSkip, inSkip int) *XorConn { + return &XorConn{ + Conn: conn, + CTR: ctr, + PeerCTR: peerCTR, + OutSkip: outSkip, + OutHeader: make([]byte, 0, 5), // important + InSkip: inSkip, + InHeader: make([]byte, 0, 5), // important + } +} + +func (c *XorConn) Write(b []byte) (int, error) { + if len(b) == 0 { + return 0, nil + } + for p := b; ; { + if len(p) <= c.OutSkip { + c.OutSkip -= len(p) + break + } + p = p[c.OutSkip:] + c.OutSkip = 0 + need := 5 - len(c.OutHeader) + if len(p) < need { + c.OutHeader = append(c.OutHeader, p...) + c.CTR.XORKeyStream(p, p) + break + } + c.OutSkip, _ = DecodeHeader(append(c.OutHeader, p[:need]...)) + c.OutHeader = c.OutHeader[:0] + c.CTR.XORKeyStream(p[:need], p[:need]) + p = p[need:] + } + if _, err := c.Conn.Write(b); err != nil { + return 0, err + } + return len(b), nil +} + +func (c *XorConn) Read(b []byte) (int, error) { + if len(b) == 0 { + return 0, nil + } + n, err := c.Conn.Read(b) + for p := b[:n]; ; { + if len(p) <= c.InSkip { + c.InSkip -= len(p) + break + } + p = p[c.InSkip:] + c.InSkip = 0 + need := 5 - len(c.InHeader) + if len(p) < need { + c.PeerCTR.XORKeyStream(p, p) + c.InHeader = append(c.InHeader, p...) + break + } + c.PeerCTR.XORKeyStream(p[:need], p[:need]) + c.InSkip, _ = DecodeHeader(append(c.InHeader, p[:need]...)) + c.InHeader = c.InHeader[:0] + p = p[need:] + } + return n, err +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/packet.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/packet.go new file mode 100644 index 0000000000..587e272732 --- /dev/null +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/packet.go @@ -0,0 +1,57 @@ +package vless + +import ( + "encoding/binary" + "io" + "net" + + "github.com/metacubex/mihomo/common/pool" +) + +type PacketConn struct { + net.Conn + rAddr net.Addr +} + +func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { + err := binary.Write(c.Conn, binary.BigEndian, uint16(len(b))) + if err != nil { + return 0, err + } + + return c.Conn.Write(b) +} + +func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { + var length uint16 + err := binary.Read(c.Conn, binary.BigEndian, &length) + if err != nil { + return 0, nil, err + } + if len(b) < int(length) { + return 0, nil, io.ErrShortBuffer + } + n, err := io.ReadFull(c.Conn, b[:length]) + return n, c.rAddr, err +} + +func (c *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + var length uint16 + err = binary.Read(c.Conn, binary.BigEndian, &length) + if err != nil { + return + } + readBuf := pool.Get(int(length)) + put = func() { + _ = pool.Put(readBuf) + } + n, err := io.ReadFull(c.Conn, readBuf) + if err != nil { + put() + put = nil + return + } + data = readBuf[:n] + addr = c.rAddr + return +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/conn.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/conn.go index 56684808cb..0c300e05d1 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/conn.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/conn.go @@ -3,7 +3,6 @@ package vision import ( "bytes" "crypto/subtle" - gotls "crypto/tls" "encoding/binary" "errors" "fmt" @@ -12,7 +11,6 @@ import ( "github.com/metacubex/mihomo/common/buf" N "github.com/metacubex/mihomo/common/net" - tlsC "github.com/metacubex/mihomo/component/tls" "github.com/metacubex/mihomo/log" "github.com/gofrs/uuid/v5" @@ -23,15 +21,16 @@ var ( ) type Conn struct { - net.Conn + net.Conn // should be *vless.Conn N.ExtendedReader N.ExtendedWriter - upstream net.Conn userUUID *uuid.UUID - tlsConn net.Conn - input *bytes.Reader - rawInput *bytes.Buffer + // tlsConn and it's internal variables + tlsConn net.Conn // maybe [*tls.Conn] or other tls-like conn + netConn net.Conn // tlsConn.NetConn() + input *bytes.Reader // &tlsConn.input or nil + rawInput *bytes.Buffer // &tlsConn.rawInput or nil needHandshake bool packetsToFilter int @@ -145,7 +144,7 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error { } if vc.input == nil && vc.rawInput == nil { vc.readProcess = false - vc.ExtendedReader = N.NewExtendedReader(vc.Conn) + vc.ExtendedReader = N.NewExtendedReader(vc.netConn) log.Debugln("XTLS Vision direct read start") } if needReturn { @@ -171,7 +170,7 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { if vc.needHandshake { vc.needHandshake = false if buffer.IsEmpty() { - ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, false) + ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, true) // we do a long padding to hide vless header } else { vc.FilterTLS(buffer.Bytes()) ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, vc.isTLS) @@ -181,72 +180,47 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { buffer.Release() return err } - switch underlying := vc.tlsConn.(type) { - case *gotls.Conn: - if underlying.ConnectionState().Version != gotls.VersionTLS13 { - buffer.Release() - return ErrNotTLS13 - } - case *tlsC.UConn: - if underlying.ConnectionState().Version != tlsC.VersionTLS13 { - buffer.Release() - return ErrNotTLS13 - } + err = vc.checkTLSVersion() + if err != nil { + buffer.Release() + return err } vc.tlsConn = nil return nil } if vc.writeFilterApplicationData { - buffer2 := ReshapeBuffer(buffer) - defer buffer2.Release() vc.FilterTLS(buffer.Bytes()) - command := commandPaddingContinue - if !vc.isTLS { - command = commandPaddingEnd - - // disable XTLS - //vc.readProcess = false - vc.writeFilterApplicationData = false - vc.packetsToFilter = 0 - } else if buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true - } - vc.writeFilterApplicationData = false - } - ApplyPadding(buffer, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer) - if err != nil { - return err - } - if vc.writeDirect { - vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn) - log.Debugln("XTLS Vision direct write start") - //time.Sleep(5 * time.Millisecond) - } - if buffer2 != nil { - if vc.writeDirect || !vc.isTLS { - return vc.ExtendedWriter.WriteBuffer(buffer2) - } - vc.FilterTLS(buffer2.Bytes()) - command = commandPaddingContinue - if buffer2.Len() > 6 && bytes.Equal(buffer2.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true + buffers := vc.ReshapeBuffer(buffer) + applyPadding := true + for i, buffer := range buffers { + command := commandPaddingContinue + if applyPadding { + if vc.isTLS && buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) { + command = commandPaddingEnd + if vc.enableXTLS { + command = commandPaddingDirect + vc.writeDirect = true + } + vc.writeFilterApplicationData = false + applyPadding = false + } else if !vc.isTLS12orAbove && vc.packetsToFilter <= 1 { + command = commandPaddingEnd + vc.writeFilterApplicationData = false + applyPadding = false } - vc.writeFilterApplicationData = false + ApplyPadding(buffer, command, nil, vc.isTLS) } - ApplyPadding(buffer2, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer2) - if vc.writeDirect { - vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn) + + err = vc.ExtendedWriter.WriteBuffer(buffer) + if err != nil { + buf.ReleaseMulti(buffers[i:]) // release unwritten buffers + return + } + if command == commandPaddingDirect { + vc.ExtendedWriter = N.NewExtendedWriter(vc.netConn) log.Debugln("XTLS Vision direct write start") - //time.Sleep(10 * time.Millisecond) + //time.Sleep(5 * time.Millisecond) } } return err @@ -275,9 +249,9 @@ func (vc *Conn) NeedHandshake() bool { func (vc *Conn) Upstream() any { if vc.writeDirect || vc.readLastCommand == commandPaddingDirect { - return vc.Conn + return vc.netConn } - return vc.upstream + return vc.Conn } func (vc *Conn) ReaderPossiblyReplaceable() bool { @@ -302,3 +276,10 @@ func (vc *Conn) WriterReplaceable() bool { } return false } + +func (vc *Conn) Close() error { + if vc.ReaderReplaceable() || vc.WriterReplaceable() { // ignore send closeNotify alert in tls.Conn + return vc.netConn.Close() + } + return vc.Conn.Close() +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/padding.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/padding.go index dd9cb261a3..710f64c217 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/padding.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/padding.go @@ -6,6 +6,7 @@ import ( "github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/log" + N "github.com/metacubex/sing/common/network" "github.com/gofrs/uuid/v5" "github.com/metacubex/randv2" @@ -19,30 +20,6 @@ const ( commandPaddingDirect byte = 0x02 ) -func WriteWithPadding(buffer *buf.Buffer, p []byte, command byte, userUUID *uuid.UUID, paddingTLS bool) { - contentLen := int32(len(p)) - var paddingLen int32 - if contentLen < 900 { - if paddingTLS { - //log.Debugln("long padding") - paddingLen = randv2.Int32N(500) + 900 - contentLen - } else { - paddingLen = randv2.Int32N(256) - } - } - if userUUID != nil { - buffer.Write(userUUID.Bytes()) - } - - buffer.WriteByte(command) - binary.BigEndian.PutUint16(buffer.Extend(2), uint16(contentLen)) - binary.BigEndian.PutUint16(buffer.Extend(2), uint16(paddingLen)) - buffer.Write(p) - - buffer.Extend(int(paddingLen)) - log.Debugln("XTLS Vision write padding1: command=%v, payloadLen=%v, paddingLen=%v", command, contentLen, paddingLen) -} - func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID, paddingTLS bool) { contentLen := int32(buffer.Len()) var paddingLen int32 @@ -63,19 +40,20 @@ func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID, padding } buffer.Extend(int(paddingLen)) - log.Debugln("XTLS Vision write padding2: command=%d, payloadLen=%d, paddingLen=%d", command, contentLen, paddingLen) + log.Debugln("XTLS Vision write padding: command=%d, payloadLen=%d, paddingLen=%d", command, contentLen, paddingLen) } -func ReshapeBuffer(buffer *buf.Buffer) *buf.Buffer { - if buffer.Len() <= buf.BufferSize-PaddingHeaderLen { - return nil +func (vc *Conn) ReshapeBuffer(buffer *buf.Buffer) []*buf.Buffer { + const xrayBufSize = 8192 + if buffer.Len() <= xrayBufSize-PaddingHeaderLen { + return []*buf.Buffer{buffer} } cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) if cutAt == -1 { - cutAt = buf.BufferSize / 2 + cutAt = xrayBufSize / 2 } - buffer2 := buf.New() + buffer2 := N.NewReadWaitOptions(nil, vc).NewBuffer() // ensure the new buffer can send used in vc.WriteBuffer buffer2.Write(buffer.From(cutAt)) buffer.Truncate(cutAt) - return buffer2 + return []*buf.Buffer{buffer, buffer2} } diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/vision.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/vision.go index 00d0bf09dd..f9158ca4e3 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/vision.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/vision/vision.go @@ -12,24 +12,20 @@ import ( N "github.com/metacubex/mihomo/common/net" tlsC "github.com/metacubex/mihomo/component/tls" + "github.com/metacubex/mihomo/transport/vless/encryption" "github.com/gofrs/uuid/v5" - "github.com/metacubex/sing/common" ) var ErrNotTLS13 = errors.New("XTLS Vision based on TLS 1.3 outer connection") -type connWithUpstream interface { - net.Conn - common.WithUpstream -} - -func NewConn(conn connWithUpstream, userUUID *uuid.UUID) (*Conn, error) { +func NewConn(conn net.Conn, tlsConn net.Conn, userUUID *uuid.UUID) (*Conn, error) { c := &Conn{ ExtendedReader: N.NewExtendedReader(conn), ExtendedWriter: N.NewExtendedWriter(conn), - upstream: conn, + Conn: conn, userUUID: userUUID, + tlsConn: tlsConn, packetsToFilter: 6, needHandshake: true, readProcess: true, @@ -38,32 +34,54 @@ func NewConn(conn connWithUpstream, userUUID *uuid.UUID) (*Conn, error) { } var t reflect.Type var p unsafe.Pointer - switch underlying := conn.Upstream().(type) { + switch underlying := tlsConn.(type) { case *gotls.Conn: //log.Debugln("type tls") - c.Conn = underlying.NetConn() - c.tlsConn = underlying + c.netConn = underlying.NetConn() t = reflect.TypeOf(underlying).Elem() p = unsafe.Pointer(underlying) case *tlsC.Conn: //log.Debugln("type *tlsC.Conn") - c.Conn = underlying.NetConn() - c.tlsConn = underlying + c.netConn = underlying.NetConn() t = reflect.TypeOf(underlying).Elem() p = unsafe.Pointer(underlying) case *tlsC.UConn: //log.Debugln("type *tlsC.UConn") - c.Conn = underlying.NetConn() - c.tlsConn = underlying + c.netConn = underlying.NetConn() t = reflect.TypeOf(underlying.Conn).Elem() //log.Debugln("t:%v", t) p = unsafe.Pointer(underlying.Conn) + case *encryption.CommonConn: + //log.Debugln("type *encryption.CommonConn") + c.netConn = underlying.Conn + t = reflect.TypeOf(underlying).Elem() + p = unsafe.Pointer(underlying) default: return nil, fmt.Errorf(`failed to use vision, maybe "security" is not "tls" or "utls"`) } - i, _ := t.FieldByName("input") - r, _ := t.FieldByName("rawInput") - c.input = (*bytes.Reader)(unsafe.Add(p, i.Offset)) - c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset)) + if i, ok := t.FieldByName("input"); ok { + c.input = (*bytes.Reader)(unsafe.Add(p, i.Offset)) + } + if r, ok := t.FieldByName("rawInput"); ok { + c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset)) + } return c, nil } + +func (vc *Conn) checkTLSVersion() error { + switch underlying := vc.tlsConn.(type) { + case *gotls.Conn: + if underlying.ConnectionState().Version != gotls.VersionTLS13 { + return ErrNotTLS13 + } + case *tlsC.Conn: + if underlying.ConnectionState().Version != tlsC.VersionTLS13 { + return ErrNotTLS13 + } + case *tlsC.UConn: + if underlying.ConnectionState().Version != tlsC.VersionTLS13 { + return ErrNotTLS13 + } + } + return nil +} diff --git a/clash-meta-android/core/src/foss/golang/clash/transport/vless/vless.go b/clash-meta-android/core/src/foss/golang/clash/transport/vless/vless.go index ce07cdb415..9fb54f9205 100644 --- a/clash-meta-android/core/src/foss/golang/clash/transport/vless/vless.go +++ b/clash-meta-android/core/src/foss/golang/clash/transport/vless/vless.go @@ -51,6 +51,10 @@ func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) { return newConn(conn, c, dst) } +func (c *Client) PacketConn(conn net.Conn, rAddr net.Addr) net.PacketConn { + return &PacketConn{conn, rAddr} +} + // NewClient return Client instance func NewClient(uuidStr string, addons *Addons) (*Client, error) { uid, err := utils.UUIDMap(uuidStr) diff --git a/clash-meta-android/core/src/foss/golang/go.mod b/clash-meta-android/core/src/foss/golang/go.mod index 9cea5ef94f..5bda019f79 100644 --- a/clash-meta-android/core/src/foss/golang/go.mod +++ b/clash-meta-android/core/src/foss/golang/go.mod @@ -5,7 +5,6 @@ go 1.20 require cfa v0.0.0 require ( - github.com/3andne/restls-client-go v0.1.6 // indirect github.com/RyuaNerin/go-krypto v1.3.0 // indirect github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 // indirect github.com/ajg/form v1.5.1 // indirect @@ -14,15 +13,15 @@ require ( github.com/buger/jsonparser v1.1.1 // indirect github.com/coreos/go-iptables v0.8.0 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect - github.com/ebitengine/purego v0.8.3 // indirect - github.com/enfein/mieru/v3 v3.16.1 // indirect + github.com/ebitengine/purego v0.8.4 // indirect + github.com/enfein/mieru/v3 v3.19.1 // indirect github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 // indirect github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/gaukas/godicttls v0.0.4 // indirect - github.com/go-chi/chi/v5 v5.2.2 // indirect + github.com/go-chi/chi/v5 v5.2.3 // indirect github.com/go-chi/render v1.0.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect @@ -37,36 +36,37 @@ require ( github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 // indirect github.com/josharian/native v1.1.0 // indirect github.com/klauspost/compress v1.17.9 // indirect - github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.4.1 // indirect - github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab // indirect + github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a // indirect + github.com/metacubex/ascon v0.1.0 // indirect github.com/metacubex/bart v0.20.5 // indirect github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b // indirect + github.com/metacubex/blake3 v0.1.0 // indirect github.com/metacubex/chacha v0.1.5 // indirect github.com/metacubex/fswatch v0.1.1 // indirect github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect github.com/metacubex/mihomo v1.7.0 // indirect github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect - github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c // indirect + github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 // indirect github.com/metacubex/randv2 v0.2.0 // indirect - github.com/metacubex/sing v0.5.4 // indirect - github.com/metacubex/sing-mux v0.3.2 // indirect + github.com/metacubex/restls-client-go v0.1.7 // indirect + github.com/metacubex/sing v0.5.5 // indirect + github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac // indirect github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb // indirect - github.com/metacubex/sing-shadowsocks v0.2.11 // indirect - github.com/metacubex/sing-shadowsocks2 v0.2.5 // indirect + github.com/metacubex/sing-shadowsocks v0.2.12 // indirect + github.com/metacubex/sing-shadowsocks2 v0.2.6 // indirect github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 // indirect - github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97 // indirect - github.com/metacubex/sing-vmess v0.2.3 // indirect + github.com/metacubex/sing-tun v0.4.7 // indirect + github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 // indirect github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f // indirect github.com/metacubex/smux v0.0.0-20250503055512-501391591dee // indirect - github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 // indirect - github.com/metacubex/utls v1.8.0 // indirect - github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 // indirect + github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617 // indirect + github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142 // indirect + github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f // indirect github.com/miekg/dns v1.1.63 // indirect github.com/mroth/weightedrand/v2 v2.1.0 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect @@ -107,7 +107,6 @@ require ( golang.org/x/tools v0.24.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/blake3 v1.3.0 // indirect ) replace cfa => ../../main/golang diff --git a/clash-meta-android/core/src/foss/golang/go.sum b/clash-meta-android/core/src/foss/golang/go.sum index fd6da6964b..899ec40b2f 100644 --- a/clash-meta-android/core/src/foss/golang/go.sum +++ b/clash-meta-android/core/src/foss/golang/go.sum @@ -1,5 +1,3 @@ -github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08= -github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY= github.com/RyuaNerin/go-krypto v1.3.0 h1:smavTzSMAx8iuVlGb4pEwl9MD2qicqMzuXR2QWp2/Pg= github.com/RyuaNerin/go-krypto v1.3.0/go.mod h1:9R9TU936laAIqAmjcHo/LsaXYOZlymudOAxjaBf62UM= github.com/RyuaNerin/testingutil v0.1.0 h1:IYT6JL57RV3U2ml3dLHZsVtPOP6yNK7WUVdzzlpNrss= @@ -24,10 +22,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc= -github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/enfein/mieru/v3 v3.16.1 h1:CfIt1pQCCQbohkw+HBD2o8V9tnhZvB5yuXGGQIXTLOs= -github.com/enfein/mieru/v3 v3.16.1/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/enfein/mieru/v3 v3.19.1 h1:19b9kgFC7oJXX9RLEO5Pi1gO6yek5cWlpK7IJVUoE8I= +github.com/enfein/mieru/v3 v3.19.1/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM= github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 h1:kXYqH/sL8dS/FdoFjr12ePjnLPorPo2FsnrHNuXSDyo= github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I= github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g= @@ -41,8 +39,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= -github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= -github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= +github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -80,24 +78,24 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= -github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= -github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= -github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab h1:Chbw+/31UC14YFNr78pESt5Vowlc62zziw05JCUqoL4= -github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab/go.mod h1:xVKK8jC5Sd3hfh7WjmCq+HorehIbrBijaUWmcuKjPcI= +github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a h1:c1QSGpacSeQdBdWcEKZKGuWLcqIG2wxHEygAcXuDwS4= +github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a/go.mod h1:MsM/5czONyXMJ3PRr5DbQ4O/BxzAnJWOIcJdLzW6qHY= +github.com/metacubex/ascon v0.1.0 h1:6ZWxmXYszT1XXtwkf6nxfFhc/OTtQ9R3Vyj1jN32lGM= +github.com/metacubex/ascon v0.1.0/go.mod h1:eV5oim4cVPPdEL8/EYaTZ0iIKARH9pnhAK/fcT5Kacc= github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM= github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI= github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b h1:j7dadXD8I2KTmMt8jg1JcaP1ANL3JEObJPdANKcSYPY= github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b/go.mod h1:+WmP0VJZDkDszvpa83HzfUp6QzARl/IKkMorH4+nODw= +github.com/metacubex/blake3 v0.1.0 h1:KGnjh/56REO7U+cgZA8dnBhxdP7jByrG7hTP+bu6cqY= +github.com/metacubex/blake3 v0.1.0/go.mod h1:CCkLdzFrqf7xmxCdhQFvJsRRV2mwOLDoSPg6vUTB9Uk= github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M= github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8= github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU= @@ -108,37 +106,39 @@ github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= -github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c h1:ABQzmOaZddM3q0OYeoZEc0XF+KW+dUdPNvY/c5rsunI= -github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c/go.mod h1:eWlAK3zsKI0P8UhYpXlIsl3mtW4D6MpMNuYLIu8CKWI= +github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs= +github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= +github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k= +github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing v0.5.4 h1:a4kAOZmF+OXosbzPEcrSc5QD35/ex+MNuZsrcuWskHk= -github.com/metacubex/sing v0.5.4/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing-mux v0.3.2 h1:nJv52pyRivHcaZJKk2JgxpaVvj1GAXG81scSa9N7ncw= -github.com/metacubex/sing-mux v0.3.2/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= +github.com/metacubex/sing v0.5.5 h1:m5U8iHvRAUxlme3FZlE/LPIGHjU8oMCUzXWGbQQAC1E= +github.com/metacubex/sing v0.5.5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= +github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs= +github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb/go.mod h1:B60FxaPHjR1SeQB0IiLrgwgvKsaoASfOWdiqhLjmMGA= -github.com/metacubex/sing-shadowsocks v0.2.11 h1:p2NGNOdF95e6XvdDKipLj1FRRqR8dnbfC/7pw2CCTlw= -github.com/metacubex/sing-shadowsocks v0.2.11/go.mod h1:bT1PCTV316zFnlToRMk5zt9HmIQYRBveiT71mplYPfc= -github.com/metacubex/sing-shadowsocks2 v0.2.5 h1:MnPn0hbcDkSJt6TlpI15XImHKK6IqaOwBUGPKyMnJnE= -github.com/metacubex/sing-shadowsocks2 v0.2.5/go.mod h1:Zyh+rAQRyevYfG/COCvDs1c/YMhGqCuknn7QrGmoQIw= +github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE= +github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU= +github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7kjgRdMm0SB98= +github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97 h1:YYpc60UZE2G0pUeHbRw9erDrUDZrPQy8QzWFqA3kHsk= -github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64= -github.com/metacubex/sing-vmess v0.2.3 h1:QKLdIk5A2FcR3Y7m2/JO1XhfzgDA8tF4W9/ffsH9opo= -github.com/metacubex/sing-vmess v0.2.3/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= +github.com/metacubex/sing-tun v0.4.7 h1:ZDY/W+1c7PeWWKeKRyUo18fySF/TWjB0i5ui81Ar778= +github.com/metacubex/sing-tun v0.4.7/go.mod h1:xHecZRwBnKWe6zG9amAK9cXf91lF6blgjBqm+VvOrmU= +github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 h1:WZepq4TOZa6WewB8tGAZrrL+bL2R2ivoBzuEgAeolWc= +github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113awp7P6odM2okB5s60HUyF0FMqKmo= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= -github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc= -github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= -github.com/metacubex/utls v1.8.0 h1:mSYi6FMnmc5riARl5UZDmWVy710z+P5b7xuGW0lV9ac= -github.com/metacubex/utls v1.8.0/go.mod h1:FdjYzVfCtgtna19hX0ER1Xsa5uJInwdQ4IcaaI98lEQ= -github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ= -github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y= +github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617 h1:yN3mQ4cT9sPUciw/rO0Isc/8QlO86DB6g9SEMRgQ8Cw= +github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= +github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142 h1:csEbKOzRAxJXffOeZnnS3/kA/F55JiTbKv5jcYqCXms= +github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142/go.mod h1:67I3skhEY4Sya8f1YxELwWPoeQdXqZCrWNYLvq8gn2U= +github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk= +github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f/go.mod h1:oPGcV994OGJedmmxrcK9+ni7jUEMGhR+uVQAdaduIP4= github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU= @@ -191,7 +191,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -271,5 +271,3 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= -lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/clash-meta-android/core/src/main/golang/go.mod b/clash-meta-android/core/src/main/golang/go.mod index a43c5964c5..41f7d22999 100644 --- a/clash-meta-android/core/src/main/golang/go.mod +++ b/clash-meta-android/core/src/main/golang/go.mod @@ -12,7 +12,6 @@ require ( replace github.com/metacubex/mihomo => ../../foss/golang/clash require ( - github.com/3andne/restls-client-go v0.1.6 // indirect github.com/RyuaNerin/go-krypto v1.3.0 // indirect github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 // indirect github.com/ajg/form v1.5.1 // indirect @@ -20,15 +19,15 @@ require ( github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/coreos/go-iptables v0.8.0 // indirect - github.com/ebitengine/purego v0.8.3 // indirect - github.com/enfein/mieru/v3 v3.16.1 // indirect + github.com/ebitengine/purego v0.8.4 // indirect + github.com/enfein/mieru/v3 v3.19.1 // indirect github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 // indirect github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/gaukas/godicttls v0.0.4 // indirect - github.com/go-chi/chi/v5 v5.2.2 // indirect + github.com/go-chi/chi/v5 v5.2.3 // indirect github.com/go-chi/render v1.0.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect @@ -44,35 +43,36 @@ require ( github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 // indirect github.com/josharian/native v1.1.0 // indirect github.com/klauspost/compress v1.17.9 // indirect - github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.4.1 // indirect - github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab // indirect + github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a // indirect + github.com/metacubex/ascon v0.1.0 // indirect github.com/metacubex/bart v0.20.5 // indirect github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b // indirect + github.com/metacubex/blake3 v0.1.0 // indirect github.com/metacubex/chacha v0.1.5 // indirect github.com/metacubex/fswatch v0.1.1 // indirect github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect - github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c // indirect + github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 // indirect github.com/metacubex/randv2 v0.2.0 // indirect - github.com/metacubex/sing v0.5.4 // indirect - github.com/metacubex/sing-mux v0.3.2 // indirect + github.com/metacubex/restls-client-go v0.1.7 // indirect + github.com/metacubex/sing v0.5.5 // indirect + github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac // indirect github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb // indirect - github.com/metacubex/sing-shadowsocks v0.2.11 // indirect - github.com/metacubex/sing-shadowsocks2 v0.2.5 // indirect + github.com/metacubex/sing-shadowsocks v0.2.12 // indirect + github.com/metacubex/sing-shadowsocks2 v0.2.6 // indirect github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 // indirect - github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97 // indirect - github.com/metacubex/sing-vmess v0.2.3 // indirect + github.com/metacubex/sing-tun v0.4.7 // indirect + github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 // indirect github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f // indirect github.com/metacubex/smux v0.0.0-20250503055512-501391591dee // indirect - github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 // indirect - github.com/metacubex/utls v1.8.0 // indirect - github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 // indirect + github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617 // indirect + github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142 // indirect + github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f // indirect github.com/miekg/dns v1.1.63 // indirect github.com/mroth/weightedrand/v2 v2.1.0 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect @@ -111,5 +111,4 @@ require ( golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.24.0 // indirect google.golang.org/protobuf v1.34.2 // indirect - lukechampine.com/blake3 v1.3.0 // indirect ) diff --git a/clash-meta-android/core/src/main/golang/go.sum b/clash-meta-android/core/src/main/golang/go.sum index 3299c00077..36395707dc 100644 --- a/clash-meta-android/core/src/main/golang/go.sum +++ b/clash-meta-android/core/src/main/golang/go.sum @@ -1,5 +1,3 @@ -github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08= -github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY= github.com/RyuaNerin/go-krypto v1.3.0 h1:smavTzSMAx8iuVlGb4pEwl9MD2qicqMzuXR2QWp2/Pg= github.com/RyuaNerin/go-krypto v1.3.0/go.mod h1:9R9TU936laAIqAmjcHo/LsaXYOZlymudOAxjaBf62UM= github.com/RyuaNerin/testingutil v0.1.0 h1:IYT6JL57RV3U2ml3dLHZsVtPOP6yNK7WUVdzzlpNrss= @@ -24,10 +22,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc= -github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/enfein/mieru/v3 v3.16.1 h1:CfIt1pQCCQbohkw+HBD2o8V9tnhZvB5yuXGGQIXTLOs= -github.com/enfein/mieru/v3 v3.16.1/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/enfein/mieru/v3 v3.19.1 h1:19b9kgFC7oJXX9RLEO5Pi1gO6yek5cWlpK7IJVUoE8I= +github.com/enfein/mieru/v3 v3.19.1/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM= github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 h1:kXYqH/sL8dS/FdoFjr12ePjnLPorPo2FsnrHNuXSDyo= github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I= github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g= @@ -41,8 +39,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= -github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= -github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= +github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -81,24 +79,24 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= -github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= -github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= -github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab h1:Chbw+/31UC14YFNr78pESt5Vowlc62zziw05JCUqoL4= -github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab/go.mod h1:xVKK8jC5Sd3hfh7WjmCq+HorehIbrBijaUWmcuKjPcI= +github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a h1:c1QSGpacSeQdBdWcEKZKGuWLcqIG2wxHEygAcXuDwS4= +github.com/metacubex/amneziawg-go v0.0.0-20250820070344-732c0c9d418a/go.mod h1:MsM/5czONyXMJ3PRr5DbQ4O/BxzAnJWOIcJdLzW6qHY= +github.com/metacubex/ascon v0.1.0 h1:6ZWxmXYszT1XXtwkf6nxfFhc/OTtQ9R3Vyj1jN32lGM= +github.com/metacubex/ascon v0.1.0/go.mod h1:eV5oim4cVPPdEL8/EYaTZ0iIKARH9pnhAK/fcT5Kacc= github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM= github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI= github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b h1:j7dadXD8I2KTmMt8jg1JcaP1ANL3JEObJPdANKcSYPY= github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b/go.mod h1:+WmP0VJZDkDszvpa83HzfUp6QzARl/IKkMorH4+nODw= +github.com/metacubex/blake3 v0.1.0 h1:KGnjh/56REO7U+cgZA8dnBhxdP7jByrG7hTP+bu6cqY= +github.com/metacubex/blake3 v0.1.0/go.mod h1:CCkLdzFrqf7xmxCdhQFvJsRRV2mwOLDoSPg6vUTB9Uk= github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M= github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8= github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU= @@ -109,37 +107,39 @@ github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= -github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c h1:ABQzmOaZddM3q0OYeoZEc0XF+KW+dUdPNvY/c5rsunI= -github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c/go.mod h1:eWlAK3zsKI0P8UhYpXlIsl3mtW4D6MpMNuYLIu8CKWI= +github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs= +github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= +github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k= +github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing v0.5.4 h1:a4kAOZmF+OXosbzPEcrSc5QD35/ex+MNuZsrcuWskHk= -github.com/metacubex/sing v0.5.4/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing-mux v0.3.2 h1:nJv52pyRivHcaZJKk2JgxpaVvj1GAXG81scSa9N7ncw= -github.com/metacubex/sing-mux v0.3.2/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= +github.com/metacubex/sing v0.5.5 h1:m5U8iHvRAUxlme3FZlE/LPIGHjU8oMCUzXWGbQQAC1E= +github.com/metacubex/sing v0.5.5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= +github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs= +github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb/go.mod h1:B60FxaPHjR1SeQB0IiLrgwgvKsaoASfOWdiqhLjmMGA= -github.com/metacubex/sing-shadowsocks v0.2.11 h1:p2NGNOdF95e6XvdDKipLj1FRRqR8dnbfC/7pw2CCTlw= -github.com/metacubex/sing-shadowsocks v0.2.11/go.mod h1:bT1PCTV316zFnlToRMk5zt9HmIQYRBveiT71mplYPfc= -github.com/metacubex/sing-shadowsocks2 v0.2.5 h1:MnPn0hbcDkSJt6TlpI15XImHKK6IqaOwBUGPKyMnJnE= -github.com/metacubex/sing-shadowsocks2 v0.2.5/go.mod h1:Zyh+rAQRyevYfG/COCvDs1c/YMhGqCuknn7QrGmoQIw= +github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE= +github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU= +github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7kjgRdMm0SB98= +github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97 h1:YYpc60UZE2G0pUeHbRw9erDrUDZrPQy8QzWFqA3kHsk= -github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64= -github.com/metacubex/sing-vmess v0.2.3 h1:QKLdIk5A2FcR3Y7m2/JO1XhfzgDA8tF4W9/ffsH9opo= -github.com/metacubex/sing-vmess v0.2.3/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= +github.com/metacubex/sing-tun v0.4.7 h1:ZDY/W+1c7PeWWKeKRyUo18fySF/TWjB0i5ui81Ar778= +github.com/metacubex/sing-tun v0.4.7/go.mod h1:xHecZRwBnKWe6zG9amAK9cXf91lF6blgjBqm+VvOrmU= +github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 h1:WZepq4TOZa6WewB8tGAZrrL+bL2R2ivoBzuEgAeolWc= +github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113awp7P6odM2okB5s60HUyF0FMqKmo= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= -github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc= -github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= -github.com/metacubex/utls v1.8.0 h1:mSYi6FMnmc5riARl5UZDmWVy710z+P5b7xuGW0lV9ac= -github.com/metacubex/utls v1.8.0/go.mod h1:FdjYzVfCtgtna19hX0ER1Xsa5uJInwdQ4IcaaI98lEQ= -github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ= -github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y= +github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617 h1:yN3mQ4cT9sPUciw/rO0Isc/8QlO86DB6g9SEMRgQ8Cw= +github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= +github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142 h1:csEbKOzRAxJXffOeZnnS3/kA/F55JiTbKv5jcYqCXms= +github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142/go.mod h1:67I3skhEY4Sya8f1YxELwWPoeQdXqZCrWNYLvq8gn2U= +github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk= +github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f/go.mod h1:oPGcV994OGJedmmxrcK9+ni7jUEMGhR+uVQAdaduIP4= github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU= @@ -192,7 +192,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -272,5 +272,3 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= -lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/clash-meta/go.mod b/clash-meta/go.mod index 013bfe66a7..f7a63fa75a 100644 --- a/clash-meta/go.mod +++ b/clash-meta/go.mod @@ -6,8 +6,8 @@ require ( github.com/bahlo/generic-list-go v0.2.0 github.com/coreos/go-iptables v0.8.0 github.com/dlclark/regexp2 v1.11.5 - github.com/enfein/mieru/v3 v3.19.0 - github.com/go-chi/chi/v5 v5.2.2 + github.com/enfein/mieru/v3 v3.19.1 + github.com/go-chi/chi/v5 v5.2.3 github.com/go-chi/render v1.0.3 github.com/gobwas/ws v1.4.0 github.com/gofrs/uuid/v5 v5.3.2 @@ -30,11 +30,11 @@ require ( github.com/metacubex/sing-shadowsocks v0.2.12 github.com/metacubex/sing-shadowsocks2 v0.2.6 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 - github.com/metacubex/sing-tun v0.4.8-0.20250826073243-05ab78f45ac4 + github.com/metacubex/sing-tun v0.4.8-0.20250827085914-fc5681b9fc9f github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20250503055512-501391591dee - github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 + github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617 github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142 github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20 @@ -46,7 +46,7 @@ require ( github.com/samber/lo v1.51.0 github.com/shirou/gopsutil/v4 v4.25.1 // lastest version compatible with golang1.20 github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.0 github.com/vmihailenco/msgpack/v5 v5.4.1 github.com/wk8/go-ordered-map/v2 v2.1.8 gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7 @@ -68,7 +68,7 @@ require ( github.com/andybalholm/brotli v1.0.6 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/ebitengine/purego v0.8.3 // indirect + github.com/ebitengine/purego v0.8.4 // indirect github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 // indirect github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect diff --git a/clash-meta/go.sum b/clash-meta/go.sum index d94dbb6419..9b62944f4c 100644 --- a/clash-meta/go.sum +++ b/clash-meta/go.sum @@ -23,10 +23,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc= -github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/enfein/mieru/v3 v3.19.0 h1:GXUTWoWmr8pTqGSTbh82VXfnCENJm6m5UN76c3Ynzfw= -github.com/enfein/mieru/v3 v3.19.0/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/enfein/mieru/v3 v3.19.1 h1:19b9kgFC7oJXX9RLEO5Pi1gO6yek5cWlpK7IJVUoE8I= +github.com/enfein/mieru/v3 v3.19.1/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM= github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 h1:kXYqH/sL8dS/FdoFjr12ePjnLPorPo2FsnrHNuXSDyo= github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I= github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g= @@ -40,8 +40,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= -github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= -github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= +github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -129,16 +129,16 @@ github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7 github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.8-0.20250826073243-05ab78f45ac4 h1:GRfLW6QD1SfApCzi2SR8prAWVA//myGDq93YL4OE2T0= -github.com/metacubex/sing-tun v0.4.8-0.20250826073243-05ab78f45ac4/go.mod h1:FQ9zXA+kVhdzqgFqeJdi/AUhJgUgw+SUXqrR++GvbnM= +github.com/metacubex/sing-tun v0.4.8-0.20250827085914-fc5681b9fc9f h1:1MV/pFn2vjnyvH/0u6sJST0kmaoZXgbUytCCfuelhl8= +github.com/metacubex/sing-tun v0.4.8-0.20250827085914-fc5681b9fc9f/go.mod h1:FQ9zXA+kVhdzqgFqeJdi/AUhJgUgw+SUXqrR++GvbnM= github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 h1:WZepq4TOZa6WewB8tGAZrrL+bL2R2ivoBzuEgAeolWc= github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113awp7P6odM2okB5s60HUyF0FMqKmo= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= -github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc= -github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= +github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617 h1:yN3mQ4cT9sPUciw/rO0Isc/8QlO86DB6g9SEMRgQ8Cw= +github.com/metacubex/tfo-go v0.0.0-20250827083229-aa432b865617/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142 h1:csEbKOzRAxJXffOeZnnS3/kA/F55JiTbKv5jcYqCXms= github.com/metacubex/utls v1.8.1-0.20250823120917-12f5ba126142/go.mod h1:67I3skhEY4Sya8f1YxELwWPoeQdXqZCrWNYLvq8gn2U= github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk= @@ -196,8 +196,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= +github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index 3bb3599503..b05a715b3c 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -1305,9 +1305,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d07aa9a93b00c76f71bc35d598bed923f6d4f3a9ca5c24b7737ae1a292841c0" +checksum = "dd0b03af37dad7a14518b7691d81acb0f8222604ad3d1b02f6b4bed5188c0cd5" dependencies = [ "serde", ] diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 6ae5ca474e..a600c33490 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -59,9 +59,9 @@ "@iconify/json": "2.2.378", "@monaco-editor/react": "4.7.0", "@tanstack/react-query": "5.85.5", - "@tanstack/react-router": "1.131.27", - "@tanstack/react-router-devtools": "1.131.27", - "@tanstack/router-plugin": "1.131.27", + "@tanstack/react-router": "1.131.28", + "@tanstack/react-router-devtools": "1.131.28", + "@tanstack/router-plugin": "1.131.28", "@tauri-apps/plugin-clipboard-manager": "2.3.0", "@tauri-apps/plugin-dialog": "2.3.0", "@tauri-apps/plugin-fs": "2.4.0", @@ -71,7 +71,7 @@ "@tauri-apps/plugin-shell": "2.3.0", "@tauri-apps/plugin-updater": "2.9.0", "@types/react": "19.1.11", - "@types/react-dom": "19.1.7", + "@types/react-dom": "19.1.8", "@types/validator": "13.15.2", "@vitejs/plugin-legacy": "7.2.1", "@vitejs/plugin-react": "5.0.1", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index b34c4e3937..7819522200 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.12", - "mihomo_alpha": "alpha-443200a", + "mihomo_alpha": "alpha-bf8d1e1", "clash_rs": "v0.9.0", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.9.0-alpha+sha.8791f7f" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-08-25T22:21:06.996Z" + "updated_at": "2025-08-26T22:20:55.772Z" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 504ca7cb44..1fb0c30c25 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -250,7 +250,7 @@ importers: version: 4.1.12 '@tanstack/router-zod-adapter': specifier: 1.81.5 - version: 1.81.5(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.17) + version: 1.81.5(@tanstack/react-router@1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.17) '@tauri-apps/api': specifier: 2.6.0 version: 2.6.0 @@ -352,14 +352,14 @@ importers: specifier: 5.85.5 version: 5.85.5(react@19.1.1) '@tanstack/react-router': - specifier: 1.131.27 - version: 1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: 1.131.28 + version: 1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tanstack/react-router-devtools': - specifier: 1.131.27 - version: 1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.27)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3) + specifier: 1.131.28 + version: 1.131.28(@tanstack/react-router@1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.28)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3) '@tanstack/router-plugin': - specifier: 1.131.27 - version: 1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + specifier: 1.131.28 + version: 1.131.28(@tanstack/react-router@1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) '@tauri-apps/plugin-clipboard-manager': specifier: 2.3.0 version: 2.3.0 @@ -388,8 +388,8 @@ importers: specifier: 19.1.11 version: 19.1.11 '@types/react-dom': - specifier: 19.1.7 - version: 19.1.7(@types/react@19.1.11) + specifier: 19.1.8 + version: 19.1.8(@types/react@19.1.11) '@types/validator': specifier: 13.15.2 version: 13.15.2 @@ -473,10 +473,10 @@ importers: version: 7.3.1(@emotion/react@11.14.0(@types/react@19.1.11)(react@19.1.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.11)(react@19.1.1))(@types/react@19.1.11)(react@19.1.1))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-portal': specifier: 1.1.9 - version: 1.1.9(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 1.1.9(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-scroll-area': specifier: 1.2.10 - version: 1.2.10(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 1.2.10(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tauri-apps/api': specifier: 2.6.0 version: 2.6.0 @@ -566,8 +566,8 @@ importers: specifier: 11.0.2 version: 11.0.2 p-retry: - specifier: 6.2.1 - version: 6.2.1 + specifier: 7.0.0 + version: 7.0.0 semver: specifier: 7.7.2 version: 7.7.2 @@ -3021,16 +3021,16 @@ packages: peerDependencies: react: ^18 || ^19 - '@tanstack/react-router-devtools@1.131.27': - resolution: {integrity: sha512-SHulN0a7hZvyl3fXi+VLHxdMKdsg1lhPOZeKd5xs6bu/x+N5FaXEA5bUPGB2sbiSYXw/XFcjUqR5dkw8T1dkXg==} + '@tanstack/react-router-devtools@1.131.28': + resolution: {integrity: sha512-2EOxuvc2k7vT14XVEGJRuqEZhQkZ7RnHwpw2aGY6m/7xprl2elNwKtLExTntirAxE6HDokg8sRAnqvySHf1OVA==} engines: {node: '>=12'} peerDependencies: - '@tanstack/react-router': ^1.131.27 + '@tanstack/react-router': ^1.131.28 react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' - '@tanstack/react-router@1.131.27': - resolution: {integrity: sha512-JLUsmlarNxMz7VDhFscZCqoc2quhocQZKhia/7YXWf8Jbc8rANk6lukK4ecYn92m/ytoHAAy77JeaB6n0HvqwQ==} + '@tanstack/react-router@1.131.28': + resolution: {integrity: sha512-vWExhrqHJuT9v+6/2DCQ4pVvPaYoLazMNw8WXiLNuzBXh1FuEoIGaW3jw3DEP0OJCmMiWtTi34NzQnakkQZlQg==} engines: {node: '>=12'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -3055,15 +3055,15 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.131.27': - resolution: {integrity: sha512-NEBNxZ/LIBIh6kvQntr6bKq57tDe55zecyTtjAmzPkYFsMy1LXEpRm5H3BPiteBMRApAjuaq+bS1qA664hLH6Q==} + '@tanstack/router-core@1.131.28': + resolution: {integrity: sha512-f+vdfr3WKSS/BcqgI5s4vZg9xYb7NkvIolkaMELrbz3l+khkw1aTjx8wqCHRY4dqwIAxq+iZBZtMWXA7pztGJg==} engines: {node: '>=12'} - '@tanstack/router-devtools-core@1.131.27': - resolution: {integrity: sha512-upoMv/uq1CQdrOyBO2h6CLXI1Ym7Rawoovt26fN1Wl+RMXqKGVpHAXYuKpugdFMFhFieccKVYcrj9NP4V5BIDw==} + '@tanstack/router-devtools-core@1.131.28': + resolution: {integrity: sha512-CPj8wv/00sfHm5tjUCJ44A5tWBYvui5PVstkNfEyNW/Cmo6aknMk4SHiWIa/khCbj5HGjVMWSBRn6XZixEdOxw==} engines: {node: '>=12'} peerDependencies: - '@tanstack/router-core': ^1.131.27 + '@tanstack/router-core': ^1.131.28 csstype: ^3.0.10 solid-js: '>=1.9.5' tiny-invariant: ^1.3.3 @@ -3071,16 +3071,16 @@ packages: csstype: optional: true - '@tanstack/router-generator@1.131.27': - resolution: {integrity: sha512-PXBIVl45q2bBq9g0DDXLBGeKjO9eExcZd2JotLjLdIJ0I/wdxPQOBJHLPZfnmbf3vispToedRvG3b1YDWjL48g==} + '@tanstack/router-generator@1.131.28': + resolution: {integrity: sha512-e/6+2bfKhdiAgbFh4X0fADcnS7jNr6HqmDQ8Dcx9zpIGzWnj3pi9HUfHi7kmgZvxtCv8286BdVJsC7PqgxFHJw==} engines: {node: '>=12'} - '@tanstack/router-plugin@1.131.27': - resolution: {integrity: sha512-0V611ehOE8nfCFT2tvrLfQMroyoYW/virDXPaaFe38hdDxslmfCW2miJxngxz4+QqgK/M3sX71ElrZDvkP2Ixw==} + '@tanstack/router-plugin@1.131.28': + resolution: {integrity: sha512-7PxDjczsv90YQtphmjaakvHi8yF+d1mSs+ro8yIA/KrGD1+TaWvguAdFceDn/2ZGy5/tmCOVXQwuOg95HL8u6g==} engines: {node: '>=12'} peerDependencies: '@rsbuild/core': '>=1.0.2' - '@tanstack/react-router': ^1.131.27 + '@tanstack/react-router': ^1.131.28 vite: '>=5.0.0 || >=6.0.0' vite-plugin-solid: ^2.11.2 webpack: '>=5.92.0' @@ -3432,8 +3432,8 @@ packages: '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/react-dom@19.1.7': - resolution: {integrity: sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==} + '@types/react-dom@19.1.8': + resolution: {integrity: sha512-xG7xaBMJCpcK0RpN8jDbAACQo54ycO6h4dSSmgv8+fu6ZIAdANkx/WsawASUjVXYfy+J9AbUpRMNNEsXCDfDBQ==} peerDependencies: '@types/react': ^19.0.0 @@ -3448,9 +3448,6 @@ packages: '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} - '@types/retry@0.12.2': - resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} - '@types/semver@7.7.0': resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} @@ -6790,9 +6787,9 @@ packages: resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - p-retry@6.2.1: - resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} - engines: {node: '>=16.17'} + p-retry@7.0.0: + resolution: {integrity: sha512-3BgO9rjULJYyr0Y0pcsG7FZ+7JB/hfOODO8kx9ppumiO5jprUF92WK/Y7Q0xppZtq4VhTcPiVq7qWLQfIV5aKQ==} + engines: {node: '>=20'} p-timeout@3.2.0: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} @@ -7386,10 +7383,6 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} - retry@0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -8829,11 +8822,11 @@ snapshots: '@babel/helper-annotate-as-pure@7.25.9': dependencies: - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@babel/helper-compilation-targets@7.26.5': dependencies: @@ -8859,7 +8852,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.25.9 '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.10) '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -8872,7 +8865,20 @@ snapshots: '@babel/helper-optimise-call-expression': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.3 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -8915,14 +8921,14 @@ snapshots: '@babel/helper-member-expression-to-functions@7.25.9': dependencies: - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.1 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color '@babel/helper-member-expression-to-functions@7.27.1': dependencies: - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -8936,8 +8942,8 @@ snapshots: '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.1 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -8946,7 +8952,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-module-imports': 7.25.9 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -8955,7 +8961,16 @@ snapshots: '@babel/core': 7.28.0 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -8970,7 +8985,7 @@ snapshots: '@babel/helper-optimise-call-expression@7.25.9': dependencies: - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@babel/helper-optimise-call-expression@7.27.1': dependencies: @@ -8985,7 +9000,7 @@ snapshots: '@babel/core': 7.28.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-wrap-function': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -8994,7 +9009,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-member-expression-to-functions': 7.25.9 '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -9003,21 +9018,30 @@ snapshots: '@babel/core': 7.28.0 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.25.9': dependencies: - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.1 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.1 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -9037,7 +9061,7 @@ snapshots: '@babel/helper-wrap-function@7.27.1': dependencies: '@babel/template': 7.27.2 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -9045,12 +9069,12 @@ snapshots: '@babel/helpers@7.27.0': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@babel/helpers@7.27.6': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@babel/helpers@7.28.3': dependencies: @@ -9073,7 +9097,7 @@ snapshots: dependencies: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -9100,7 +9124,7 @@ snapshots: dependencies: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -9126,14 +9150,14 @@ snapshots: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.0)': @@ -9152,7 +9176,7 @@ snapshots: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0) - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -9199,7 +9223,7 @@ snapshots: '@babel/helper-globals': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -9213,7 +9237,7 @@ snapshots: dependencies: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -9270,7 +9294,7 @@ snapshots: '@babel/core': 7.28.0 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -9297,7 +9321,7 @@ snapshots: '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.0) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color @@ -9305,7 +9329,15 @@ snapshots: '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.0) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color @@ -9323,7 +9355,7 @@ snapshots: '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.0) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color @@ -9356,7 +9388,7 @@ snapshots: '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0) - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color @@ -9462,14 +9494,14 @@ snapshots: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typescript@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-typescript@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color @@ -9576,17 +9608,17 @@ snapshots: dependencies: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 esutils: 2.0.3 - '@babel/preset-typescript@7.27.1(@babel/core@7.28.0)': + '@babel/preset-typescript@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color @@ -9604,13 +9636,13 @@ snapshots: dependencies: '@babel/code-frame': 7.27.1 '@babel/parser': 7.28.0 - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.0 - '@babel/types': 7.28.1 + '@babel/parser': 7.28.3 + '@babel/types': 7.28.2 '@babel/traverse@7.23.2': dependencies: @@ -10804,17 +10836,17 @@ snapshots: optionalDependencies: '@types/react': 19.1.11 - '@radix-ui/react-portal@1.1.9(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.11)(react@19.1.1) react: 19.1.1 react-dom: 19.1.1(react@19.1.1) optionalDependencies: '@types/react': 19.1.11 - '@types/react-dom': 19.1.7(@types/react@19.1.11) + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.11)(react@19.1.1) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.11)(react@19.1.1) @@ -10822,33 +10854,33 @@ snapshots: react-dom: 19.1.1(react@19.1.1) optionalDependencies: '@types/react': 19.1.11 - '@types/react-dom': 19.1.7(@types/react@19.1.11) + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/react-slot': 1.2.3(@types/react@19.1.11)(react@19.1.1) react: 19.1.1 react-dom: 19.1.1(react@19.1.1) optionalDependencies: '@types/react': 19.1.11 - '@types/react-dom': 19.1.7(@types/react@19.1.11) + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.3 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.11)(react@19.1.1) '@radix-ui/react-context': 1.1.2(@types/react@19.1.11)(react@19.1.1) '@radix-ui/react-direction': 1.1.1(@types/react@19.1.11)(react@19.1.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.11)(react@19.1.1) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.11)(react@19.1.1) react: 19.1.1 react-dom: 19.1.1(react@19.1.1) optionalDependencies: '@types/react': 19.1.11 - '@types/react-dom': 19.1.7(@types/react@19.1.11) + '@types/react-dom': 19.1.8(@types/react@19.1.11) '@radix-ui/react-slot@1.2.3(@types/react@19.1.11)(react@19.1.1)': dependencies: @@ -11248,10 +11280,10 @@ snapshots: '@tanstack/query-core': 5.85.5 react: 19.1.1 - '@tanstack/react-router-devtools@1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.27)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)': + '@tanstack/react-router-devtools@1.131.28(@tanstack/react-router@1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.28)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)': dependencies: - '@tanstack/react-router': 1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@tanstack/router-devtools-core': 1.131.27(@tanstack/router-core@1.131.27)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3) + '@tanstack/react-router': 1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/router-devtools-core': 1.131.28(@tanstack/router-core@1.131.28)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3) react: 19.1.1 react-dom: 19.1.1(react@19.1.1) transitivePeerDependencies: @@ -11260,11 +11292,11 @@ snapshots: - solid-js - tiny-invariant - '@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@tanstack/react-router@1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@tanstack/history': 1.131.2 '@tanstack/react-store': 0.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@tanstack/router-core': 1.131.27 + '@tanstack/router-core': 1.131.28 isbot: 5.1.28 react: 19.1.1 react-dom: 19.1.1(react@19.1.1) @@ -11290,7 +11322,7 @@ snapshots: react: 19.1.1 react-dom: 19.1.1(react@19.1.1) - '@tanstack/router-core@1.131.27': + '@tanstack/router-core@1.131.28': dependencies: '@tanstack/history': 1.131.2 '@tanstack/store': 0.7.0 @@ -11300,9 +11332,9 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/router-devtools-core@1.131.27(@tanstack/router-core@1.131.27)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)': + '@tanstack/router-devtools-core@1.131.28(@tanstack/router-core@1.131.28)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)': dependencies: - '@tanstack/router-core': 1.131.27 + '@tanstack/router-core': 1.131.28 clsx: 2.1.1 goober: 2.1.16(csstype@3.1.3) solid-js: 1.9.5 @@ -11310,9 +11342,9 @@ snapshots: optionalDependencies: csstype: 3.1.3 - '@tanstack/router-generator@1.131.27': + '@tanstack/router-generator@1.131.28': dependencies: - '@tanstack/router-core': 1.131.27 + '@tanstack/router-core': 1.131.28 '@tanstack/router-utils': 1.131.2 '@tanstack/virtual-file-routes': 1.131.2 prettier: 3.6.2 @@ -11323,16 +11355,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': + '@tanstack/router-plugin@1.131.28(@tanstack/react-router@1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': dependencies: - '@babel/core': 7.28.0 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.3) '@babel/template': 7.27.2 - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.1 - '@tanstack/router-core': 1.131.27 - '@tanstack/router-generator': 1.131.27 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 + '@tanstack/router-core': 1.131.28 + '@tanstack/router-generator': 1.131.28 '@tanstack/router-utils': 1.131.2 '@tanstack/virtual-file-routes': 1.131.2 babel-dead-code-elimination: 1.0.10 @@ -11340,25 +11372,25 @@ snapshots: unplugin: 2.3.5 zod: 3.25.76 optionalDependencies: - '@tanstack/react-router': 1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/react-router': 1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1) vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - supports-color '@tanstack/router-utils@1.131.2': dependencies: - '@babel/core': 7.28.0 - '@babel/generator': 7.28.0 - '@babel/parser': 7.28.0 - '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/generator': 7.28.3 + '@babel/parser': 7.28.3 + '@babel/preset-typescript': 7.27.1(@babel/core@7.28.3) ansis: 4.1.0 diff: 8.0.2 transitivePeerDependencies: - supports-color - '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.17)': + '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.17)': dependencies: - '@tanstack/react-router': 1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/react-router': 1.131.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1) zod: 4.0.17 '@tanstack/store@0.7.0': {} @@ -11490,23 +11522,23 @@ snapshots: '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.28.0 - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.0 - '@babel/types': 7.28.1 + '@babel/parser': 7.28.3 + '@babel/types': 7.28.2 '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@types/cacheable-request@6.0.3': dependencies: @@ -11707,7 +11739,7 @@ snapshots: '@types/prop-types@15.7.15': {} - '@types/react-dom@19.1.7(@types/react@19.1.11)': + '@types/react-dom@19.1.8(@types/react@19.1.11)': dependencies: '@types/react': 19.1.11 @@ -11723,8 +11755,6 @@ snapshots: dependencies: '@types/node': 22.18.0 - '@types/retry@0.12.2': {} - '@types/semver@7.7.0': {} '@types/unist@2.0.10': {} @@ -12011,7 +12041,7 @@ snapshots: '@vue/compiler-core@3.5.13': dependencies: - '@babel/parser': 7.28.0 + '@babel/parser': 7.28.3 '@vue/shared': 3.5.13 entities: 4.5.0 estree-walker: 2.0.2 @@ -12300,10 +12330,10 @@ snapshots: babel-dead-code-elimination@1.0.10: dependencies: - '@babel/core': 7.28.0 - '@babel/parser': 7.28.0 - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.1 + '@babel/core': 7.28.3 + '@babel/parser': 7.28.3 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -15636,11 +15666,9 @@ snapshots: dependencies: p-limit: 4.0.0 - p-retry@6.2.1: + p-retry@7.0.0: dependencies: - '@types/retry': 0.12.2 is-network-error: 1.1.0 - retry: 0.13.1 p-timeout@3.2.0: dependencies: @@ -16195,8 +16223,6 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 - retry@0.13.1: {} - reusify@1.0.4: {} rfdc@1.4.1: {} diff --git a/clash-nyanpasu/scripts/package.json b/clash-nyanpasu/scripts/package.json index c00a44d54e..bfb1964a0d 100644 --- a/clash-nyanpasu/scripts/package.json +++ b/clash-nyanpasu/scripts/package.json @@ -8,7 +8,7 @@ "@types/semver": "7.7.0", "figlet": "1.8.2", "filesize": "11.0.2", - "p-retry": "6.2.1", + "p-retry": "7.0.0", "semver": "7.7.2", "zod": "4.0.17" }, diff --git a/lede/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch b/lede/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch index ea51478fd0..12fbc59e98 100644 --- a/lede/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch +++ b/lede/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch @@ -578,7 +578,7 @@ SVN-Revision: 35130 goto next_ht; --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c -@@ -269,7 +269,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff * +@@ -271,7 +271,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff * continue; iph2 = (struct ipv6hdr *)(p->data + off); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0054-Add-dwc_otg-driver.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0054-Add-dwc_otg-driver.patch index ad0b6cf7dd..9502cdf2cf 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0054-Add-dwc_otg-driver.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0054-Add-dwc_otg-driver.patch @@ -1248,7 +1248,7 @@ Signed-off-by: Jonathan Bell } --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -5757,7 +5757,7 @@ static void port_event(struct usb_hub *h +@@ -5786,7 +5786,7 @@ static void port_event(struct usb_hub *h port_dev->over_current_count++; port_over_current_notify(port_dev); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0073-ASoC-Add-support-for-all-the-downstream-rpi-sound-ca.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0073-ASoC-Add-support-for-all-the-downstream-rpi-sound-ca.patch index 2da70b23d8..59105068c1 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0073-ASoC-Add-support-for-all-the-downstream-rpi-sound-ca.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0073-ASoC-Add-support-for-all-the-downstream-rpi-sound-ca.patch @@ -18589,7 +18589,7 @@ Signed-off-by: j-schambacher u32 xfer_resolution; --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c -@@ -1434,7 +1434,15 @@ int snd_soc_runtime_set_dai_fmt(struct s +@@ -1437,7 +1437,15 @@ int snd_soc_runtime_set_dai_fmt(struct s return 0; for_each_rtd_codec_dais(rtd, i, codec_dai) { diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0100-media-tc358743-Increase-FIFO-level-to-374.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0100-media-tc358743-Increase-FIFO-level-to-374.patch deleted file mode 100644 index 2981e5c663..0000000000 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0100-media-tc358743-Increase-FIFO-level-to-374.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6fd71667a133560b84946a5008e3c9375b5115b7 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 31 Oct 2018 14:56:59 +0000 -Subject: [PATCH] media: tc358743: Increase FIFO level to 374. - -The existing fixed value of 16 worked for UYVY 720P60 over -2 lanes at 594MHz, or UYVY 1080P60 over 4 lanes. (RGB888 -1080P60 needs 6 lanes at 594MHz). -It doesn't allow for lower resolutions to work as the FIFO -underflows. - -374 is required for 1080P24-30 UYVY over 2 lanes @ 972Mbit/s, but ->374 means that the FIFO underflows on 1080P50 UYVY over 2 lanes -@ 972Mbit/s. - -Signed-off-by: Dave Stevenson ---- - drivers/media/i2c/tc358743.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/media/i2c/tc358743.c -+++ b/drivers/media/i2c/tc358743.c -@@ -1942,7 +1942,7 @@ static int tc358743_probe_of(struct tc35 - state->pdata.ddc5v_delay = DDC5V_DELAY_100_MS; - state->pdata.enable_hdcp = false; - /* A FIFO level of 16 should be enough for 2-lane 720p60 at 594 MHz. */ -- state->pdata.fifo_level = 16; -+ state->pdata.fifo_level = 374; - /* - * The PLL input clock is obtained by dividing refclk by pll_prd. - * It must be between 6 MHz and 40 MHz, lower frequency is better. diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0101-media-tc358743-Add-support-for-972Mbit-s-link-freq.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0101-media-tc358743-Add-support-for-972Mbit-s-link-freq.patch index 247b83d938..4dc5d19c94 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0101-media-tc358743-Add-support-for-972Mbit-s-link-freq.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0101-media-tc358743-Add-support-for-972Mbit-s-link-freq.patch @@ -24,7 +24,7 @@ Signed-off-by: Jacko Dirks --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c -@@ -1962,6 +1962,7 @@ static int tc358743_probe_of(struct tc35 +@@ -1980,6 +1980,7 @@ static int tc358743_probe_of(struct tc35 /* * The CSI bps per lane must be between 62.5 Mbps and 1 Gbps. * The default is 594 Mbps for 4-lane 1080p60 or 2-lane 720p60. @@ -32,7 +32,7 @@ Signed-off-by: Jacko Dirks */ bps_pr_lane = 2 * endpoint.link_frequencies[0]; if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) { -@@ -1975,23 +1976,42 @@ static int tc358743_probe_of(struct tc35 +@@ -1993,23 +1994,42 @@ static int tc358743_probe_of(struct tc35 state->pdata.refclk_hz * state->pdata.pll_prd; /* diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0102-media-tc358743-Check-I2C-succeeded-during-probe.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0102-media-tc358743-Check-I2C-succeeded-during-probe.patch deleted file mode 100644 index 77194eef03..0000000000 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0102-media-tc358743-Check-I2C-succeeded-during-probe.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 307615221ab3249fcfdd21b81a8aca138ed7a1ed Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 31 Oct 2018 14:57:34 +0000 -Subject: [PATCH] media: tc358743: Check I2C succeeded during probe. - -The probe for the TC358743 reads the CHIPID register from -the device and compares it to the expected value of 0. -If the I2C request fails then that also returns 0, so -the driver loads thinking that the device is there. - -Generally I2C communications are reliable so there is -limited need to check the return value on every transfer, -therefore only amend the one read during probe to check -for I2C errors. - -Signed-off-by: Dave Stevenson ---- - drivers/media/i2c/tc358743.c | 27 +++++++++++++++++++++++---- - 1 file changed, 23 insertions(+), 4 deletions(-) - ---- a/drivers/media/i2c/tc358743.c -+++ b/drivers/media/i2c/tc358743.c -@@ -110,7 +110,7 @@ static inline struct tc358743_state *to_ - - /* --------------- I2C --------------- */ - --static void i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) -+static int i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) - { - struct tc358743_state *state = to_state(sd); - struct i2c_client *client = state->i2c_client; -@@ -136,6 +136,7 @@ static void i2c_rd(struct v4l2_subdev *s - v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed: %d\n", - __func__, reg, client->addr, err); - } -+ return err != ARRAY_SIZE(msgs); - } - - static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) -@@ -192,15 +193,24 @@ static void i2c_wr(struct v4l2_subdev *s - } - } - --static noinline u32 i2c_rdreg(struct v4l2_subdev *sd, u16 reg, u32 n) -+static noinline u32 i2c_rdreg_err(struct v4l2_subdev *sd, u16 reg, u32 n, -+ int *err) - { -+ int error; - __le32 val = 0; - -- i2c_rd(sd, reg, (u8 __force *)&val, n); -+ error = i2c_rd(sd, reg, (u8 __force *)&val, n); -+ if (err) -+ *err = error; - - return le32_to_cpu(val); - } - -+static inline u32 i2c_rdreg(struct v4l2_subdev *sd, u16 reg, u32 n) -+{ -+ return i2c_rdreg_err(sd, reg, n, NULL); -+} -+ - static noinline void i2c_wrreg(struct v4l2_subdev *sd, u16 reg, u32 val, u32 n) - { - __le32 raw = cpu_to_le32(val); -@@ -229,6 +239,13 @@ static u16 i2c_rd16(struct v4l2_subdev * - return i2c_rdreg(sd, reg, 2); - } - -+static int i2c_rd16_err(struct v4l2_subdev *sd, u16 reg, u16 *value) -+{ -+ int err; -+ *value = i2c_rdreg_err(sd, reg, 2, &err); -+ return err; -+} -+ - static void i2c_wr16(struct v4l2_subdev *sd, u16 reg, u16 val) - { - i2c_wrreg(sd, reg, val, 2); -@@ -2050,6 +2067,7 @@ static int tc358743_probe(struct i2c_cli - struct tc358743_platform_data *pdata = client->dev.platform_data; - struct v4l2_subdev *sd; - u16 irq_mask = MASK_HDMI_MSK | MASK_CSI_MSK; -+ u16 chipid; - int err; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) -@@ -2081,7 +2099,8 @@ static int tc358743_probe(struct i2c_cli - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; - - /* i2c access */ -- if ((i2c_rd16(sd, CHIPID) & MASK_CHIPID) != 0) { -+ if (i2c_rd16_err(sd, CHIPID, &chipid) || -+ (chipid & MASK_CHIPID) != 0) { - v4l2_info(sd, "not a TC358743 on address 0x%x\n", - client->addr << 1); - return -ENODEV; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0107-media-tc358743-Return-an-appropriate-colorspace-from.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0107-media-tc358743-Return-an-appropriate-colorspace-from.patch deleted file mode 100644 index 0ac1a1a9f2..0000000000 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0107-media-tc358743-Return-an-appropriate-colorspace-from.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 1745cb8447123a894db6c0b579259ec5d976808f Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Thu, 22 Nov 2018 17:31:06 +0000 -Subject: [PATCH] media: tc358743: Return an appropriate colorspace from - tc358743_set_fmt - -When calling tc358743_set_fmt, the code was calling tc358743_get_fmt -to choose a valid format. However that sets the colorspace -based on what was read back from the chip. When you set the format, -then the driver would choose and program the colorspace based -on the format code. - -The result was that if you called try or set format for UYVY -when the current format was RGB3 then you would get told sRGB, -and try RGB3 when current was UYVY and you would get told -SMPTE170M. - -The value programmed into the chip is determined by this driver, -therefore there is no need to read back the value. Return the -colorspace based on the format set/tried instead. - -Signed-off-by: Dave Stevenson - -media: i2c: tc358743: Only allow supported pixel fmts in set_fmt - -Fix commit "media: tc358743: Return an appropriate colorspace from -tc358743_set_fmt" to ensure that the format passed in to set_fmt -is checked to be valid, and reset to the current format if not. - -Signed-off-by: Dave Stevenson ---- - drivers/media/i2c/tc358743.c | 44 ++++++++++++++---------------------- - 1 file changed, 17 insertions(+), 27 deletions(-) - ---- a/drivers/media/i2c/tc358743.c -+++ b/drivers/media/i2c/tc358743.c -@@ -1677,12 +1677,23 @@ static int tc358743_enum_mbus_code(struc - return 0; - } - -+static u32 tc358743_g_colorspace(u32 code) -+{ -+ switch (code) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ return V4L2_COLORSPACE_SRGB; -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ return V4L2_COLORSPACE_SMPTE170M; -+ default: -+ return 0; -+ } -+} -+ - static int tc358743_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) - { - struct tc358743_state *state = to_state(sd); -- u8 vi_rep = i2c_rd8(sd, VI_REP); - - if (format->pad != 0) - return -EINVAL; -@@ -1692,23 +1703,7 @@ static int tc358743_get_fmt(struct v4l2_ - format->format.height = state->timings.bt.height; - format->format.field = V4L2_FIELD_NONE; - -- switch (vi_rep & MASK_VOUT_COLOR_SEL) { -- case MASK_VOUT_COLOR_RGB_FULL: -- case MASK_VOUT_COLOR_RGB_LIMITED: -- format->format.colorspace = V4L2_COLORSPACE_SRGB; -- break; -- case MASK_VOUT_COLOR_601_YCBCR_LIMITED: -- case MASK_VOUT_COLOR_601_YCBCR_FULL: -- format->format.colorspace = V4L2_COLORSPACE_SMPTE170M; -- break; -- case MASK_VOUT_COLOR_709_YCBCR_FULL: -- case MASK_VOUT_COLOR_709_YCBCR_LIMITED: -- format->format.colorspace = V4L2_COLORSPACE_REC709; -- break; -- default: -- format->format.colorspace = 0; -- break; -- } -+ format->format.colorspace = tc358743_g_colorspace(format->format.code); - - return 0; - } -@@ -1722,19 +1717,14 @@ static int tc358743_set_fmt(struct v4l2_ - u32 code = format->format.code; /* is overwritten by get_fmt */ - int ret = tc358743_get_fmt(sd, sd_state, format); - -- format->format.code = code; -+ if (code == MEDIA_BUS_FMT_RGB888_1X24 || -+ code == MEDIA_BUS_FMT_UYVY8_1X16) -+ format->format.code = code; -+ format->format.colorspace = tc358743_g_colorspace(format->format.code); - - if (ret) - return ret; - -- switch (code) { -- case MEDIA_BUS_FMT_RGB888_1X24: -- case MEDIA_BUS_FMT_UYVY8_1X16: -- break; -- default: -- return -EINVAL; -- } -- - if (format->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0125-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0125-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch index 041d364b89..b3f1233293 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0125-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0125-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch @@ -14,7 +14,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c -@@ -1517,6 +1517,109 @@ static int xhci_check_ep0_maxpacket(stru +@@ -1519,6 +1519,109 @@ static int xhci_check_ep0_maxpacket(stru } /* @@ -124,7 +124,7 @@ Signed-off-by: Jonathan Bell * non-error returns are a promise to giveback() the urb later * we drop ownership so next owner (or urb unlink) can get it */ -@@ -5381,6 +5484,7 @@ static const struct hc_driver xhci_hc_dr +@@ -5383,6 +5486,7 @@ static const struct hc_driver xhci_hc_dr .endpoint_reset = xhci_endpoint_reset, .check_bandwidth = xhci_check_bandwidth, .reset_bandwidth = xhci_reset_bandwidth, diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0127-usb-xhci-drop-and-add-the-endpoint-context-in-xhci_f.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0127-usb-xhci-drop-and-add-the-endpoint-context-in-xhci_f.patch index c6f2196c32..1ac575a2ce 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0127-usb-xhci-drop-and-add-the-endpoint-context-in-xhci_f.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0127-usb-xhci-drop-and-add-the-endpoint-context-in-xhci_f.patch @@ -19,7 +19,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c -@@ -1606,7 +1606,7 @@ static void xhci_fixup_endpoint(struct u +@@ -1608,7 +1608,7 @@ static void xhci_fixup_endpoint(struct u return; } ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0132-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0132-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch index 1c13a65b21..dc9c10cb73 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0132-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0132-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch @@ -32,7 +32,7 @@ Signed-off-by: Jonathan Bell #define USB_VENDOR_ID_BELKIN 0x050d #define USB_DEVICE_ID_FLIP_KVM 0x3201 -@@ -1460,6 +1463,9 @@ +@@ -1463,6 +1466,9 @@ #define USB_VENDOR_ID_XIAOMI 0x2717 #define USB_DEVICE_ID_MI_SILENT_MOUSE 0x5014 diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0157-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0157-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch index 950e93c5db..b62142dd9f 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0157-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0157-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch @@ -26,7 +26,7 @@ Signed-off-by: Jonathan Bell return; val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); -@@ -1444,7 +1445,7 @@ static struct phy_driver broadcom_driver +@@ -1461,7 +1462,7 @@ static struct phy_driver broadcom_driver .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM54210E, @@ -35,7 +35,7 @@ Signed-off-by: Jonathan Bell .name = "Broadcom BCM54210E", /* PHY_GBIT_FEATURES */ .flags = PHY_ALWAYS_CALL_SUSPEND, -@@ -1462,6 +1463,13 @@ static struct phy_driver broadcom_driver +@@ -1479,6 +1480,13 @@ static struct phy_driver broadcom_driver .set_wol = bcm54xx_phy_set_wol, .led_brightness_set = bcm_phy_led_brightness_set, }, { @@ -49,7 +49,7 @@ Signed-off-by: Jonathan Bell .phy_id = PHY_ID_BCM5461, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM5461", -@@ -1728,7 +1736,8 @@ module_phy_driver(broadcom_drivers); +@@ -1745,7 +1753,8 @@ module_phy_driver(broadcom_drivers); static const struct mdio_device_id __maybe_unused broadcom_tbl[] = { { PHY_ID_BCM5411, 0xfffffff0 }, { PHY_ID_BCM5421, 0xfffffff0 }, diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0196-staging-fbtft-Add-support-for-display-variants.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0196-staging-fbtft-Add-support-for-display-variants.patch index bf6573548e..105941aa55 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0196-staging-fbtft-Add-support-for-display-variants.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0196-staging-fbtft-Add-support-for-display-variants.patch @@ -95,7 +95,7 @@ Signed-off-by: Phil Elwell #include