diff --git a/.github/update.log b/.github/update.log index 2db165e8e5..44b98de2ce 100644 --- a/.github/update.log +++ b/.github/update.log @@ -828,3 +828,4 @@ Update On Thu Nov 14 19:39:40 CET 2024 Update On Fri Nov 15 19:36:45 CET 2024 Update On Sat Nov 16 19:33:37 CET 2024 Update On Sun Nov 17 19:33:17 CET 2024 +Update On Mon Nov 18 19:38:02 CET 2024 diff --git a/clash-meta/.github/workflows/build.yml b/clash-meta/.github/workflows/build.yml index ee498d3a70..56c7b66d78 100644 --- a/clash-meta/.github/workflows/build.yml +++ b/clash-meta/.github/workflows/build.yml @@ -104,31 +104,24 @@ jobs: - uses: actions/checkout@v4 - name: Set up Go - if: ${{ matrix.jobs.goversion == '' && matrix.jobs.goarch != 'loong64' }} + if: ${{ matrix.jobs.goversion == '' && matrix.jobs.abi != '1' }} uses: actions/setup-go@v5 with: go-version: '1.23' - name: Set up Go - if: ${{ matrix.jobs.goversion != '' && matrix.jobs.goarch != 'loong64' }} + if: ${{ matrix.jobs.goversion != '' && matrix.jobs.abi != '1' }} uses: actions/setup-go@v5 with: go-version: ${{ matrix.jobs.goversion }} - - name: Set up Go1.22 loongarch abi1 + - name: Set up Go1.23 loongarch abi1 if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '1' }} run: | wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.23.0/go1.23.0.linux-amd64-abi1.tar.gz sudo tar zxf go1.23.0.linux-amd64-abi1.tar.gz -C /usr/local echo "/usr/local/go/bin" >> $GITHUB_PATH - # - name: Set up Go1.22 loongarch abi2 - # if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '2' }} - # run: | - # wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/go1.22.4.linux-amd64-abi2.tar.gz - # sudo tar zxf go1.22.4.linux-amd64-abi2.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.23.x # that means after golang1.24 release it must be changed diff --git a/clash-meta/adapter/inbound/auth.go b/clash-meta/adapter/inbound/auth.go index 984c9bd68e..8317274687 100644 --- a/clash-meta/adapter/inbound/auth.go +++ b/clash-meta/adapter/inbound/auth.go @@ -34,12 +34,5 @@ func SkipAuthRemoteAddress(addr string) bool { } func skipAuth(addr netip.Addr) bool { - if addr.IsValid() { - for _, prefix := range skipAuthPrefixes { - if prefix.Contains(addr.Unmap()) { - return true - } - } - } - return false + return prefixesContains(skipAuthPrefixes, addr) } diff --git a/clash-meta/adapter/inbound/ipfilter.go b/clash-meta/adapter/inbound/ipfilter.go index 7fa218c1f9..872d0c85a1 100644 --- a/clash-meta/adapter/inbound/ipfilter.go +++ b/clash-meta/adapter/inbound/ipfilter.go @@ -31,27 +31,17 @@ func IsRemoteAddrDisAllowed(addr net.Addr) bool { if err := m.SetRemoteAddr(addr); err != nil { return false } - return isAllowed(m.AddrPort().Addr().Unmap()) && !isDisAllowed(m.AddrPort().Addr().Unmap()) + ipAddr := m.AddrPort().Addr() + if ipAddr.IsValid() { + return isAllowed(ipAddr) && !isDisAllowed(ipAddr) + } + return false } func isAllowed(addr netip.Addr) bool { - if addr.IsValid() { - for _, prefix := range lanAllowedIPs { - if prefix.Contains(addr) { - return true - } - } - } - return false + return prefixesContains(lanAllowedIPs, addr) } func isDisAllowed(addr netip.Addr) bool { - if addr.IsValid() { - for _, prefix := range lanDisAllowedIPs { - if prefix.Contains(addr) { - return true - } - } - } - return false + return prefixesContains(lanDisAllowedIPs, addr) } diff --git a/clash-meta/adapter/inbound/util.go b/clash-meta/adapter/inbound/util.go index 743337fc12..3bcd280895 100644 --- a/clash-meta/adapter/inbound/util.go +++ b/clash-meta/adapter/inbound/util.go @@ -61,3 +61,19 @@ func parseHTTPAddr(request *http.Request) *C.Metadata { return metadata } + +func prefixesContains(prefixes []netip.Prefix, addr netip.Addr) bool { + if len(prefixes) == 0 { + return false + } + if !addr.IsValid() { + return false + } + addr = addr.Unmap().WithZone("") // netip.Prefix.Contains returns false if ip has an IPv6 zone + for _, prefix := range prefixes { + if prefix.Contains(addr) { + return true + } + } + return false +} diff --git a/clash-meta/rules/common/ipcidr.go b/clash-meta/rules/common/ipcidr.go index 663c9397c9..9c159502b4 100644 --- a/clash-meta/rules/common/ipcidr.go +++ b/clash-meta/rules/common/ipcidr.go @@ -40,7 +40,7 @@ func (i *IPCIDR) Match(metadata *C.Metadata) (bool, string) { if i.isSourceIP { ip = metadata.SrcIP } - return ip.IsValid() && i.ipnet.Contains(ip), i.adapter + return ip.IsValid() && i.ipnet.Contains(ip.WithZone("")), i.adapter } func (i *IPCIDR) Adapter() string { diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index e523cfc2ce..7a2c33ffcb 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -7810,9 +7810,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "simd-json" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1df0290e9bfe79ddd5ff8798ca887cd107b75353d2957efe9777296e17f26b5" +checksum = "aa2bcf6c6e164e81bc7a5d49fc6988b3d515d9e8c07457d7b74ffb9324b9cd40" dependencies = [ "getrandom 0.2.15", "halfbrown", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 4557b42284..392499c68d 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -54,8 +54,8 @@ "@emotion/react": "11.13.3", "@iconify/json": "2.2.273", "@monaco-editor/react": "4.6.0", - "@tanstack/react-router": "1.81.14", - "@tanstack/router-devtools": "1.81.14", + "@tanstack/react-router": "1.82.1", + "@tanstack/router-devtools": "1.82.1", "@tanstack/router-plugin": "1.81.9", "@tauri-apps/plugin-clipboard-manager": "2.0.0", "@tauri-apps/plugin-dialog": "2.0.1", @@ -79,7 +79,7 @@ "monaco-yaml": "5.2.3", "nanoid": "5.0.8", "sass": "1.81.0", - "shiki": "1.23.0", + "shiki": "1.23.1", "tailwindcss-textshadow": "2.1.3", "unplugin-auto-import": "0.18.4", "unplugin-icons": "0.20.1", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 36152d07a4..1038f96dc6 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.18.10", - "mihomo_alpha": "alpha-de19f92", + "mihomo_alpha": "alpha-25b3c86", "clash_rs": "v0.7.1", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.7.1-alpha+sha.5f2306a" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2024-11-14T22:20:48.929Z" + "updated_at": "2024-11-17T22:20:55.383Z" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index de5cd18f50..b54448c3b0 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -218,7 +218,7 @@ importers: version: link:../ui '@tanstack/router-zod-adapter': specifier: 1.81.5 - version: 1.81.5(@tanstack/react-router@1.81.14(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(zod@3.23.8) + version: 1.81.5(@tanstack/react-router@1.82.1(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(zod@3.23.8) '@tauri-apps/api': specifier: 2.1.1 version: 2.1.1 @@ -311,11 +311,11 @@ importers: specifier: 4.6.0 version: 4.6.0(monaco-editor@0.52.0)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) '@tanstack/react-router': - specifier: 1.81.14 - version: 1.81.14(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) + specifier: 1.82.1 + version: 1.82.1(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) '@tanstack/router-devtools': - specifier: 1.81.14 - version: 1.81.14(@tanstack/react-router@1.81.14(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) + specifier: 1.82.1 + version: 1.82.1(@tanstack/react-router@1.82.1(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) '@tanstack/router-plugin': specifier: 1.81.9 version: 1.81.9(vite@5.4.11(@types/node@22.9.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.81.0)(stylus@0.62.0)(terser@5.36.0)) @@ -386,8 +386,8 @@ importers: specifier: 1.81.0 version: 1.81.0 shiki: - specifier: 1.23.0 - version: 1.23.0 + specifier: 1.23.1 + version: 1.23.1 tailwindcss-textshadow: specifier: 2.1.3 version: 2.1.3 @@ -2526,17 +2526,17 @@ packages: '@rushstack/ts-command-line@4.23.0': resolution: {integrity: sha512-jYREBtsxduPV6ptNq8jOKp9+yx0ld1Tb/Tkdnlj8gTjazl1sF3DwX2VbluyYrNd0meWIL0bNeer7WDf5tKFjaQ==} - '@shikijs/core@1.23.0': - resolution: {integrity: sha512-J4Fo22oBlfRHAXec+1AEzcowv+Qdf4ZQkuP/X/UHYH9+KA9LvyFXSXyS+HxuBRFfon+u7bsmKdRBjoZlbDVRkQ==} + '@shikijs/core@1.23.1': + resolution: {integrity: sha512-NuOVgwcHgVC6jBVH5V7iblziw6iQbWWHrj5IlZI3Fqu2yx9awH7OIQkXIcsHsUmY19ckwSgUMgrqExEyP5A0TA==} - '@shikijs/engine-javascript@1.23.0': - resolution: {integrity: sha512-CcrppseWShG+8Efp1iil9divltuXVdCaU4iu+CKvzTGZO5RmXyAiSx668M7VbX8+s/vt1ZKu75Vn/jWi8O3G/Q==} + '@shikijs/engine-javascript@1.23.1': + resolution: {integrity: sha512-i/LdEwT5k3FVu07SiApRFwRcSJs5QM9+tod5vYCPig1Ywi8GR30zcujbxGQFJHwYD7A5BUqagi8o5KS+LEVgBg==} - '@shikijs/engine-oniguruma@1.23.0': - resolution: {integrity: sha512-gS8bZLqVvmZXX+E5JUMJICsBp+kx6gj79MH/UEpKHKIqnUzppgbmEn6zLa6mB5D+sHse2gFei3YYJxQe1EzZXQ==} + '@shikijs/engine-oniguruma@1.23.1': + resolution: {integrity: sha512-KQ+lgeJJ5m2ISbUZudLR1qHeH3MnSs2mjFg7bnencgs5jDVPeJ2NVDJ3N5ZHbcTsOIh0qIueyAJnwg7lg7kwXQ==} - '@shikijs/types@1.23.0': - resolution: {integrity: sha512-HiwzsihRao+IbPk7FER/EQT/D0dEEK3n5LAtHDzL5iRT+JMblA7y9uitUnjEnHeLkKigNM+ZplrP7MuEyyc5kA==} + '@shikijs/types@1.23.1': + resolution: {integrity: sha512-98A5hGyEhzzAgQh2dAeHKrWW4HfCMeoFER2z16p5eJ+vmPeF6lZ/elEne6/UCU551F/WqkopqRsr1l2Yu6+A0g==} '@shikijs/vscode-textmate@9.3.0': resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} @@ -2705,8 +2705,8 @@ packages: resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} - '@tanstack/react-router@1.81.14': - resolution: {integrity: sha512-+pzpblWgIUGXlyYlUAfGTZv7YfNOEMKupB5cP4CY9K/qu94D1qrUipjZ6PAqwj8yAwUDcBGam/AyzOLLTSNY5w==} + '@tanstack/react-router@1.82.1': + resolution: {integrity: sha512-C3+itdLVvEA3dOd/dYOrFSpqVBhWt/WUfjMWfda5lAGIxGkPM8Cv+7IE6P6LI80JOnUPGLpup23SShPD+cv3kw==} engines: {node: '>=12'} peerDependencies: '@tanstack/router-generator': 1.81.9 @@ -2735,11 +2735,11 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@tanstack/router-devtools@1.81.14': - resolution: {integrity: sha512-nigYdVDLWC22tff4Z1gBT26R/RBpW/nhBR4Vgs/0kBLqcj+/DFjZK5Q1MS/xSUUTOR4AW4J9av5zpHNqGFgEYQ==} + '@tanstack/router-devtools@1.82.1': + resolution: {integrity: sha512-sIPuoqrnnFmAGMuCMuw9kMMbIdzZW6ecipTD87xk44VusLtm7Rb4IAIAc2Kr8e4rrKlbOmieQ1Qihte9/KVrrA==} engines: {node: '>=12'} peerDependencies: - '@tanstack/react-router': ^1.81.14 + '@tanstack/react-router': ^1.82.1 react: '>=18' react-dom: '>=18' @@ -5919,8 +5919,8 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} - oniguruma-to-es@0.1.2: - resolution: {integrity: sha512-sBYKVJlIMB0WPO+tSu/NNB1ytSFeHyyJZ3Ayxfx3f/QUuXu0lvZk0VB4K7npmdlHSC0ldqanzh/sUSlAbgCTfw==} + oniguruma-to-es@0.4.1: + resolution: {integrity: sha512-rNcEohFz095QKGRovP/yqPIKc+nP+Sjs4YTHMv33nMePGKrq/r2eu9Yh4646M5XluGJsUnmwoXuiXE69KDs+fQ==} open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} @@ -6512,8 +6512,8 @@ packages: regex-utilities@2.3.0: resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} - regex@4.4.0: - resolution: {integrity: sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==} + regex@5.0.1: + resolution: {integrity: sha512-gIS00E8eHNWONxofNKOhtlkwBQj/K39ZJamnvMEFH3pNKc06Zz2jtFXF/4ldAaJTzQNhMJU7b5+C7tTq2ukV7Q==} regexp.prototype.flags@1.5.2: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} @@ -6861,8 +6861,8 @@ packages: shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - shiki@1.23.0: - resolution: {integrity: sha512-xfdu9DqPkIpExH29cmiTlgo0/jBki5la1Tkfhsv+Wu5TT3APLNHslR1acxuKJOCWqVdSc+pIbs/2ozjVRGppdg==} + shiki@1.23.1: + resolution: {integrity: sha512-8kxV9TH4pXgdKGxNOkrSMydn1Xf6It8lsle0fiqxf7a1149K1WGtdOu3Zb91T5r1JpvRPxqxU3C2XdZZXQnrig==} side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} @@ -9933,27 +9933,27 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@shikijs/core@1.23.0': + '@shikijs/core@1.23.1': dependencies: - '@shikijs/engine-javascript': 1.23.0 - '@shikijs/engine-oniguruma': 1.23.0 - '@shikijs/types': 1.23.0 + '@shikijs/engine-javascript': 1.23.1 + '@shikijs/engine-oniguruma': 1.23.1 + '@shikijs/types': 1.23.1 '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 hast-util-to-html: 9.0.3 - '@shikijs/engine-javascript@1.23.0': + '@shikijs/engine-javascript@1.23.1': dependencies: - '@shikijs/types': 1.23.0 + '@shikijs/types': 1.23.1 '@shikijs/vscode-textmate': 9.3.0 - oniguruma-to-es: 0.1.2 + oniguruma-to-es: 0.4.1 - '@shikijs/engine-oniguruma@1.23.0': + '@shikijs/engine-oniguruma@1.23.1': dependencies: - '@shikijs/types': 1.23.0 + '@shikijs/types': 1.23.1 '@shikijs/vscode-textmate': 9.3.0 - '@shikijs/types@1.23.0': + '@shikijs/types@1.23.1': dependencies: '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 @@ -10100,7 +10100,7 @@ snapshots: dependencies: remove-accents: 0.5.0 - '@tanstack/react-router@1.81.14(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)': + '@tanstack/react-router@1.82.1(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)': dependencies: '@tanstack/history': 1.81.9 '@tanstack/react-store': 0.5.6(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) @@ -10131,9 +10131,9 @@ snapshots: react: 19.0.0-rc.1 react-dom: 19.0.0-rc.1(react@19.0.0-rc.1) - '@tanstack/router-devtools@1.81.14(@tanstack/react-router@1.81.14(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)': + '@tanstack/router-devtools@1.82.1(@tanstack/react-router@1.82.1(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)': dependencies: - '@tanstack/react-router': 1.81.14(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) + '@tanstack/react-router': 1.82.1(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) clsx: 2.1.1 goober: 2.1.16(csstype@3.1.3) react: 19.0.0-rc.1 @@ -10173,9 +10173,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.81.14(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(zod@3.23.8)': + '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.82.1(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(zod@3.23.8)': dependencies: - '@tanstack/react-router': 1.81.14(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) + '@tanstack/react-router': 1.82.1(@tanstack/router-generator@1.81.9)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) zod: 3.23.8 '@tanstack/store@0.5.5': {} @@ -13751,10 +13751,10 @@ snapshots: dependencies: mimic-function: 5.0.1 - oniguruma-to-es@0.1.2: + oniguruma-to-es@0.4.1: dependencies: emoji-regex-xs: 1.0.0 - regex: 4.4.0 + regex: 5.0.1 regex-recursion: 4.2.1 open@8.4.2: @@ -14297,7 +14297,7 @@ snapshots: regex-utilities@2.3.0: {} - regex@4.4.0: {} + regex@5.0.1: {} regexp.prototype.flags@1.5.2: dependencies: @@ -14634,12 +14634,12 @@ snapshots: shell-quote@1.8.1: {} - shiki@1.23.0: + shiki@1.23.1: dependencies: - '@shikijs/core': 1.23.0 - '@shikijs/engine-javascript': 1.23.0 - '@shikijs/engine-oniguruma': 1.23.0 - '@shikijs/types': 1.23.0 + '@shikijs/core': 1.23.1 + '@shikijs/engine-javascript': 1.23.1 + '@shikijs/engine-oniguruma': 1.23.1 + '@shikijs/types': 1.23.1 '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 diff --git a/lede/include/kernel-5.15 b/lede/include/kernel-5.15 index 02ccce117b..2949af40be 100644 --- a/lede/include/kernel-5.15 +++ b/lede/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .162 -LINUX_KERNEL_HASH-5.15.162 = 91bfc0ea152ce7b102a0b79d35a7c92843874ebf085c99d2ba8b4d85e62b1a7c +LINUX_VERSION-5.15 = .173 +LINUX_KERNEL_HASH-5.15.173 = 8a4b2a47ccc9b208b2b6ed9a216ea1a5eb12852c723bec1a04de9e671a1d7da8 diff --git a/lede/include/kernel-6.1 b/lede/include/kernel-6.1 index 7044ddce1a..df52cf3047 100644 --- a/lede/include/kernel-6.1 +++ b/lede/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .117 -LINUX_KERNEL_HASH-6.1.117 = a8fbffe691974a3bf6a21d34eefad71a64c2a1fcc4513218356f1a87e390788b +LINUX_VERSION-6.1 = .118 +LINUX_KERNEL_HASH-6.1.118 = 010784bd7161c32c4cd68a423d4dcb14e4587677d238b2825a31fe012869224c diff --git a/lede/include/kernel-6.6 b/lede/include/kernel-6.6 index d870747f83..dfb1e855f8 100644 --- a/lede/include/kernel-6.6 +++ b/lede/include/kernel-6.6 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.6 = .61 -LINUX_KERNEL_HASH-6.6.61 = 418fc24df9190f1c3ed9906dc3b7651c2a2eae5c1cb9ab4a6348e20faf047c0b +LINUX_VERSION-6.6 = .62 +LINUX_KERNEL_HASH-6.6.62 = e2c35611775534941b9d4dd871f3ae5b988b6594dc9033b5ca784366e07d9336 diff --git a/lede/package/boot/uboot-rockchip/Makefile b/lede/package/boot/uboot-rockchip/Makefile index a3c9439c3a..ad25649706 100644 --- a/lede/package/boot/uboot-rockchip/Makefile +++ b/lede/package/boot/uboot-rockchip/Makefile @@ -46,6 +46,13 @@ define U-Boot/nanopi-r2s-rk3328 friendlyarm_nanopi-neo3 endef +define U-Boot/nanopi-r2s-plus-rk3328 + $(U-Boot/rk3328/Default) + NAME:=NanoPi R2S Plus + BUILD_DEVICES:= \ + friendlyarm_nanopi-r2s-plus +endef + define U-Boot/orangepi-r1-plus-rk3328 $(U-Boot/rk3328/Default) NAME:=Orange Pi R1 Plus @@ -355,6 +362,13 @@ define U-Boot/orangepi-5-rk3588s xunlong_orangepi-5 endef +define U-Boot/rock5a-rk3588s + $(U-Boot/rk3588/Default) + NAME:=ROCK 5A + BUILD_DEVICES:= \ + radxa_rock-5a +endef + UBOOT_TARGETS := \ nanopi-r3s-rk3566 \ panther-x2-rk3566 \ @@ -377,6 +391,7 @@ UBOOT_TARGETS := \ nanopi-r6c-rk3588s \ nanopi-r6s-rk3588s \ orangepi-5-rk3588s \ + rock5a-rk3588s \ dlfr100-rk3399 \ h3399pc-rk3399 \ fine3399-rk3399 \ @@ -392,6 +407,7 @@ UBOOT_TARGETS := \ xiaobao-nas-v1-rk3399 \ nanopi-r2c-rk3328 \ nanopi-r2s-rk3328 \ + nanopi-r2s-plus-rk3328 \ orangepi-r1-plus-rk3328 \ orangepi-r1-plus-lts-rk3328 diff --git a/lede/package/boot/uboot-rockchip/patches/303-rockchip-rk3328-Add-FriendlyARM-NanoPi-R2S-Plus.patch b/lede/package/boot/uboot-rockchip/patches/303-rockchip-rk3328-Add-FriendlyARM-NanoPi-R2S-Plus.patch new file mode 100644 index 0000000000..be8f643e7d --- /dev/null +++ b/lede/package/boot/uboot-rockchip/patches/303-rockchip-rk3328-Add-FriendlyARM-NanoPi-R2S-Plus.patch @@ -0,0 +1,242 @@ +From d6a55cc9e7e7d44b4b357818a9690e05af5d87e2 Mon Sep 17 00:00:00 2001 +From: Sergey Bostandzhyan +Date: Fri, 1 Nov 2024 22:21:29 +0000 +Subject: [PATCH] arm64: dts: rockchip: Add DTS for FriendlyARM NanoPi R2S Plus + +The R2S Plus is basically an R2S with additional eMMC. + +The eMMC configuration for the DTS has been extracted and copied from +rk3328-nanopi-r2.dts, v2017.09 branch from the friendlyarm/uboot-rockchip +repository. + +Signed-off-by: Sergey Bostandzhyan +Link: https://lore.kernel.org/r/20240814170048.23816-2-jin@mediatomb.cc +Signed-off-by: Heiko Stuebner + +[ upstream commit: b8c02878292200ebb5b4a8cfc9dbf227327908bd ] + +(cherry picked from commit c9bf98827964441f4dd16faa45bd4046f472e693) +Signed-off-by: Jonas Karlman +Reviewed-by: Kever Yang +--- + .../arm64/rockchip/rk3328-nanopi-r2s-plus.dts | 32 +++++++++++++++++++ + 1 file changed, 32 insertions(+) + create mode 100644 dts/upstream/src/arm64/rockchip/rk3328-nanopi-r2s-plus.dts + +diff --git a/dts/upstream/src/arm64/rockchip/rk3328-nanopi-r2s-plus.dts b/dts/upstream/src/arm64/rockchip/rk3328-nanopi-r2s-plus.dts +new file mode 100644 +index 000000000000..cb81ba3f23ff +--- /dev/null ++++ b/dts/upstream/src/arm64/rockchip/rk3328-nanopi-r2s-plus.dts +@@ -0,0 +1,32 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * (C) Copyright 2018 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ * ++ * (C) Copyright 2016 Rockchip Electronics Co., Ltd ++ */ ++ ++/dts-v1/; ++#include "rk3328-nanopi-r2s.dts" ++ ++/ { ++ compatible = "friendlyarm,nanopi-r2s-plus", "rockchip,rk3328"; ++ model = "FriendlyElec NanoPi R2S Plus"; ++ ++ aliases { ++ mmc1 = &emmc; ++ }; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ disable-wp; ++ mmc-hs200-1_8v; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ status = "okay"; ++}; +From 3133b7c645157846590f6fc16e26f54d70f5e1d6 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 1 Nov 2024 22:21:30 +0000 +Subject: [PATCH] board: rockchip: Add FriendlyElec NanoPi R2S Plus + +The FriendlyElec NanoPi R2S Plus is a single-board computer based on +Rockchip RK3328 SoC. It features e.g. 1 GB DDR4 RAM, 32 GB eMMC, +SD-card, 2x GbE LAN, optional M.2 SDIO Wi-Fi and 2x USB 2.0 host. + +Features tested on a NanoPi R2S Plus 2309: +- SD-card boot +- eMMC boot +- Ethernet +- USB gadget +- USB host + +Signed-off-by: Jonas Karlman +Reviewed-by: Kever Yang +--- + .../dts/rk3328-nanopi-r2s-plus-u-boot.dtsi | 3 + + board/rockchip/evb_rk3328/MAINTAINERS | 6 + + configs/nanopi-r2s-plus-rk3328_defconfig | 108 ++++++++++++++++++ + doc/board/rockchip/rockchip.rst | 1 + + 4 files changed, 118 insertions(+) + create mode 100644 arch/arm/dts/rk3328-nanopi-r2s-plus-u-boot.dtsi + create mode 100644 configs/nanopi-r2s-plus-rk3328_defconfig + +diff --git a/arch/arm/dts/rk3328-nanopi-r2s-plus-u-boot.dtsi b/arch/arm/dts/rk3328-nanopi-r2s-plus-u-boot.dtsi +new file mode 100644 +index 000000000000..2ab32cf00a1d +--- /dev/null ++++ b/arch/arm/dts/rk3328-nanopi-r2s-plus-u-boot.dtsi +@@ -0,0 +1,3 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#include "rk3328-nanopi-r2s-u-boot.dtsi" +diff --git a/board/rockchip/evb_rk3328/MAINTAINERS b/board/rockchip/evb_rk3328/MAINTAINERS +index 8f619e54e0e7..5f81be55b8e0 100644 +--- a/board/rockchip/evb_rk3328/MAINTAINERS ++++ b/board/rockchip/evb_rk3328/MAINTAINERS +@@ -28,6 +28,12 @@ F: configs/nanopi-r2s-rk3328_defconfig + F: arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi + F: arch/arm/dts/rk3328-nanopi-r2s.dts + ++NANOPI-R2S-PLUS-RK3328 ++M: Jonas Karlman ++S: Maintained ++F: configs/nanopi-r2s-plus-rk3328_defconfig ++F: arch/arm/dts/rk3328-nanopi-r2s-plus-u-boot.dtsi ++ + ORANGEPI-R1-PLUS-RK3328 + M: Tianling Shen + S: Maintained +diff --git a/configs/nanopi-r2s-plus-rk3328_defconfig b/configs/nanopi-r2s-plus-rk3328_defconfig +new file mode 100644 +index 000000000000..6e6785fcc882 +--- /dev/null ++++ b/configs/nanopi-r2s-plus-rk3328_defconfig +@@ -0,0 +1,108 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_COUNTER_FREQUENCY=24000000 ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SPL_GPIO=y ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_SF_DEFAULT_SPEED=20000000 ++CONFIG_ENV_OFFSET=0x3F8000 ++CONFIG_DEFAULT_DEVICE_TREE="rockchip/rk3328-nanopi-r2s-plus" ++CONFIG_DM_RESET=y ++CONFIG_ROCKCHIP_RK3328=y ++CONFIG_SYS_LOAD_ADDR=0x800800 ++CONFIG_DEBUG_UART_BASE=0xFF130000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++# CONFIG_ANDROID_BOOT_IMAGE is not set ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_FIT_SIGNATURE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_LEGACY_IMAGE_FORMAT=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-nanopi-r2s-plus.dtb" ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++CONFIG_SPL_MAX_SIZE=0x40000 ++CONFIG_SPL_PAD_TO=0x7f8000 ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_POWER=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y ++CONFIG_CMD_BOOTZ=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++CONFIG_CMD_ROCKUSB=y ++CONFIG_CMD_USB_MASS_STORAGE=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_TIME=y ++CONFIG_CMD_REGULATOR=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_TPL_OF_CONTROL=y ++CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_TPL_OF_PLATDATA=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_SYS_MMC_ENV_DEV=0 ++CONFIG_TPL_DM=y ++CONFIG_SPL_DM_SEQ_ALIAS=y ++CONFIG_REGMAP=y ++CONFIG_SPL_REGMAP=y ++CONFIG_TPL_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_SPL_SYSCON=y ++CONFIG_TPL_SYSCON=y ++CONFIG_CLK=y ++CONFIG_SPL_CLK=y ++CONFIG_FASTBOOT_BUF_ADDR=0x800800 ++CONFIG_FASTBOOT_CMD_OEM_FORMAT=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_PHY_MOTORCOMM=y ++CONFIG_PHY_REALTEK=y ++CONFIG_DM_MDIO=y ++CONFIG_DM_ETH_PHY=y ++CONFIG_PHY_GIGE=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_PHY_ROCKCHIP_INNO_USB2=y ++CONFIG_PINCTRL=y ++CONFIG_SPL_PINCTRL=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_SPL_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_RAM=y ++CONFIG_SPL_RAM=y ++CONFIG_TPL_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_ROCKCHIP=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYS_NS16550_MEM32=y ++CONFIG_SYSINFO=y ++CONFIG_SYSRESET=y ++# CONFIG_TPL_SYSRESET is not set ++CONFIG_USB=y ++CONFIG_DM_USB_GADGET=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_GADGET_DWC2_OTG=y ++CONFIG_USB_FUNCTION_ROCKUSB=y ++CONFIG_SPL_TINY_MEMSET=y ++CONFIG_TPL_TINY_MEMSET=y ++CONFIG_ERRNO_STR=y +diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst +index 3056e071f4ff..9bab86d23479 100644 +--- a/doc/board/rockchip/rockchip.rst ++++ b/doc/board/rockchip/rockchip.rst +@@ -65,6 +65,7 @@ List of mainline supported Rockchip boards: + - FriendlyElec NanoPi R2C (nanopi-r2c-rk3328) + - FriendlyElec NanoPi R2C Plus (nanopi-r2c-plus-rk3328) + - FriendlyElec NanoPi R2S (nanopi-r2s-rk3328) ++ - FriendlyElec NanoPi R2S Plus (nanopi-r2s-plus-rk3328) + - Pine64 Rock64 (rock64-rk3328) + - Radxa ROCK Pi E (rock-pi-e-rk3328) + - Xunlong Orange Pi R1 Plus (orangepi-r1-plus-rk3328) diff --git a/lede/package/kernel/mac80211/patches/build/236-fix-genlmsg_multicast_allns-build-error.patch b/lede/package/kernel/mac80211/patches/build/236-fix-genlmsg_multicast_allns-build-error.patch index 131a715694..c8bb51c3c1 100644 --- a/lede/package/kernel/mac80211/patches/build/236-fix-genlmsg_multicast_allns-build-error.patch +++ b/lede/package/kernel/mac80211/patches/build/236-fix-genlmsg_multicast_allns-build-error.patch @@ -147,7 +147,7 @@ Signed-off-by: Sasha Levin genlmsg_end(msg, hdr); -+#if LINUX_VERSION_IS_GEQ(6,1,115) && LINUX_VERSION_IS_LESS(6,1,999) ++#if (LINUX_VERSION_IS_GEQ(6,1,115) && LINUX_VERSION_IS_LESS(6,1,999)) || ((LINUX_VERSION_IS_GEQ(5,15,170) && LINUX_VERSION_IS_LESS(5,15,999))) + genlmsg_multicast_allns(&nl80211_fam, msg, 0, + NL80211_MCGRP_REGULATORY); +#else @@ -163,7 +163,7 @@ Signed-off-by: Sasha Levin genlmsg_end(msg, hdr); -+#if LINUX_VERSION_IS_GEQ(6,1,115) && LINUX_VERSION_IS_LESS(6,1,999) ++#if (LINUX_VERSION_IS_GEQ(6,1,115) && LINUX_VERSION_IS_LESS(6,1,999)) || ((LINUX_VERSION_IS_GEQ(5,15,170) && LINUX_VERSION_IS_LESS(5,15,999))) + genlmsg_multicast_allns(&nl80211_fam, msg, 0, + NL80211_MCGRP_REGULATORY); +#else diff --git a/lede/target/linux/bcm27xx/patches-6.6/950-0169-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch b/lede/target/linux/bcm27xx/patches-6.6/950-0169-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch index 5301066196..6e9ca2261b 100644 --- a/lede/target/linux/bcm27xx/patches-6.6/950-0169-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch +++ b/lede/target/linux/bcm27xx/patches-6.6/950-0169-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch @@ -33,7 +33,7 @@ Signed-off-by: Jonathan Bell #define USB_VENDOR_ID_BELKIN 0x050d #define USB_DEVICE_ID_FLIP_KVM 0x3201 -@@ -1404,6 +1407,9 @@ +@@ -1405,6 +1408,9 @@ #define USB_VENDOR_ID_XIAOMI 0x2717 #define USB_DEVICE_ID_MI_SILENT_MOUSE 0x5014 diff --git a/lede/target/linux/bcm27xx/patches-6.6/950-0359-mm-page_alloc-cma-introduce-a-customisable-threshold.patch b/lede/target/linux/bcm27xx/patches-6.6/950-0359-mm-page_alloc-cma-introduce-a-customisable-threshold.patch index 8c39ae9931..f8baf9befc 100644 --- a/lede/target/linux/bcm27xx/patches-6.6/950-0359-mm-page_alloc-cma-introduce-a-customisable-threshold.patch +++ b/lede/target/linux/bcm27xx/patches-6.6/950-0359-mm-page_alloc-cma-introduce-a-customisable-threshold.patch @@ -48,7 +48,7 @@ Signed-off-by: David Plowman /* * A cached value of the page's pageblock's migratetype, used when the page is * put on a pcplist. Used to avoid the pageblock migratetype lookup when -@@ -2095,12 +2116,13 @@ __rmqueue(struct zone *zone, unsigned in +@@ -2094,12 +2115,13 @@ __rmqueue(struct zone *zone, unsigned in if (IS_ENABLED(CONFIG_CMA)) { /* * Balance movable allocations between regular and CMA areas by diff --git a/lede/target/linux/bcm27xx/patches-6.6/950-1340-mm-numa-Allow-override-of-kernel-s-default-NUMA-poli.patch b/lede/target/linux/bcm27xx/patches-6.6/950-1340-mm-numa-Allow-override-of-kernel-s-default-NUMA-poli.patch index f0de0ce9d5..dceb6df45f 100644 --- a/lede/target/linux/bcm27xx/patches-6.6/950-1340-mm-numa-Allow-override-of-kernel-s-default-NUMA-poli.patch +++ b/lede/target/linux/bcm27xx/patches-6.6/950-1340-mm-numa-Allow-override-of-kernel-s-default-NUMA-poli.patch @@ -23,7 +23,7 @@ Signed-off-by: Tvrtko Ursulin --- a/mm/mempolicy.c +++ b/mm/mempolicy.c -@@ -2974,7 +2974,9 @@ void __init numa_policy_init(void) +@@ -2963,7 +2963,9 @@ void __init numa_policy_init(void) /* Reset policy of current process to default */ void numa_default_policy(void) { @@ -34,7 +34,7 @@ Signed-off-by: Tvrtko Ursulin } /* -@@ -2992,7 +2994,6 @@ static const char * const policy_modes[] +@@ -2981,7 +2983,6 @@ static const char * const policy_modes[] }; @@ -42,7 +42,7 @@ Signed-off-by: Tvrtko Ursulin /** * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option. * @str: string containing mempolicy to parse -@@ -3005,13 +3006,18 @@ static const char * const policy_modes[] +@@ -2994,13 +2995,18 @@ static const char * const policy_modes[] */ int mpol_parse_str(char *str, struct mempolicy **mpol) { @@ -62,7 +62,7 @@ Signed-off-by: Tvrtko Ursulin if (flags) *flags++ = '\0'; /* terminate mode string */ -@@ -3090,9 +3096,16 @@ int mpol_parse_str(char *str, struct mem +@@ -3079,9 +3085,16 @@ int mpol_parse_str(char *str, struct mem goto out; } @@ -82,7 +82,7 @@ Signed-off-by: Tvrtko Ursulin /* * Save nodes for mpol_to_str() to show the tmpfs mount options -@@ -3125,7 +3138,29 @@ out: +@@ -3114,7 +3127,29 @@ out: *mpol = new; return err; } diff --git a/lede/target/linux/generic/backport-5.15/020-v6.1-05-mm-multi-gen-LRU-groundwork.patch b/lede/target/linux/generic/backport-5.15/020-v6.1-05-mm-multi-gen-LRU-groundwork.patch index ff4bb4df3e..ce7ab38ed9 100644 --- a/lede/target/linux/generic/backport-5.15/020-v6.1-05-mm-multi-gen-LRU-groundwork.patch +++ b/lede/target/linux/generic/backport-5.15/020-v6.1-05-mm-multi-gen-LRU-groundwork.patch @@ -582,7 +582,7 @@ Signed-off-by: Andrew Morton endmenu --- a/mm/huge_memory.c +++ b/mm/huge_memory.c -@@ -2366,7 +2366,8 @@ static void __split_huge_page_tail(struc +@@ -2362,7 +2362,8 @@ static void __split_huge_page_tail(struc #ifdef CONFIG_64BIT (1L << PG_arch_2) | #endif @@ -594,7 +594,7 @@ Signed-off-by: Andrew Morton VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING, --- a/mm/memcontrol.c +++ b/mm/memcontrol.c -@@ -5179,6 +5179,7 @@ static void __mem_cgroup_free(struct mem +@@ -5199,6 +5199,7 @@ static void __mem_cgroup_free(struct mem static void mem_cgroup_free(struct mem_cgroup *memcg) { @@ -602,17 +602,17 @@ Signed-off-by: Andrew Morton memcg_wb_domain_exit(memcg); __mem_cgroup_free(memcg); } -@@ -5242,6 +5243,7 @@ static struct mem_cgroup *mem_cgroup_all - memcg->deferred_split_queue.split_queue_len = 0; - #endif +@@ -5262,6 +5263,7 @@ static struct mem_cgroup *mem_cgroup_all + spin_lock(&memcg_idr_lock); idr_replace(&mem_cgroup_idr, memcg, memcg->id.id); + spin_unlock(&memcg_idr_lock); + lru_gen_init_memcg(memcg); return memcg; fail: mem_cgroup_id_remove(memcg); --- a/mm/memory.c +++ b/mm/memory.c -@@ -4805,6 +4805,27 @@ static inline void mm_account_fault(stru +@@ -4821,6 +4821,27 @@ static inline void mm_account_fault(stru perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address); } @@ -640,7 +640,7 @@ Signed-off-by: Andrew Morton /* * By the time we get here, we already hold the mm semaphore * -@@ -4836,11 +4857,15 @@ vm_fault_t handle_mm_fault(struct vm_are +@@ -4852,11 +4873,15 @@ vm_fault_t handle_mm_fault(struct vm_are if (flags & FAULT_FLAG_USER) mem_cgroup_enter_user_fault(); diff --git a/lede/target/linux/generic/hack-5.15/645-netfilter-connmark-introduce-set-dscpmark.patch b/lede/target/linux/generic/hack-5.15/645-netfilter-connmark-introduce-set-dscpmark.patch index c368c4ae3b..9ad5a4b6d4 100644 --- a/lede/target/linux/generic/hack-5.15/645-netfilter-connmark-introduce-set-dscpmark.patch +++ b/lede/target/linux/generic/hack-5.15/645-netfilter-connmark-introduce-set-dscpmark.patch @@ -195,20 +195,37 @@ Signed-off-by: Kevin Darbyshire-Bryant return connmark_tg_shift(skb, info); } -@@ -167,6 +194,16 @@ static struct xt_target connmark_tg_reg[ - .targetsize = sizeof(struct xt_connmark_tginfo2), +@@ -168,6 +195,16 @@ static struct xt_target connmark_tg_reg[ .destroy = connmark_tg_destroy, .me = THIS_MODULE, -+ }, + }, + { + .name = "CONNMARK", + .revision = 3, -+ .family = NFPROTO_UNSPEC, ++ .family = NFPROTO_IPV4, + .checkentry = connmark_tg_check, + .target = connmark_tg_v3, + .targetsize = sizeof(struct xt_connmark_tginfo3), + .destroy = connmark_tg_destroy, + .me = THIS_MODULE, - } ++ }, + #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) + { + .name = "CONNMARK", +@@ -189,6 +226,16 @@ static struct xt_target connmark_tg_reg[ + .destroy = connmark_tg_destroy, + .me = THIS_MODULE, + }, ++ { ++ .name = "CONNMARK", ++ .revision = 3, ++ .family = NFPROTO_IPV6, ++ .checkentry = connmark_tg_check, ++ .target = connmark_tg_v3, ++ .targetsize = sizeof(struct xt_connmark_tginfo3), ++ .destroy = connmark_tg_destroy, ++ .me = THIS_MODULE, ++ }, + #endif }; diff --git a/lede/target/linux/generic/pending-5.15/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch b/lede/target/linux/generic/pending-5.15/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch deleted file mode 100644 index 5216d6a706..0000000000 --- a/lede/target/linux/generic/pending-5.15/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch +++ /dev/null @@ -1,32 +0,0 @@ -From f7982c726e02001afc19052fe48f642dfcbc00b2 Mon Sep 17 00:00:00 2001 -From: Vincent Tremblay -Date: Mon, 26 Dec 2022 21:10:37 -0500 -Subject: [PATCH 1/2] spidev: Add Silicon Labs EM3581 device compatible - -Add compatible string for Silicon Labs EM3581 device. - -Note: This patch is adapted from a patch submitted to the for-next branch (v6.3). - -Signed-off-by: Vincent Tremblay ---- - drivers/spi/spidev.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/spi/spidev.c -+++ b/drivers/spi/spidev.c -@@ -691,6 +691,7 @@ static const struct spi_device_id spidev - { .name = "m53cpld" }, - { .name = "spi-petra" }, - { .name = "spi-authenta" }, -+ { .name = "em3581" }, - {}, - }; - MODULE_DEVICE_TABLE(spi, spidev_spi_ids); -@@ -705,6 +706,7 @@ static const struct of_device_id spidev_ - { .compatible = "menlo,m53cpld" }, - { .compatible = "cisco,spi-petra" }, - { .compatible = "micron,spi-authenta" }, -+ { .compatible = "silabs,em3581" }, - {}, - }; - MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/lede/target/linux/generic/pending-5.15/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch b/lede/target/linux/generic/pending-5.15/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch index ffbed0c622..799494e55c 100644 --- a/lede/target/linux/generic/pending-5.15/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch +++ b/lede/target/linux/generic/pending-5.15/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch @@ -14,7 +14,7 @@ Signed-off-by: Vincent Tremblay --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c -@@ -692,6 +692,7 @@ static const struct spi_device_id spidev +@@ -693,6 +693,7 @@ static const struct spi_device_id spidev { .name = "spi-petra" }, { .name = "spi-authenta" }, { .name = "em3581" }, @@ -22,11 +22,11 @@ Signed-off-by: Vincent Tremblay {}, }; MODULE_DEVICE_TABLE(spi, spidev_spi_ids); -@@ -707,6 +708,7 @@ static const struct of_device_id spidev_ - { .compatible = "cisco,spi-petra" }, - { .compatible = "micron,spi-authenta" }, - { .compatible = "silabs,em3581" }, -+ { .compatible = "silabs,si3210" }, +@@ -722,6 +723,7 @@ static const struct of_device_id spidev_ + { .compatible = "rohm,dh2228fv", .data = &spidev_of_check }, + { .compatible = "semtech,sx1301", .data = &spidev_of_check }, + { .compatible = "silabs,em3581", .data = &spidev_of_check }, ++ { .compatible = "silabs,si3210", .data = &spidev_of_check }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/lede/target/linux/generic/pending-5.15/901-usb-add-more-modem-support.patch b/lede/target/linux/generic/pending-5.15/901-usb-add-more-modem-support.patch deleted file mode 100644 index 91f621126e..0000000000 --- a/lede/target/linux/generic/pending-5.15/901-usb-add-more-modem-support.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -1424,6 +1424,9 @@ static const struct usb_device_id produc - {QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */ - {QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */ - {QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */ -+ {QMI_FIXED_INTF(0x2077, 0x2002, 4)}, /* T&W TW04C */ -+ {QMI_FIXED_INTF(0x2077, 0x2003, 4)}, /* T&W TW12G */ -+ {QMI_FIXED_INTF(0x2077, 0x2004, 4)}, /* T&W TW510M */ - - /* 4. Gobi 1000 devices */ - {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -2310,9 +2310,13 @@ static const struct usb_device_id option - { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */ - { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */ - { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ -+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1402, 0xff) }, /* GosunCn GM800 (Download mode) */ -+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1403, 0xff) }, /* GosunCn GM800 (rmnet, old) */ - { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ - { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ - { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */ -+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1421, 0xff) }, /* GosunCn GM800 (rmnet) */ -+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1422, 0xff) }, /* GosunCn GM800 (EAP) */ - { USB_DEVICE(0x33f8, 0x0104), /* Rolling RW101-GL (laptop RMNET) */ - .driver_info = RSVD(4) | RSVD(5) }, - { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a2, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */ diff --git a/lede/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds b/lede/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds index 18e184052f..7db3d26457 100755 --- a/lede/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds +++ b/lede/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds @@ -11,6 +11,7 @@ board_config_update case $board in friendlyarm,nanopi-r2c|\ friendlyarm,nanopi-r2s|\ +friendlyarm,nanopi-r2s-plus|\ friendlyarm,nanopi-r4s|\ friendlyarm,nanopi-r6c|\ sharevdi,guangmiao-g4c|\ diff --git a/lede/target/linux/rockchip/armv8/base-files/etc/board.d/02_network b/lede/target/linux/rockchip/armv8/base-files/etc/board.d/02_network index 1e8897938c..c982b66e50 100755 --- a/lede/target/linux/rockchip/armv8/base-files/etc/board.d/02_network +++ b/lede/target/linux/rockchip/armv8/base-files/etc/board.d/02_network @@ -15,6 +15,7 @@ rockchip_setup_interfaces() ezpro,mrkaio-m68s-plus|\ friendlyarm,nanopi-r2c|\ friendlyarm,nanopi-r2s|\ + friendlyarm,nanopi-r2s-plus|\ friendlyarm,nanopi-r4s|\ friendlyarm,nanopi-r4se|\ friendlyarm,nanopi-r6c|\ @@ -107,6 +108,7 @@ rockchip_setup_macs() friendlyarm,nanopc-t6|\ friendlyarm,nanopi-r2c|\ friendlyarm,nanopi-r2s|\ + friendlyarm,nanopi-r2s-plus|\ hinlink,opc-h28k|\ hinlink,opc-h66k|\ hinlink,opc-h68k|\ diff --git a/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts index a7a55d68db..c6018e7bdb 100644 --- a/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts +++ b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts @@ -24,6 +24,11 @@ ethernet0 = &gmac1; mmc0 = &sdmmc0; mmc1 = &sdhci; + + led-boot = &power_led; + led-failsafe = &power_led; + led-running = &power_led; + led-upgrade = &power_led; }; chosen: chosen { diff --git a/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts new file mode 100644 index 0000000000..9645fc9cc7 --- /dev/null +++ b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -0,0 +1,790 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include +#include "rk3588s.dtsi" + +/ { + model = "Radxa ROCK 5A"; + compatible = "radxa,rock-5a", "rockchip,rk3588s"; + + aliases { + ethernet0 = &gmac1; + mmc0 = &sdhci; + mmc1 = &sdmmc; + + led-boot = &status_led; + led-failsafe = &status_led; + led-running = &status_led; + led-upgrade = &status_led; + }; + + analog-sound { + compatible = "audio-graph-card"; + label = "rk3588-es8316"; + + widgets = "Microphone", "Mic Jack", + "Headphone", "Headphones"; + + routing = "MIC2", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR"; + + dais = <&i2s0_8ch_p0>; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&io_led>; + + status_led: io-led { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + cooling-levels = <0 95 145 195 255>; + fan-supply = <&vcc_5v0>; + pwms = <&pwm3 0 50000 0>; + #cooling-cells = <2>; + }; + + vcc12v_dcin: vcc12v-dcin-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc3v3_wf: vcc3v3-wf-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_wf"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&pow_en>; + pinctrl-names = "default"; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc_5v0: vcc-5v0-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + enable-active-high; + gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_5v0_en>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_npu_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + eeprom: eeprom@50 { + compatible = "belling,bl24c16a", "atmel,24c16"; + reg = <0x50>; + pagesize = <16>; + }; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5m2_xfer>; +}; + +&i2c7 { + status = "okay"; + + es8316: audio-codec@11 { + compatible = "everest,es8316"; + reg = <0x11>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + clock-names = "mclk"; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + assigned-clock-rates = <12288000>; + #sound-dai-cells = <0>; + + port { + es8316_p0_0: endpoint { + remote-endpoint = <&i2s0_8ch_p0_0>; + }; + }; + }; +}; + +&i2s0_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_lrck + &i2s0_mclk + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; + status = "okay"; + + i2s0_8ch_p0: port { + i2s0_8ch_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&es8316_p0_0>; + }; + }; +}; + +&gmac1 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii"; + pinctrl-0 = <&gmac1_miim + &gmac1_tx_bus2 + &gmac1_rx_bus2 + &gmac1_rgmii_clk + &gmac1_rgmii_bus>; + pinctrl-names = "default"; + tx_delay = <0x3a>; + rx_delay = <0x3e>; + status = "okay"; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@1 { + /* RTL8211F */ + compatible = "ethernet-phy-id001c.c916"; + reg = <0x1>; + pinctrl-names = "default"; + pinctrl-0 = <&rtl8211f_rst>; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; +}; + +&pcie2x1l2 { + pinctrl-0 = <&pcie20x1m0_pins>; + pinctrl-names = "default"; + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_wf>; + status = "okay"; +}; + +&pinctrl { + leds { + io_led: io-led { + rockchip,pins = <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie { + pow_en: pow-en { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + power { + vcc_5v0_en: vcc-5v0-en { + rockchip,pins = <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + rtl8211f { + rtl8211f_rst: rtl8211f-rst { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm3 { + pinctrl-names = "default"; + pinctrl-0 = <&pwm3m1_pins>; + status = "okay"; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + max-frequency = <150000000>; + no-sdio; + no-mmc; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s0>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&sfc { + pinctrl-names = "default"; + pinctrl-0 = <&fspim0_pins>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <104000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + num-cs = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + spi-max-frequency = <1000000>; + system-power-controller; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-name = "vdd_gpu_s0"; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-name = "vdd_cpu_lit_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-name = "vdd_log_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-name = "vdd_vdenc_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-name = "vdd_ddr_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-name = "vdd2_ddr_s3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-name = "vdd_2v0_pldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-name = "vcc_3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-name = "vddq_ddr_s0"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-name = "vcc_1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-name = "avcc_1v8_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-name = "vcc_1v8_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-name = "avdd_1v2_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-name = "vcc_3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-name = "vccio_sd_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-name = "pldo6_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-name = "vdd_0v75_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-name = "vdd_ddr_pll_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-name = "avdd_0v75_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-name = "vdd_0v85_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-name = "vdd_0v75_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy2_host { + status = "okay"; + phy-supply = <&vcc5v0_host>; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&usbdp_phy0 { + status = "okay"; + rockchip,dp-lane-mux = <2 3>; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host2_xhci { + status = "okay"; +}; diff --git a/lede/target/linux/rockchip/image/armv8.mk b/lede/target/linux/rockchip/image/armv8.mk index b304d33659..9329eaf32a 100644 --- a/lede/target/linux/rockchip/image/armv8.mk +++ b/lede/target/linux/rockchip/image/armv8.mk @@ -164,6 +164,16 @@ define Device/friendlyarm_nanopi-r2s endef TARGET_DEVICES += friendlyarm_nanopi-r2s +define Device/friendlyarm_nanopi-r2s-plus + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPi R2S Plus + SOC := rk3328 + UBOOT_DEVICE_NAME := nanopi-r2s-plus-rk3328 + IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-bin | gzip | append-metadata + DEVICE_PACKAGES := kmod-usb-net-rtl8152 +endef +TARGET_DEVICES += friendlyarm_nanopi-r2s-plus + define Device/friendlyarm_nanopi-r3s DEVICE_VENDOR := FriendlyARM DEVICE_MODEL := NanoPi R3S @@ -374,6 +384,16 @@ define Device/radxa_rock-pi-4 endef TARGET_DEVICES += radxa_rock-pi-4 +define Device/radxa_rock-5a + DEVICE_VENDOR := Radxa + DEVICE_MODEL := ROCK 5A + SOC := rk3588s + UBOOT_DEVICE_NAME := rock5a-rk3588s + IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-hwmon-pwmfan +endef +TARGET_DEVICES += radxa_rock-5a + define Device/rongpin_king3399 DEVICE_VENDOR := Rongpin DEVICE_MODEL := King3399 diff --git a/lede/target/linux/rockchip/patches-6.6/050-08-v6.8-arm64-dts-rockchip-move-rk3588-serial-aliases-to-soc-dtsi.patch b/lede/target/linux/rockchip/patches-6.6/050-08-v6.8-arm64-dts-rockchip-move-rk3588-serial-aliases-to-soc-dtsi.patch index fda9d09def..ca77a3a63b 100644 --- a/lede/target/linux/rockchip/patches-6.6/050-08-v6.8-arm64-dts-rockchip-move-rk3588-serial-aliases-to-soc-dtsi.patch +++ b/lede/target/linux/rockchip/patches-6.6/050-08-v6.8-arm64-dts-rockchip-move-rk3588-serial-aliases-to-soc-dtsi.patch @@ -25,7 +25,6 @@ Link: https://lore.kernel.org/r/20231205164842.556684-2-heiko@sntech.de .../boot/dts/rockchip/rk3588s-indiedroid-nova.dts | 1 - .../boot/dts/rockchip/rk3588s-khadas-edge2.dts | 1 - arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts | 1 - - arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 1 - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 13 +++++++++++++ 13 files changed, 13 insertions(+), 19 deletions(-) @@ -95,16 +94,6 @@ Link: https://lore.kernel.org/r/20231205164842.556684-2-heiko@sntech.de }; chosen { ---- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -@@ -14,7 +14,6 @@ - aliases { - mmc0 = &sdhci; - mmc1 = &sdmmc; -- serial2 = &uart2; - }; - - analog-sound { --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -18,6 +18,19 @@ diff --git a/lede/target/linux/rockchip/patches-6.6/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch b/lede/target/linux/rockchip/patches-6.6/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch index ea311951be..cef31ad0fa 100644 --- a/lede/target/linux/rockchip/patches-6.6/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch +++ b/lede/target/linux/rockchip/patches-6.6/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch @@ -36,9 +36,9 @@ to status_led in accordance with the board schematics. --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -17,6 +17,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-ev - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c-plus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s-plus.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-neo3.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb diff --git a/mihomo/.github/workflows/build.yml b/mihomo/.github/workflows/build.yml index ee498d3a70..56c7b66d78 100644 --- a/mihomo/.github/workflows/build.yml +++ b/mihomo/.github/workflows/build.yml @@ -104,31 +104,24 @@ jobs: - uses: actions/checkout@v4 - name: Set up Go - if: ${{ matrix.jobs.goversion == '' && matrix.jobs.goarch != 'loong64' }} + if: ${{ matrix.jobs.goversion == '' && matrix.jobs.abi != '1' }} uses: actions/setup-go@v5 with: go-version: '1.23' - name: Set up Go - if: ${{ matrix.jobs.goversion != '' && matrix.jobs.goarch != 'loong64' }} + if: ${{ matrix.jobs.goversion != '' && matrix.jobs.abi != '1' }} uses: actions/setup-go@v5 with: go-version: ${{ matrix.jobs.goversion }} - - name: Set up Go1.22 loongarch abi1 + - name: Set up Go1.23 loongarch abi1 if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '1' }} run: | wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.23.0/go1.23.0.linux-amd64-abi1.tar.gz sudo tar zxf go1.23.0.linux-amd64-abi1.tar.gz -C /usr/local echo "/usr/local/go/bin" >> $GITHUB_PATH - # - name: Set up Go1.22 loongarch abi2 - # if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '2' }} - # run: | - # wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/go1.22.4.linux-amd64-abi2.tar.gz - # sudo tar zxf go1.22.4.linux-amd64-abi2.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.23.x # that means after golang1.24 release it must be changed diff --git a/mihomo/adapter/inbound/auth.go b/mihomo/adapter/inbound/auth.go index 984c9bd68e..8317274687 100644 --- a/mihomo/adapter/inbound/auth.go +++ b/mihomo/adapter/inbound/auth.go @@ -34,12 +34,5 @@ func SkipAuthRemoteAddress(addr string) bool { } func skipAuth(addr netip.Addr) bool { - if addr.IsValid() { - for _, prefix := range skipAuthPrefixes { - if prefix.Contains(addr.Unmap()) { - return true - } - } - } - return false + return prefixesContains(skipAuthPrefixes, addr) } diff --git a/mihomo/adapter/inbound/ipfilter.go b/mihomo/adapter/inbound/ipfilter.go index 7fa218c1f9..872d0c85a1 100644 --- a/mihomo/adapter/inbound/ipfilter.go +++ b/mihomo/adapter/inbound/ipfilter.go @@ -31,27 +31,17 @@ func IsRemoteAddrDisAllowed(addr net.Addr) bool { if err := m.SetRemoteAddr(addr); err != nil { return false } - return isAllowed(m.AddrPort().Addr().Unmap()) && !isDisAllowed(m.AddrPort().Addr().Unmap()) + ipAddr := m.AddrPort().Addr() + if ipAddr.IsValid() { + return isAllowed(ipAddr) && !isDisAllowed(ipAddr) + } + return false } func isAllowed(addr netip.Addr) bool { - if addr.IsValid() { - for _, prefix := range lanAllowedIPs { - if prefix.Contains(addr) { - return true - } - } - } - return false + return prefixesContains(lanAllowedIPs, addr) } func isDisAllowed(addr netip.Addr) bool { - if addr.IsValid() { - for _, prefix := range lanDisAllowedIPs { - if prefix.Contains(addr) { - return true - } - } - } - return false + return prefixesContains(lanDisAllowedIPs, addr) } diff --git a/mihomo/adapter/inbound/util.go b/mihomo/adapter/inbound/util.go index 743337fc12..3bcd280895 100644 --- a/mihomo/adapter/inbound/util.go +++ b/mihomo/adapter/inbound/util.go @@ -61,3 +61,19 @@ func parseHTTPAddr(request *http.Request) *C.Metadata { return metadata } + +func prefixesContains(prefixes []netip.Prefix, addr netip.Addr) bool { + if len(prefixes) == 0 { + return false + } + if !addr.IsValid() { + return false + } + addr = addr.Unmap().WithZone("") // netip.Prefix.Contains returns false if ip has an IPv6 zone + for _, prefix := range prefixes { + if prefix.Contains(addr) { + return true + } + } + return false +} diff --git a/mihomo/rules/common/ipcidr.go b/mihomo/rules/common/ipcidr.go index 663c9397c9..9c159502b4 100644 --- a/mihomo/rules/common/ipcidr.go +++ b/mihomo/rules/common/ipcidr.go @@ -40,7 +40,7 @@ func (i *IPCIDR) Match(metadata *C.Metadata) (bool, string) { if i.isSourceIP { ip = metadata.SrcIP } - return ip.IsValid() && i.ipnet.Contains(ip), i.adapter + return ip.IsValid() && i.ipnet.Contains(ip.WithZone("")), i.adapter } func (i *IPCIDR) Adapter() string { diff --git a/openwrt-packages/luci-app-store/luasrc/controller/store.lua b/openwrt-packages/luci-app-store/luasrc/controller/store.lua index 4cb527eee6..cbde2eafb7 100644 --- a/openwrt-packages/luci-app-store/luasrc/controller/store.lua +++ b/openwrt-packages/luci-app-store/luasrc/controller/store.lua @@ -354,7 +354,9 @@ function store_action(param) uci:set("istore", "istore", "last_path", autopath) uci:commit("istore") end - autoenv = autoenv .. " enable=" .. autoenable + if autoenable ~= nil then + autoenv = autoenv .. " enable=" .. autoenable + end code, out, err = _action(myopkg, luci.util.shellquote(autoenv), action, metapkg) else code, out, err = _action(myopkg, action, metapkg) diff --git a/openwrt-passwall/luci-app-passwall/Makefile b/openwrt-passwall/luci-app-passwall/Makefile index db3778313e..eaa3e9bff4 100644 --- a/openwrt-passwall/luci-app-passwall/Makefile +++ b/openwrt-passwall/luci-app-passwall/Makefile @@ -6,8 +6,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall -PKG_VERSION:=4.78-4 -PKG_RELEASE:= +PKG_VERSION:=24.11.18 +PKG_RELEASE:=3 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_sing-box.lua b/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_sing-box.lua index 6a74cd40a1..d4f516878b 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_sing-box.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_sing-box.lua @@ -927,11 +927,9 @@ function gen_config(var) if node.protocol == "_shunt" then local rules = {} - local preproxy_enabled = node.preproxy_enabled == "1" - local preproxy_rule_name = "main" - local preproxy_tag = "main" - local preproxy_node_id = node["main_node"] - local preproxy_node = preproxy_enabled and preproxy_node_id and uci:get_all(appname, preproxy_node_id) or nil + local preproxy_rule_name = node.preproxy_enabled == "1" and "main" or nil + local preproxy_tag = preproxy_rule_name + local preproxy_node_id = preproxy_rule_name and node["main_node"] or nil local function gen_shunt_node(rule_name, _node_id) if not rule_name then return nil, nil end @@ -956,7 +954,6 @@ function gen_config(var) } local _outbound = gen_outbound(flag, _node, rule_name) if _outbound then - _outbound.tag = _outbound.tag .. ":" .. _node.remarks table.insert(outbounds, _outbound) rule_outboundTag = _outbound.tag end @@ -966,10 +963,10 @@ function gen_config(var) if not _node then return nil, nil end if api.is_normal_node(_node) then - local proxy = preproxy_enabled and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id + local use_proxy = preproxy_tag and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id local copied_outbound for index, value in ipairs(outbounds) do - if value["_id"] == _node_id and value["_flag_proxy_tag"] == preproxy_tag then + if value["_id"] == _node_id and value["_flag_proxy_tag"] == (use_proxy and preproxy_tag or nil) then copied_outbound = api.clone(value) break end @@ -979,7 +976,7 @@ function gen_config(var) table.insert(outbounds, copied_outbound) rule_outboundTag = copied_outbound.tag else - if proxy then + if use_proxy then local pre_proxy = nil if _node.type ~= "sing-box" then pre_proxy = true @@ -1006,7 +1003,7 @@ function gen_config(var) end end - local _outbound = gen_outbound(flag, _node, rule_name, { tag = proxy and preproxy_tag or nil }) + local _outbound = gen_outbound(flag, _node, rule_name, { tag = use_proxy and preproxy_tag or nil }) if _outbound then _outbound.tag = _outbound.tag .. ":" .. _node.remarks rule_outboundTag = set_outbound_detour(_node, _outbound, outbounds, rule_name) @@ -1030,12 +1027,10 @@ function gen_config(var) return rule_outboundTag end - if preproxy_node then + if preproxy_tag and preproxy_node_id then local preproxy_outboundTag = gen_shunt_node(preproxy_rule_name, preproxy_node_id) if preproxy_outboundTag then preproxy_tag = preproxy_outboundTag - else - preproxy_node = nil end end --default_node diff --git a/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua b/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua index 04d46f0568..90137784b5 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -758,16 +758,15 @@ function gen_config(var) end -- new balancer local blc_nodes = _node.balancing_node - local length = #blc_nodes local valid_nodes = {} - for i = 1, length do + for i = 1, #blc_nodes do local blc_node_id = blc_nodes[i] local blc_node_tag = "blc-" .. blc_node_id local is_new_blc_node = true for _, outbound in ipairs(outbounds) do - if outbound.tag == blc_node_tag then + if outbound.tag:find("^" .. blc_node_tag) == 1 then is_new_blc_node = false - valid_nodes[#valid_nodes + 1] = blc_node_tag + valid_nodes[#valid_nodes + 1] = outbound.tag break end end @@ -777,20 +776,22 @@ function gen_config(var) if outbound then outbound.tag = outbound.tag .. ":" .. blc_node.remarks table.insert(outbounds, outbound) - valid_nodes[#valid_nodes + 1] = blc_node_tag + valid_nodes[#valid_nodes + 1] = outbound.tag end end end if #valid_nodes == 0 then return nil end -- fallback node + local fallback_node_tag = nil local fallback_node_id = _node.fallback_node - if fallback_node_id == "" then fallback_node_id = nil end + if fallback_node_id == "" or fallback_node_id == "nil" then fallback_node_id = nil end if fallback_node_id then local is_new_node = true for _, outbound in ipairs(outbounds) do - if outbound.tag == fallback_node_id then + if outbound.tag:find("^" .. fallback_node_id) == 1 then is_new_node = false + fallback_node_tag = outbound.tag break end end @@ -801,12 +802,7 @@ function gen_config(var) if outbound then outbound.tag = outbound.tag .. ":" .. fallback_node.remarks table.insert(outbounds, outbound) - else - fallback_node_id = nil - end - else - if not gen_balancer(fallback_node) then - fallback_node_id = nil + fallback_node_tag = outbound.tag end end end @@ -814,10 +810,10 @@ function gen_config(var) table.insert(balancers, { tag = balancer_tag, selector = valid_nodes, - fallbackTag = fallback_node_id, + fallbackTag = fallback_node_tag, strategy = { type = _node.balancingStrategy or "random" } }) - if _node.balancingStrategy == "leastPing" or fallback_node_id then + if _node.balancingStrategy == "leastPing" or fallback_node_tag then if not observatory then observatory = { subjectSelector = { "blc-" }, @@ -1192,13 +1188,8 @@ function gen_config(var) --[[ local default_dns_flag = "remote" - if node_id and tcp_redir_port then - local node = uci:get_all(appname, node_id) - if node.protocol == "_shunt" then - if node.default_node == "_direct" then - default_dns_flag = "direct" - end - end + if (not COMMON.default_balancer_tag and not COMMON.default_outbound_tag) or COMMON.default_outbound_tag == "direct" then + default_dns_flag = "direct" end if dns.servers and #dns.servers > 0 then @@ -1241,7 +1232,9 @@ function gen_config(var) } }) else - if COMMON.default_outbound_tag then + if COMMON.default_balancer_tag then + dns_outbound_tag = nil + elseif COMMON.default_outbound_tag then dns_outbound_tag = COMMON.default_outbound_tag end end @@ -1262,9 +1255,9 @@ function gen_config(var) table.insert(outbounds, { tag = "dns-out", protocol = "dns", - proxySettings = { + proxySettings = dns_outbound_tag and { tag = dns_outbound_tag - }, + } or nil, settings = { address = remote_dns_tcp_server, port = tonumber(remote_dns_tcp_port), @@ -1288,6 +1281,7 @@ function gen_config(var) remote_dns_tcp_server }, port = tonumber(remote_dns_tcp_port), + balancerTag = COMMON.default_balancer_tag, outboundTag = dns_outbound_tag }) if _remote_dns_host then @@ -1299,6 +1293,7 @@ function gen_config(var) _remote_dns_host }, port = tonumber(remote_dns_doh_port), + balancerTag = COMMON.default_balancer_tag, outboundTag = dns_outbound_tag }) end @@ -1311,6 +1306,7 @@ function gen_config(var) remote_dns_doh_ip }, port = tonumber(remote_dns_doh_port), + balancerTag = COMMON.default_balancer_tag, outboundTag = dns_outbound_tag }) end diff --git a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm index 849bb6dac4..6a15a52f71 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm +++ b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm @@ -812,6 +812,11 @@ local api = require "luci.passwall.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); @@ -851,7 +856,7 @@ local api = require "luci.passwall.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } } } else { @@ -922,6 +927,11 @@ local api = require "luci.passwall.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); @@ -961,7 +971,7 @@ local api = require "luci.passwall.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } if (m.hash) { @@ -1001,8 +1011,13 @@ local api = require "luci.passwall.api" ssm.net = ssm.net.toLowerCase(); if (ssm.net === "kcp" || ssm.net === "mkcp") ssm.net = "mkcp" + if (dom_prefix == "singbox_" && ssm.net === "raw") { + ssm.net = "tcp"; + } else if (dom_prefix == "xray_" && ssm.net === "tcp") { + ssm.net = "raw"; + } opt.set(dom_prefix + 'transport', ssm.net); - if (ssm.net === "raw") { + if (ssm.net === "raw" || ssm.net === "tcp") { opt.set(dom_prefix + 'tcp_guise', (ssm.host && ssm.path) ? "http" : "none"); if (ssm.host && ssm.path) { opt.set(dom_prefix + 'tcp_guise_http_host', ssm.host); @@ -1109,6 +1124,11 @@ local api = require "luci.passwall.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); @@ -1148,7 +1168,7 @@ local api = require "luci.passwall.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } else if (queryParam.type === "xhttp" || queryParam.type === "splithttp") { opt.set(dom_prefix + 'xhttp_host', queryParam.host || ""); opt.set(dom_prefix + 'xhttp_path', queryParam.path || ""); diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 73f5fb7eb9..ada7b9b88a 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -442,10 +442,13 @@ local function processData(szType, content, add_mode, add_from) -- result.mux = 1 -- result.mux_concurrency = 8 - if not info.net then - info.net = "tcp" - end + if not info.net then info.net = "tcp" end info.net = string.lower(info.net) + if result.type == "sing-box" and info.net == "raw" then + info.net = "tcp" + elseif result.type == "Xray" and info.net == "tcp" then + info.net = "raw" + end result.transport = info.net if info.net == 'ws' then result.ws_host = info.host @@ -514,7 +517,7 @@ local function processData(szType, content, add_mode, add_from) result.tls = "0" end - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "raw" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -602,7 +605,7 @@ local function processData(szType, content, add_mode, add_from) if ss_type_default == "xray" and has_xray then result.type = 'Xray' result.protocol = 'shadowsocks' - result.transport = 'tcp' + result.transport = 'raw' end if ss_type_default == "sing-box" and has_singbox then result.type = 'sing-box' @@ -643,6 +646,11 @@ local function processData(szType, content, add_mode, add_from) if params.type then params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if result.type ~= "SS-Rust" and result.type ~= "SS" then if params.type == 'ws' then @@ -699,7 +707,7 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end result.tls = "0" if params.security == "tls" or params.security == "reality" then @@ -783,10 +791,13 @@ local function processData(szType, content, add_mode, add_from) result.tls_allowInsecure = allowInsecure_default and "1" or "0" end - if not params.type then - params.type = "tcp" - end + if not params.type then params.type = "tcp" end params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if params.type == 'ws' then result.ws_host = params.host @@ -842,9 +853,9 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end - if info.net == 'xhttp' or info.net == 'splithttp' then + if params.type == 'xhttp' or params.type == 'splithttp' then result.xhttp_host = params.host result.xhttp_path = params.path end @@ -857,7 +868,7 @@ local function processData(szType, content, add_mode, add_from) result.flow = params.flow or nil - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "raw" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -920,10 +931,13 @@ local function processData(szType, content, add_mode, add_from) result.address = host_port end - if not params.type then - params.type = "tcp" - end + if not params.type then params.type = "tcp" end params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if params.type == 'ws' then result.ws_host = params.host @@ -979,9 +993,9 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end - if info.net == 'xhttp' or info.net == 'splithttp' then + if params.type == 'xhttp' or params.type == 'splithttp' then result.xhttp_host = params.host result.xhttp_path = params.path end @@ -1011,7 +1025,7 @@ local function processData(szType, content, add_mode, add_from) result.port = port result.tls_allowInsecure = allowInsecure_default and "1" or "0" - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "raw" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end diff --git a/openwrt-passwall2/.github/ISSUE_TEMPLATE/bug.yml b/openwrt-passwall2/.github/ISSUE_TEMPLATE/bug.yml index 1834c1fee1..0dc70492bf 100644 --- a/openwrt-passwall2/.github/ISSUE_TEMPLATE/bug.yml +++ b/openwrt-passwall2/.github/ISSUE_TEMPLATE/bug.yml @@ -1,5 +1,5 @@ -name: Bug上报 -description: 报告您使用中遇到的Bug以帮助我们改进 +name: Bug Reporting +description: Report any Bugs you encounter to help us improve. title: "[Bug]: " labels: bug @@ -8,68 +8,68 @@ body: id: tips attributes: value: | - 请按此规范填写,有效的反馈能让我们更好地解决您的问题 + Please fill in this specification. Effective feedback will help us better solve your problem. - type: textarea id: description attributes: - label: 描述您遇到的bug - description: 请尽可能简单清晰地描述问题 + label: Describe the Bug you encountered + description: Please describe the problem as simply and clearly as possible. validations: required: true - type: textarea id: steps attributes: - label: 复现此Bug的步骤 + label: Steps to reproduce this Bug placeholder: | - 1. 选择菜单'...' - 2. 点击按钮'....' - 3. 然后... - 4. 出现Bug: + 1. Select Menu'...' + 2. Click the button'....' + 3. Then... + 4. Appear: validations: required: true - type: textarea id: purpose attributes: - label: 您想要实现的目的 - description: 请尽可能简单清晰地描述您期望发生的事 + label: What you want to implement + description: Please describe what you expect to happen as simply and clearly as possible. validations: required: true - type: textarea id: logs attributes: - label: 日志信息 - description: 提交包括问题相关的所有系统日志信息(这个很重要) + label: Log information + description: Submit all system log information related to the problem (this is very important). validations: required: true - type: textarea id: pics attributes: - label: 截图 - description: 如果适用,您可以添加屏幕截图以便更好地解释您的问题 + label: Screenshot + description: If applicable, you can add screenshots to better explain your problem. validations: required: false - type: textarea id: environment attributes: - label: 系统相关信息 - description: 填写相关信息以便更好的确定问题 + label: System related information + description: Fill in relevant information to better identify the problem. placeholder: | - - Passwall2版本: - - 浏览器版本(如Chrome 96.0.4664.45 64位 正式版): - - 其他: + - Passwall2 version: + - Browser version (such as Chrome 96.0.4664.45 64-bit official version): + - Other: validations: required: true - type: textarea id: supplements attributes: - label: 其他信息 - description: 与此Bug相关的其他信息 + label: Other Information + description: Other information related to this Bug. validations: required: false diff --git a/openwrt-passwall2/.github/ISSUE_TEMPLATE/feature.yml b/openwrt-passwall2/.github/ISSUE_TEMPLATE/feature.yml index 654257331b..2d62a77ccf 100644 --- a/openwrt-passwall2/.github/ISSUE_TEMPLATE/feature.yml +++ b/openwrt-passwall2/.github/ISSUE_TEMPLATE/feature.yml @@ -1,5 +1,5 @@ -name: 功能请求 -description: 为此项目提出关于新功能的想法 +name: Feature Requests +description: Propose new feature ideas for this project. title: "[Feature Request]: " labels: enhancement @@ -7,31 +7,31 @@ body: - type: textarea id: description attributes: - label: 描述你想要的新功能 - description: 尽可能简单清晰地描述你想要的新功能或是希望解决的问题 + label: Describe the new feature you want + description: Describe the new feature you want or the problem you want solved as simply and clearly as possible. validations: required: true - type: textarea id: ideal-solution attributes: - label: 描述你想要的解决方案 - description: 尽可能简单清晰地描述你想要的新功能 + label: Describe the solution you want + description: Describe the new feature you want as simply and clearly as possible. validations: required: true - type: textarea id: other-solutions attributes: - label: 描述你考虑过的替代方案 - description: 尽可能简单清晰地描述你考虑过的任何替代解决方案或功能 + label: Describe the alternatives you considered + description: Describe any alternative solutions or features you considered as simply and clearly as possible. validations: required: false - type: textarea id: supplements attributes: - label: 其他信息 - description: 在此处添加有关功能请求的任何其他信息或屏幕截图 + label: Other Information + description: Add any other information or screenshots about your feature request here. validations: required: false diff --git a/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml b/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml index 6e5b35e018..73fa288069 100644 --- a/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml +++ b/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml @@ -21,6 +21,7 @@ env: passwall2: ${{ github.repository }} packages: xiaorouji/openwrt-passwall-packages + jobs: job_check: name: Check Version @@ -28,27 +29,29 @@ jobs: outputs: passwall2_version: ${{ steps.check_version.outputs.latest_version }} has_update: ${{ steps.check_version.outputs.has_update }} + prerelease: ${{ steps.check_version.outputs.prerelease }} steps: - name: Checkout uses: actions/checkout@main with: fetch-depth: 0 - ref: 'main' + ref: ${{ github.ref_name }} - name: Check version id: check_version env: - url_release: https://api.github.com/repos/${{ env.passwall2 }}/releases/latest + url_tags: https://api.github.com/repos/${{ env.passwall2 }}/tags run: | cd luci-app-passwall2 - latest_version=$(awk -F ':=' '/PKG_VERSION|PKG_RELEASE/ {print $2}' Makefile | sed ':a;N;s/\n$//;s/\n/-/;ba') - latest_release=$(wget -qO- -t1 -T2 ${{env.url_release}} | awk -F '"' '/tag_name/{print $4}') - has_update=$([ "${latest_version}" != "${latest_release}" ] && echo true || echo false) + latest_version=$(awk -F ':=' '/PKG_VERSION|PKG_RELEASE/ {print $2}' Makefile | sed ':a;N;s/\$(PKG_VERSION)-//;s/\n$//;s/\n/-/;ba') + has_update=$([ -z "$(wget -qO- -t1 -T2 ${{env.url_tags}} | grep \"${latest_version}\")" ] && echo true || echo false) + prerelease=$([ "${{ github.ref_name }}" == "main" ] && echo false || echo true) echo "latest_version=${latest_version}" >> $GITHUB_OUTPUT echo "has_update=${has_update}" >> $GITHUB_OUTPUT + echo "prerelease=${prerelease}" >> $GITHUB_OUTPUT echo "latest_version: ${latest_version}" - echo "latest_release: ${latest_release}" echo "has_update: ${has_update}" + echo "prerelease: ${prerelease}" - name: Prepare release if: steps.check_version.outputs.has_update == 'true' @@ -66,6 +69,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{steps.check_version.outputs.latest_version}} + target_commitish: ${{ github.ref_name }} + prerelease: ${{steps.check_version.outputs.prerelease}} body_path: release.txt @@ -85,13 +90,11 @@ jobs: - sdk_ver: 23.05 luci_ver: 23.05 sdk_url: https://downloads.openwrt.org/releases/23.05.0/targets/x86/64/openwrt-sdk-23.05.0-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz - steps: - name: Install packages run: | docker rmi `docker images -q` sudo -E rm -rf /usr/share/dotnet /etc/mysql /etc/php /etc/apt/sources.list.d /usr/local/lib/android - df -hT echo "Install packages" sudo -E apt-get -qq update sudo -E apt-get -qq install build-essential clang flex bison g++ gawk gcc-multilib g++-multilib gettext git libncurses-dev libssl-dev python3-distutils python3-setuptools rsync swig unzip zlib1g-dev file wget @@ -103,68 +106,52 @@ jobs: uses: actions/cache@v4 with: path: sdk - key: openwrt-sdk-23.05-rc3-x86_64 + key: openwrt-luci-${{ matrix.luci_ver }}-x86_64 - name: Initialization environment if: steps.cache-sdk.outputs.cache-hit != 'true' - env: - url_sdk: https://downloads.openwrt.org/releases/23.05.0/targets/x86/64/openwrt-sdk-23.05.0-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz run: | - wget ${{ env.url_sdk }} - file_name=$(echo ${{env.url_sdk}} | awk -F/ '{print $NF}') + wget ${{ matrix.sdk_url }} + file_name=$(echo ${{ matrix.sdk_url }} | awk -F/ '{print $NF}') mkdir sdk && tar -xJf $file_name -C ./sdk --strip-components=1 cd sdk echo "src-git base https://github.com/openwrt/openwrt.git;openwrt-${{ matrix.sdk_ver }}" > feeds.conf echo "src-git packages https://github.com/openwrt/packages.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf echo "src-git luci https://github.com/openwrt/luci.git;openwrt-${{ matrix.luci_ver }}" >> feeds.conf echo "src-git routing https://git.openwrt.org/feed/routing.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf - echo "src-git passwall_packages https://github.com/${{ env.packages}}.git;main" >> feeds.conf - echo "src-git passwall2 https://github.com/${{ env.passwall2 }}.git;main" >> feeds.conf + echo "src-git passwall_packages https://github.com/${{ env.packages }}.git;main" >> feeds.conf + echo "src-git passwall2 https://github.com/${{ env.passwall2 }}.git;${{ github.ref_name }}" >> feeds.conf ./scripts/feeds update -a echo "CONFIG_PACKAGE_luci-app-passwall2=m" > .config ./scripts/feeds install -d n luci-app-passwall2 - make download -j8 + make package/luci-app-passwall2/download -j1 - - name: Configure passwall2 + - name: Update passwall2 feeds + if: steps.cache-sdk.outputs.cache-hit == 'true' run: | cd sdk + sed -i '6s/main/${{ github.ref_name }}/' feeds.conf ./scripts/feeds update passwall_packages ./scripts/feeds update passwall2 ./scripts/feeds install luci-app-passwall2 - echo "CONFIG_ALL_NONSHARED=n" > .config - echo "CONFIG_ALL_KMODS=n" >> .config - echo "CONFIG_ALL=n" >> .config - echo "CONFIG_AUTOREMOVE=n" >> .config - echo "CONFIG_LUCI_LANG_zh_Hans=y" >> .config - - echo "CONFIG_PACKAGE_luci-app-passwall2=m" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_Iptables_Transparent_Proxy=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_Nftables_Transparent_Proxy=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_Haproxy=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_Hysteria=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_IPv6_Nat=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_NaiveProxy=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_Shadowsocks_Libev_Client=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_Shadowsocks_Libev_Server=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_Shadowsocks_Rust_Client=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_Shadowsocks_Rust_Server=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_ShadowsocksR_Libev_Client=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_ShadowsocksR_Libev_Server=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_Simple_Obfs=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_SingBox=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_tuic_client=n" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_V2ray_Plugin=n" >> .config - - make defconfig - name: Compile passwall2 id: compile run: | cd sdk - echo "make package/luci-app-passwall2/{clean,compile} -j$(nproc)" + echo "CONFIG_ALL_NONSHARED=n" > .config + echo "CONFIG_ALL_KMODS=n" >> .config + echo "CONFIG_ALL=n" >> .config + echo "CONFIG_AUTOREMOVE=n" >> .config + echo "CONFIG_LUCI_LANG_zh_Hans=y" >> .config + echo "CONFIG_PACKAGE_luci-app-passwall2=m" >> .config + make defconfig + echo "make package/luci-app-passwall2/{clean,compile} -j1" make package/luci-app-passwall2/{clean,compile} -j1 mv bin/packages/x86_64/passwall2/ ../ + make clean rm .config .config.old + rm -rf feeds/passwall2 feeds/passwall2.* cd ../passwall2 for i in $(ls); do mv $i luci-${{ matrix.luci_ver }}_$i; done cd .. @@ -182,7 +169,7 @@ jobs: job_auto_compile: - if: needs.job_check.outputs.has_update == 'true' + if: ${{ needs.job_check.outputs.has_update == 'true' && needs.job_check.outputs.prerelease == 'false' }} needs: job_check runs-on: ubuntu-latest name: build (${{ matrix.platform }}) @@ -246,7 +233,6 @@ jobs: run: | docker rmi `docker images -q` sudo -E rm -rf /usr/share/dotnet /etc/mysql /etc/php /etc/apt/sources.list.d /usr/local/lib/android - df -hT echo "install packages!!!!!!" sudo -E apt-get -qq update sudo -E apt-get -qq install build-essential clang flex bison g++ gawk gcc-multilib g++-multilib gettext git libncurses-dev libssl-dev python3-distutils python3-setuptools rsync swig unzip zlib1g-dev file wget @@ -271,7 +257,7 @@ jobs: echo "src-git packages https://github.com/openwrt/packages.git;openwrt-23.05" >> feeds.conf echo "src-git luci https://github.com/openwrt/luci.git;openwrt-23.05" >> feeds.conf echo "src-git routing https://git.openwrt.org/feed/routing.git;openwrt-23.05" >> feeds.conf - echo "src-git passwall_packages https://github.com/${{ env.packages}}.git;main" >> feeds.conf + echo "src-git passwall_packages https://github.com/${{ env.packages }}.git;main" >> feeds.conf echo "src-git passwall2 https://github.com/${{ env.passwall2 }}.git;main" >> feeds.conf ./scripts/feeds update -a @@ -281,12 +267,11 @@ jobs: rm -rf feeds/packages/lang/golang git clone https://github.com/sbwml/packages_lang_golang -b 22.x feeds/packages/lang/golang - - echo "CONFIG_ALL_NONSHARED=n" > .config echo "CONFIG_ALL_KMODS=n" >> .config echo "CONFIG_ALL=n" >> .config echo "CONFIG_AUTOREMOVE=n" >> .config + echo "CONFIG_SIGNED_PACKAGES=n" >> .config echo "CONFIG_PACKAGE_luci-app-passwall2=m" >> .config echo "CONFIG_PACKAGE_luci-app-passwall2_Iptables_Transparent_Proxy=y" >> .config echo "CONFIG_PACKAGE_luci-app-passwall2_Nftables_Transparent_Proxy=y" >> .config @@ -311,7 +296,7 @@ jobs: - name: ${{ matrix.platform }} download run: | cd sdk - make download -j8 + make download -j1 find dl -size -1024c -exec ls -l {} \; - name: ${{ matrix.platform }} compile @@ -320,7 +305,7 @@ jobs: cd sdk for package in $(ls feeds/passwall_packages); do if [ -d "feeds/passwall_packages/$package" ]; then - make package/feeds/passwall_packages/$package/compile -j$(nproc) 2>/dev/null + make package/feeds/passwall_packages/$package/compile -j1 2>/dev/null fi done @@ -333,7 +318,7 @@ jobs: cd sdk mkdir upload - zip -jr upload/passwall2_packages_ipk_${{ matrix.platform }}.zip bin/packages/*/passwall_packages/ + zip -jr upload/passwall_packages_ipk_${{ matrix.platform }}.zip bin/packages/*/passwall_packages/*.ipk echo "FIRMWARE=$PWD" >> $GITHUB_ENV echo "status=success" >> $GITHUB_OUTPUT diff --git a/openwrt-passwall2/.github/workflows/Close stale issues and Prs.yml b/openwrt-passwall2/.github/workflows/Close stale issues and Prs.yml index b32f5a9419..12cf3bb168 100644 --- a/openwrt-passwall2/.github/workflows/Close stale issues and Prs.yml +++ b/openwrt-passwall2/.github/workflows/Close stale issues and Prs.yml @@ -14,7 +14,7 @@ jobs: stale-issue-label: "no-issue-activity" exempt-issue-labels: "awaiting-approval,awaiting,work-in-progress" stale-pr-label: "no-pr-activity" - exempt-pr-labels: "awaiting-approval,awaiting,work-in-progress" + exempt-pr-labels: "awaiting-approval,awaiting,work-in-progress,automated-pr" # only-labels: 'bug,enhancement' days-before-issue-stale: 10 days-before-pr-stale: 10 @@ -23,7 +23,7 @@ jobs: operations-per-run: 500 - name: Delete workflow runs - uses: Mattraks/delete-workflow-runs@v2.0.3 + uses: Mattraks/delete-workflow-runs@main with: token: ${{ github.token }} repository: ${{ github.repository }} diff --git a/openwrt-passwall2/luci-app-passwall2/Makefile b/openwrt-passwall2/luci-app-passwall2/Makefile index 579aacaf5c..ee7af1f0b6 100644 --- a/openwrt-passwall2/luci-app-passwall2/Makefile +++ b/openwrt-passwall2/luci-app-passwall2/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=24.11.17 +PKG_VERSION:=24.11.18 PKG_RELEASE:=2 PKG_CONFIG_DEPENDS:= \ diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index 26590fb41d..20650ff6d8 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -918,14 +918,9 @@ function gen_config(var) if node.protocol == "_shunt" then local rules = {} - local preproxy_enabled = node.preproxy_enabled == "1" - local preproxy_rule_name = "main" - local preproxy_tag = "main" - local preproxy_node_id = node["main_node"] - local preproxy_node = preproxy_enabled and preproxy_node_id and uci:get_all(appname, preproxy_node_id) or nil - if preproxy_node then - preproxy_tag = preproxy_tag .. ":" .. preproxy_node.remarks - end + local preproxy_rule_name = node.preproxy_enabled == "1" and "main" or nil + local preproxy_tag = preproxy_rule_name + local preproxy_node_id = preproxy_rule_name and node["main_node"] or nil local function gen_shunt_node(rule_name, _node_id) if not rule_name then return nil end @@ -950,7 +945,6 @@ function gen_config(var) } local _outbound = gen_outbound(flag, _node, rule_name) if _outbound then - _outbound.tag = _outbound.tag .. ":" .. _node.remarks table.insert(outbounds, _outbound) rule_outboundTag = _outbound.tag end @@ -960,10 +954,10 @@ function gen_config(var) if not _node then return nil end if api.is_normal_node(_node) then - local proxy = preproxy_enabled and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id + local use_proxy = preproxy_tag and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id local copied_outbound for index, value in ipairs(outbounds) do - if value["_id"] == _node_id and value["_flag_proxy_tag"] == preproxy_tag then + if value["_id"] == _node_id and value["_flag_proxy_tag"] == (use_proxy and preproxy_tag or nil) then copied_outbound = api.clone(value) break end @@ -973,7 +967,7 @@ function gen_config(var) table.insert(outbounds, copied_outbound) rule_outboundTag = copied_outbound.tag else - if proxy then + if use_proxy then local pre_proxy = nil if _node.type ~= "sing-box" then pre_proxy = true @@ -999,7 +993,8 @@ function gen_config(var) }) end end - local _outbound = gen_outbound(flag, _node, rule_name, { tag = proxy and preproxy_tag or nil }) + + local _outbound = gen_outbound(flag, _node, rule_name, { tag = use_proxy and preproxy_tag or nil }) if _outbound then _outbound.tag = _outbound.tag .. ":" .. _node.remarks rule_outboundTag = set_outbound_detour(_node, _outbound, outbounds, rule_name) @@ -1023,10 +1018,10 @@ function gen_config(var) return rule_outboundTag end - if preproxy_node then - proxy_outboundTag = gen_shunt_node(preproxy_rule_name, preproxy_node_id) - if not proxy_outboundTag then - preproxy_node = nil + if preproxy_tag and preproxy_node_id then + local preproxy_outboundTag = gen_shunt_node(preproxy_rule_name, preproxy_node_id) + if preproxy_outboundTag then + preproxy_tag = preproxy_outboundTag end end --default_node diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 816fa4ef6d..121d4d96a5 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -756,16 +756,15 @@ function gen_config(var) end -- new balancer local blc_nodes = _node.balancing_node - local length = #blc_nodes local valid_nodes = {} - for i = 1, length do + for i = 1, #blc_nodes do local blc_node_id = blc_nodes[i] local blc_node_tag = "blc-" .. blc_node_id local is_new_blc_node = true for _, outbound in ipairs(outbounds) do - if outbound.tag == blc_node_tag then + if outbound.tag:find("^" .. blc_node_tag) == 1 then is_new_blc_node = false - valid_nodes[#valid_nodes + 1] = blc_node_tag + valid_nodes[#valid_nodes + 1] = outbound.tag break end end @@ -775,20 +774,22 @@ function gen_config(var) if outbound then outbound.tag = outbound.tag .. ":" .. blc_node.remarks table.insert(outbounds, outbound) - valid_nodes[#valid_nodes + 1] = blc_node_tag + valid_nodes[#valid_nodes + 1] = outbound.tag end end end if #valid_nodes == 0 then return nil end -- fallback node + local fallback_node_tag = nil local fallback_node_id = _node.fallback_node - if fallback_node_id == "" then fallback_node_id = nil end + if fallback_node_id == "" or fallback_node_id == "nil" then fallback_node_id = nil end if fallback_node_id then local is_new_node = true for _, outbound in ipairs(outbounds) do - if outbound.tag == fallback_node_id then + if outbound.tag:find("^" .. fallback_node_id) == 1 then is_new_node = false + fallback_node_tag = outbound.tag break end end @@ -799,12 +800,7 @@ function gen_config(var) if outbound then outbound.tag = outbound.tag .. ":" .. fallback_node.remarks table.insert(outbounds, outbound) - else - fallback_node_id = nil - end - else - if not gen_balancer(fallback_node) then - fallback_node_id = nil + fallback_node_tag = outbound.tag end end end @@ -812,10 +808,10 @@ function gen_config(var) table.insert(balancers, { tag = balancer_tag, selector = valid_nodes, - fallbackTag = fallback_node_id, + fallbackTag = fallback_node_tag, strategy = { type = _node.balancingStrategy or "random" } }) - if _node.balancingStrategy == "leastPing" or fallback_node_id then + if _node.balancingStrategy == "leastPing" or fallback_node_tag then if not observatory then observatory = { subjectSelector = { "blc-" }, @@ -1050,6 +1046,7 @@ function gen_config(var) local domain_table = { shunt_rule_name = e[".name"], outboundTag = outboundTag, + balancerTag = balancerTag, domain = {}, } domains = {} @@ -1058,7 +1055,7 @@ function gen_config(var) table.insert(domains, w) table.insert(domain_table.domain, w) end) - if outboundTag and outboundTag ~= "nil" then + if (outboundTag and outboundTag ~= "nil") or (balancerTag and balancerTag ~= "nil") then table.insert(dns_domain_rules, api.clone(domain_table)) end if #domains == 0 then domains = nil end @@ -1107,16 +1104,15 @@ function gen_config(var) end end end) ---[[ - if default_outboundTag or default_balancerTag then + + if default_balancerTag then table.insert(rules, { - _flag = "default", - outboundTag = default_outboundTag, + ruleTag = "default", balancerTag = default_balancerTag, network = "tcp,udp" }) end -]] + routing = { domainStrategy = node.domainStrategy or "AsIs", domainMatcher = node.domainMatcher or "hybrid", @@ -1367,7 +1363,7 @@ function gen_config(var) end local default_dns_flag = "remote" - if not COMMON.default_outbound_tag or COMMON.default_outbound_tag == "direct" then + if (not COMMON.default_balancer_tag and not COMMON.default_outbound_tag) or COMMON.default_outbound_tag == "direct" then default_dns_flag = "direct" end @@ -1395,7 +1391,7 @@ function gen_config(var) --按分流顺序DNS if dns_domain_rules and #dns_domain_rules > 0 then for index, value in ipairs(dns_domain_rules) do - if value.outboundTag and value.domain then + if value.domain and (value.outboundTag or value.balancerTag) then local dns_server = nil if value.outboundTag == "direct" then dns_server = api.clone(_direct_dns) diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/local/loadbalancing/server_data.rs b/shadowsocks-rust/crates/shadowsocks-service/src/local/loadbalancing/server_data.rs index 86c224cffe..9a3cac8fbd 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/local/loadbalancing/server_data.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/local/loadbalancing/server_data.rs @@ -2,6 +2,7 @@ use std::{ fmt::{self, Debug}, + net::SocketAddr, sync::{ atomic::{AtomicU32, Ordering}, Arc, @@ -102,7 +103,7 @@ impl ServerIdent { } if let Some(bind_local_addr) = svr_cfg.outbound_bind_addr { - connect_opts.bind_local_addr = Some(bind_local_addr); + connect_opts.bind_local_addr = Some(SocketAddr::new(bind_local_addr, 0)); } if let Some(ref bind_interface) = svr_cfg.outbound_bind_interface { diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/local/mod.rs b/shadowsocks-rust/crates/shadowsocks-service/src/local/mod.rs index 7ece6e16dc..013cda15a0 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/local/mod.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/local/mod.rs @@ -2,6 +2,7 @@ use std::{ io::{self, ErrorKind}, + net::SocketAddr, sync::Arc, time::Duration, }; @@ -130,7 +131,7 @@ impl Server { vpn_protect_path: config.outbound_vpn_protect_path, bind_interface: config.outbound_bind_interface, - bind_local_addr: config.outbound_bind_addr, + bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)), ..Default::default() }; diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/manager/mod.rs b/shadowsocks-rust/crates/shadowsocks-service/src/manager/mod.rs index 94b40dadeb..6bc98ba827 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/manager/mod.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/manager/mod.rs @@ -2,7 +2,7 @@ //! //! Service for managing multiple relay servers. [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users) -use std::{io, sync::Arc}; +use std::{io, net::SocketAddr, sync::Arc}; use log::trace; use shadowsocks::net::{AcceptOpts, ConnectOpts}; @@ -40,7 +40,7 @@ pub async fn run(config: Config) -> io::Result<()> { #[cfg(target_os = "android")] vpn_protect_path: config.outbound_vpn_protect_path, - bind_local_addr: config.outbound_bind_addr, + bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)), bind_interface: config.outbound_bind_interface, ..Default::default() diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/server/mod.rs b/shadowsocks-rust/crates/shadowsocks-service/src/server/mod.rs index e019658fc0..1bea33f305 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/server/mod.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/server/mod.rs @@ -1,6 +1,6 @@ //! Shadowsocks server -use std::{io, sync::Arc, time::Duration}; +use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use futures::future; use log::trace; @@ -64,7 +64,7 @@ pub async fn run(config: Config) -> io::Result<()> { #[cfg(target_os = "android")] vpn_protect_path: config.outbound_vpn_protect_path, - bind_local_addr: config.outbound_bind_addr, + bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)), bind_interface: config.outbound_bind_interface, ..Default::default() @@ -110,7 +110,7 @@ pub async fn run(config: Config) -> io::Result<()> { } if let Some(bind_local_addr) = inst.outbound_bind_addr { - connect_opts.bind_local_addr = Some(bind_local_addr); + connect_opts.bind_local_addr = Some(SocketAddr::new(bind_local_addr, 0)); } if let Some(bind_interface) = inst.outbound_bind_interface { diff --git a/shadowsocks-rust/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs b/shadowsocks-rust/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs index 76a499da9e..d7062574df 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs @@ -80,7 +80,7 @@ impl RuntimeProvider for ShadowDnsRuntimeProvider { let mut connect_opts = self.connect_opts.clone(); if let Some(bind_addr) = bind_addr { - connect_opts.bind_local_addr = Some(bind_addr.ip()); + connect_opts.bind_local_addr = Some(bind_addr); } let wait_for = wait_for.unwrap_or_else(|| Duration::from_secs(5)); diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/option.rs b/shadowsocks-rust/crates/shadowsocks/src/net/option.rs index d73ea9c291..dffea6351f 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/option.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/option.rs @@ -1,6 +1,6 @@ //! Options for connecting to remote server -use std::{net::IpAddr, time::Duration}; +use std::{net::SocketAddr, time::Duration}; /// Options for connecting to TCP remote server #[derive(Debug, Clone, Default)] @@ -60,7 +60,7 @@ pub struct ConnectOpts { /// Outbound socket binds to this IP address, mostly for choosing network interfaces /// /// It only affects sockets that trying to connect to addresses with the same family - pub bind_local_addr: Option, + pub bind_local_addr: Option, /// Outbound socket binds to interface pub bind_interface: Option, diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/sys/mod.rs b/shadowsocks-rust/crates/shadowsocks/src/net/sys/mod.rs index 6540508e95..cd6f05aebe 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/sys/mod.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/sys/mod.rs @@ -1,6 +1,6 @@ use std::{ io::{self, ErrorKind}, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, + net::{Ipv4Addr, Ipv6Addr, SocketAddr}, }; use cfg_if::cfg_if; @@ -23,13 +23,13 @@ cfg_if! { fn set_common_sockopt_for_connect(addr: SocketAddr, socket: &TcpSocket, opts: &ConnectOpts) -> io::Result<()> { // Binds to IP address - if let Some(ip) = opts.bind_local_addr { - match (ip, addr.ip()) { - (IpAddr::V4(..), IpAddr::V4(..)) => { - socket.bind(SocketAddr::new(ip, 0))?; + if let Some(baddr) = opts.bind_local_addr { + match (baddr, addr) { + (SocketAddr::V4(..), SocketAddr::V4(..)) => { + socket.bind(baddr)?; } - (IpAddr::V6(..), IpAddr::V6(..)) => { - socket.bind(SocketAddr::new(ip, 0))?; + (SocketAddr::V6(..), SocketAddr::V6(..)) => { + socket.bind(baddr)?; } _ => {} } diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs index 812e29c379..46d4ab5dc8 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs @@ -1,6 +1,6 @@ use std::{ io, mem, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, + net::{Ipv4Addr, Ipv6Addr, SocketAddr}, os::unix::io::{AsRawFd, RawFd}, pin::Pin, ptr, @@ -227,8 +227,8 @@ pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> i #[inline] pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { - (AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0), - (AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0), + (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/macos.rs b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/macos.rs index de3717ee0a..b170bf1013 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/macos.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/macos.rs @@ -3,7 +3,7 @@ use std::{ collections::HashMap, io::{self, ErrorKind}, mem, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpStream as StdTcpStream}, + net::{Ipv4Addr, Ipv6Addr, SocketAddr, TcpStream as StdTcpStream}, os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, pin::Pin, ptr, @@ -355,8 +355,8 @@ pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> i #[inline] pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { - (AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0), - (AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0), + (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/linux/mod.rs b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/linux/mod.rs index f007255a0f..4f52e4682e 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/linux/mod.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/linux/mod.rs @@ -1,6 +1,6 @@ use std::{ io, mem, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, + net::{Ipv4Addr, Ipv6Addr, SocketAddr}, os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, pin::Pin, ptr, @@ -286,8 +286,8 @@ pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> i #[inline] pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { - (AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0), - (AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0), + (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/others.rs b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/others.rs index ad0b32d330..cb047e4e97 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/others.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/others.rs @@ -1,6 +1,6 @@ use std::{ io, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, + net::{Ipv4Addr, Ipv6Addr, SocketAddr}, ops::{Deref, DerefMut}, os::fd::AsRawFd, pin::Pin, @@ -81,8 +81,8 @@ pub fn set_disable_ip_fragmentation(_af: AddrFamily, _socket: &S) -> #[inline] pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { - (AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0), - (AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0), + (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs b/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs index ca5f70f5db..12e0466039 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs @@ -467,9 +467,9 @@ pub async fn create_inbound_udp_socket(addr: &SocketAddr, ipv6_only: bool) -> io /// Create a `UdpSocket` for connecting to `addr` #[inline(always)] pub async fn create_outbound_udp_socket(af: AddrFamily, opts: &ConnectOpts) -> io::Result { - let bind_addr = match (af, opts.bind_local_addr) { - (AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0), - (AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0), + let bind_addr = match (af, config.bind_local_addr) { + (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/sing-box/clients/android/app/build.gradle b/sing-box/clients/android/app/build.gradle index 0c6e97c4ea..30aaaf560a 100644 --- a/sing-box/clients/android/app/build.gradle +++ b/sing-box/clients/android/app/build.gradle @@ -10,7 +10,7 @@ plugins { android { namespace "io.nekohasekai.sfa" - compileSdk 34 + compileSdk 35 ndkVersion "26.2.11394342" @@ -22,7 +22,7 @@ android { defaultConfig { applicationId "io.nekohasekai.sfa" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode getVersionProps("VERSION_CODE").toInteger() versionName getVersionProps("VERSION_NAME") setProperty("archivesBaseName", "SFA-" + versionName) @@ -90,23 +90,23 @@ android { dependencies { implementation(fileTree("libs")) - implementation "androidx.core:core-ktx:1.13.1" + implementation "androidx.core:core-ktx:1.15.0" implementation "androidx.appcompat:appcompat:1.7.0" implementation "com.google.android.material:material:1.12.0" - implementation "androidx.constraintlayout:constraintlayout:2.1.4" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.6" - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6" - implementation "androidx.navigation:navigation-fragment-ktx:2.8.2" - implementation "androidx.navigation:navigation-ui-ktx:2.8.2" + implementation "androidx.constraintlayout:constraintlayout:2.2.0" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.7" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7" + implementation "androidx.navigation:navigation-fragment-ktx:2.8.3" + implementation "androidx.navigation:navigation-ui-ktx:2.8.3" implementation "com.google.zxing:core:3.5.3" implementation "androidx.room:room-runtime:2.6.1" implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0" implementation "androidx.preference:preference-ktx:1.2.1" - implementation "androidx.camera:camera-view:1.3.4" - implementation "androidx.camera:camera-lifecycle:1.3.4" - implementation "androidx.camera:camera-camera2:1.3.4" + implementation "androidx.camera:camera-view:1.4.0" + implementation "androidx.camera:camera-lifecycle:1.4.0" + implementation "androidx.camera:camera-camera2:1.4.0" ksp "androidx.room:room-compiler:2.6.1" - implementation "androidx.work:work-runtime-ktx:2.9.1" + implementation "androidx.work:work-runtime-ktx:2.10.0" implementation "androidx.browser:browser:1.8.0" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0" diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/Application.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/Application.kt index bec7372031..298e2318db 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/Application.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/Application.kt @@ -22,7 +22,6 @@ class Application : Application() { override fun attachBaseContext(base: Context?) { super.attachBaseContext(base) - application = this } diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/BoxService.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/BoxService.kt index de5712c26b..c8361b86b0 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/BoxService.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/BoxService.kt @@ -1,15 +1,20 @@ package io.nekohasekai.sfa.bg +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent import android.app.Service import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.net.Uri import android.os.Build import android.os.IBinder import android.os.ParcelFileDescriptor import android.os.PowerManager import androidx.annotation.RequiresApi +import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import androidx.lifecycle.MutableLiveData import go.Seq @@ -17,6 +22,7 @@ import io.nekohasekai.libbox.BoxService import io.nekohasekai.libbox.CommandServer import io.nekohasekai.libbox.CommandServerHandler import io.nekohasekai.libbox.Libbox +import io.nekohasekai.libbox.Notification import io.nekohasekai.libbox.PlatformInterface import io.nekohasekai.libbox.SystemProxyStatus import io.nekohasekai.sfa.Application @@ -27,6 +33,7 @@ import io.nekohasekai.sfa.constant.Status import io.nekohasekai.sfa.database.ProfileManager import io.nekohasekai.sfa.database.Settings import io.nekohasekai.sfa.ktx.hasPermission +import io.nekohasekai.sfa.ui.MainActivity import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -36,8 +43,7 @@ import kotlinx.coroutines.withContext import java.io.File class BoxService( - private val service: Service, - private val platformInterface: PlatformInterface + private val service: Service, private val platformInterface: PlatformInterface ) : CommandServerHandler { companion object { @@ -101,8 +107,7 @@ class BoxService( } private fun startCommandServer() { - val commandServer = - CommandServer(this, 300) + val commandServer = CommandServer(this, 300) commandServer.start() this.commandServer = commandServer } @@ -328,4 +333,45 @@ class BoxService( commandServer?.writeMessage(message) } + internal fun sendNotification(notification: Notification) { + val builder = + NotificationCompat.Builder(service, notification.identifier).setShowWhen(false) + .setContentTitle(notification.title) + .setContentText(notification.body) + .setOnlyAlertOnce(true) + .setSmallIcon(R.drawable.ic_menu) + .setCategory(NotificationCompat.CATEGORY_EVENT) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setAutoCancel(true) + if (!notification.subtitle.isNullOrBlank()) { + builder.setContentInfo(notification.subtitle) + } + if (!notification.openURL.isNullOrBlank()) { + builder.setContentIntent( + PendingIntent.getActivity( + service, + 0, + Intent( + service, MainActivity::class.java + ).apply { + setAction(Action.OPEN_URL).setData(Uri.parse(notification.openURL)) + setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) + }, + ServiceNotification.flags, + ) + ) + } + GlobalScope.launch(Dispatchers.Main) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Application.notification.createNotificationChannel( + NotificationChannel( + notification.identifier, + notification.typeName, + NotificationManager.IMPORTANCE_HIGH + ) + ) + } + Application.notification.notify(notification.typeID, builder.build()) + } + } } \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/PlatformInterfaceWrapper.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/PlatformInterfaceWrapper.kt index a5b29bea50..c5bf70073b 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/PlatformInterfaceWrapper.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/PlatformInterfaceWrapper.kt @@ -1,5 +1,6 @@ package io.nekohasekai.sfa.bg +import android.annotation.SuppressLint import android.content.pm.PackageManager import android.os.Build import android.os.Process @@ -136,6 +137,9 @@ interface PlatformInterfaceWrapper : PlatformInterface { element.interfaceAddresses.mapTo(mutableListOf()) { it.toPrefix() } .iterator() ) + runCatching { + flags = element.flags + } } } @@ -146,6 +150,13 @@ interface PlatformInterfaceWrapper : PlatformInterface { "${address.hostAddress}/${networkPrefixLength}" } } + + private val NetworkInterface.flags: Int + @SuppressLint("SoonBlockedPrivateApi") + get() { + val getFlagsMethod = NetworkInterface::class.java.getDeclaredMethod("getFlags") + return getFlagsMethod.invoke(this) as Int + } } private class StringArray(private val iterator: Iterator) : StringIterator { diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/ProxyService.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/ProxyService.kt index a84082f8dc..6087d49e33 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/ProxyService.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/ProxyService.kt @@ -2,6 +2,7 @@ package io.nekohasekai.sfa.bg import android.app.Service import android.content.Intent +import io.nekohasekai.libbox.Notification class ProxyService : Service(), PlatformInterfaceWrapper { @@ -14,4 +15,8 @@ class ProxyService : Service(), PlatformInterfaceWrapper { override fun onDestroy() = service.onDestroy() override fun writeLog(message: String) = service.writeLog(message) + + override fun sendNotification(notification: Notification) = + service.sendNotification(notification) + } \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/ServiceNotification.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/ServiceNotification.kt index db1a618877..52a236f948 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/ServiceNotification.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/ServiceNotification.kt @@ -33,7 +33,7 @@ class ServiceNotification( companion object { private const val notificationId = 1 private const val notificationChannel = "service" - private val flags = + val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0 fun checkPermission(): Boolean { @@ -83,7 +83,7 @@ class ServiceNotification( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Application.notification.createNotificationChannel( NotificationChannel( - notificationChannel, "sing-box service", NotificationManager.IMPORTANCE_LOW + notificationChannel, "Service Notifications", NotificationManager.IMPORTANCE_LOW ) ) } diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/VPNService.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/VPNService.kt index 50f838b0dc..9817e955cf 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/VPNService.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/VPNService.kt @@ -6,6 +6,7 @@ import android.net.ProxyInfo import android.net.VpnService import android.os.Build import android.os.IBinder +import io.nekohasekai.libbox.Notification import io.nekohasekai.libbox.TunOptions import io.nekohasekai.sfa.database.Settings import io.nekohasekai.sfa.ktx.toIpPrefix @@ -188,4 +189,7 @@ class VPNService : VpnService(), PlatformInterfaceWrapper { override fun writeLog(message: String) = service.writeLog(message) + override fun sendNotification(notification: Notification) = + service.sendNotification(notification) + } \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/constant/Action.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/constant/Action.kt index 5a65152117..c0bb9478fd 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/constant/Action.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/constant/Action.kt @@ -3,4 +3,5 @@ package io.nekohasekai.sfa.constant object Action { const val SERVICE = "io.nekohasekai.sfa.SERVICE" const val SERVICE_CLOSE = "io.nekohasekai.sfa.SERVICE_CLOSE" + const val OPEN_URL = "io.nekohasekai.sfa.SERVICE_OPEN_URL" } \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ktx/Dialogs.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ktx/Dialogs.kt index 5ff5b2aed4..80a98662cd 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ktx/Dialogs.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ktx/Dialogs.kt @@ -1,7 +1,6 @@ package io.nekohasekai.sfa.ktx import android.content.Context -import android.content.DialogInterface import androidx.annotation.StringRes import com.google.android.material.dialog.MaterialAlertDialogBuilder import io.nekohasekai.sfa.R @@ -14,26 +13,12 @@ fun Context.errorDialogBuilder(@StringRes messageId: Int): MaterialAlertDialogBu } fun Context.errorDialogBuilder(message: String): MaterialAlertDialogBuilder { - return errorDialogBuilder(message, null) -} - -fun Context.errorDialogBuilder( - message: String, - listener: DialogInterface.OnClickListener? -): MaterialAlertDialogBuilder { return MaterialAlertDialogBuilder(this) .setTitle(R.string.error_title) .setMessage(message) - .setPositiveButton(android.R.string.ok, listener) + .setPositiveButton(android.R.string.ok, null) } fun Context.errorDialogBuilder(exception: Throwable): MaterialAlertDialogBuilder { - return errorDialogBuilder(exception, null) -} - -fun Context.errorDialogBuilder( - exception: Throwable, - listener: DialogInterface.OnClickListener? -): MaterialAlertDialogBuilder { - return errorDialogBuilder(exception.localizedMessage ?: exception.toString(), listener) + return errorDialogBuilder(exception.localizedMessage ?: exception.toString()) } \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt index 187baf87fc..d3986a24f1 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt @@ -33,6 +33,7 @@ import io.nekohasekai.sfa.Application import io.nekohasekai.sfa.R import io.nekohasekai.sfa.bg.ServiceConnection import io.nekohasekai.sfa.bg.ServiceNotification +import io.nekohasekai.sfa.constant.Action import io.nekohasekai.sfa.constant.Alert import io.nekohasekai.sfa.constant.ServiceMode import io.nekohasekai.sfa.constant.Status @@ -43,6 +44,7 @@ import io.nekohasekai.sfa.database.TypedProfile import io.nekohasekai.sfa.databinding.ActivityMainBinding import io.nekohasekai.sfa.ktx.errorDialogBuilder import io.nekohasekai.sfa.ktx.hasPermission +import io.nekohasekai.sfa.ktx.launchCustomTab import io.nekohasekai.sfa.ui.profile.NewProfileActivity import io.nekohasekai.sfa.ui.settings.CoreFragment import io.nekohasekai.sfa.ui.shared.AbstractActivity @@ -127,6 +129,12 @@ class MainActivity : AbstractActivity(), override public fun onNewIntent(intent: Intent) { super.onNewIntent(intent) val uri = intent.data ?: return + when (intent.action) { + Action.OPEN_URL -> { + launchCustomTab(uri.toString()) + return + } + } if (uri.scheme == "sing-box" && uri.host == "import-remote-profile") { val profile = try { Libbox.parseRemoteProfileImportLink(uri.toString()) diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/debug/VPNScanActivity.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/debug/VPNScanActivity.kt index c1aab2eec3..f56717c0f6 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/debug/VPNScanActivity.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/debug/VPNScanActivity.kt @@ -78,9 +78,9 @@ class VPNScanActivity : AbstractActivity() { RecyclerView.ViewHolder(binding.root) { fun bind(element: AppInfo) { - binding.appIcon.setImageDrawable(element.packageInfo.applicationInfo.loadIcon(binding.root.context.packageManager)) + binding.appIcon.setImageDrawable(element.packageInfo.applicationInfo!!.loadIcon(binding.root.context.packageManager)) binding.appName.text = - element.packageInfo.applicationInfo.loadLabel(binding.root.context.packageManager) + element.packageInfo.applicationInfo!!.loadLabel(binding.root.context.packageManager) binding.packageName.text = element.packageInfo.packageName val appType = element.vpnType.appType if (appType != null) { @@ -129,7 +129,8 @@ class VPNScanActivity : AbstractActivity() { } val vpnAppList = installedPackages.filter { - it.services?.any { it.permission == Manifest.permission.BIND_VPN_SERVICE } ?: false + it.services?.any { it.permission == Manifest.permission.BIND_VPN_SERVICE && it.applicationInfo != null } + ?: false } for ((index, packageInfo) in vpnAppList.withIndex()) { val appType = runCatching { getVPNAppType(packageInfo) }.getOrNull() @@ -181,7 +182,7 @@ class VPNScanActivity : AbstractActivity() { } private fun getVPNAppType(packageInfo: PackageInfo): String? { - ZipFile(File(packageInfo.applicationInfo.publicSourceDir)).use { packageFile -> + ZipFile(File(packageInfo.applicationInfo!!.publicSourceDir)).use { packageFile -> for (packageEntry in packageFile.entries()) { if (!(packageEntry.name.startsWith("classes") && packageEntry.name.endsWith( ".dex" @@ -235,8 +236,8 @@ class VPNScanActivity : AbstractActivity() { } private fun getVPNCoreType(packageInfo: PackageInfo): VPNCoreType? { - val packageFiles = mutableListOf(packageInfo.applicationInfo.publicSourceDir) - packageInfo.applicationInfo.splitPublicSourceDirs?.also { + val packageFiles = mutableListOf(packageInfo.applicationInfo!!.publicSourceDir) + packageInfo.applicationInfo!!.splitPublicSourceDirs?.also { packageFiles.addAll(it) } val vpnType = try { diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/DashboardFragment.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/DashboardFragment.kt index 34bc41d1ad..084a713478 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/DashboardFragment.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/DashboardFragment.kt @@ -8,14 +8,23 @@ import androidx.annotation.StringRes import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.viewpager2.adapter.FragmentStateAdapter +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.tabs.TabLayoutMediator +import io.nekohasekai.libbox.DeprecatedNoteIterator +import io.nekohasekai.libbox.Libbox import io.nekohasekai.sfa.R import io.nekohasekai.sfa.bg.BoxService import io.nekohasekai.sfa.constant.Status import io.nekohasekai.sfa.databinding.FragmentDashboardBinding +import io.nekohasekai.sfa.ktx.errorDialogBuilder +import io.nekohasekai.sfa.ktx.launchCustomTab import io.nekohasekai.sfa.ui.MainActivity import io.nekohasekai.sfa.ui.dashboard.GroupsFragment import io.nekohasekai.sfa.ui.dashboard.OverviewFragment +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class DashboardFragment : Fragment(R.layout.fragment_dashboard) { @@ -49,6 +58,7 @@ class DashboardFragment : Fragment(R.layout.fragment_dashboard) { } Status.Started -> { + checkDeprecatedNotes() enablePager() binding.fab.setImageResource(R.drawable.ic_stop_24) binding.fab.show() @@ -99,6 +109,38 @@ class DashboardFragment : Fragment(R.layout.fragment_dashboard) { binding = null } + private fun checkDeprecatedNotes() { + GlobalScope.launch(Dispatchers.IO) { + runCatching { + val notes = Libbox.newStandaloneCommandClient().deprecatedNotes + if (notes.hasNext()) { + withContext(Dispatchers.Main) { + loopShowDeprecatedNotes(notes) + } + } + }.onFailure { + activity?.errorDialogBuilder(it)?.show() + } + } + } + + private fun loopShowDeprecatedNotes(notes: DeprecatedNoteIterator) { + if (notes.hasNext()) { + val note = notes.next() + val builder = MaterialAlertDialogBuilder(requireContext()) + builder.setTitle(getString(R.string.service_error_title_deprecated_warning)) + builder.setMessage(note.message()) + builder.setPositiveButton(R.string.ok) { _, _ -> + loopShowDeprecatedNotes(notes) + } + builder.setNeutralButton(R.string.service_error_deprecated_warning_documentation) { _, _ -> + requireContext().launchCustomTab(note.migrationLink) + loopShowDeprecatedNotes(notes) + } + builder.show() + } + } + private fun enablePager() { val activity = activity ?: return val binding = binding ?: return diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/LogFragment.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/LogFragment.kt index 7c5230e685..2ae6da0f82 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/LogFragment.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/LogFragment.kt @@ -139,12 +139,12 @@ class LogFragment : Fragment(), CommandClient.Handler { lifecycleScope.launch(Dispatchers.Main) { val messageLen = messageList.size val removeLen = logList.size + messageLen - 300 + logList.addAll(messageList) if (removeLen > 0) { repeat(removeLen) { logList.removeFirst() } } - logList.addAll(messageList) updateViews(removeLen, messageLen) } } diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/QRScanActivity.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/QRScanActivity.kt index bc81a55b40..ce3deddb5f 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/QRScanActivity.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/QRScanActivity.kt @@ -75,17 +75,25 @@ class QRScanActivity : AbstractActivity() { } private val onFailure: (Exception) -> Unit = { lifecycleScope.launch { - errorDialogBuilder(it).show() + resetAnalyzer() + errorDialogBuilder("MLKit error: ${it.localizedMessage}").show() } } private val vendorAnalyzer = Vendor.createQRCodeAnalyzer(onSuccess, onFailure) + private var useVendorAnalyzer = vendorAnalyzer != null + private fun resetAnalyzer() { + if (useVendorAnalyzer) { + useVendorAnalyzer = false + imageAnalysis.clearAnalyzer() + imageAnalyzer = ZxingQRCodeAnalyzer(onSuccess, onFailure) + imageAnalysis.setAnalyzer(analysisExecutor, imageAnalyzer) + } + } + private lateinit var cameraProvider: ProcessCameraProvider private lateinit var cameraPreview: Preview private lateinit var camera: Camera - // prevent multiple error dialogs shows up at the same time - private var invalidRawDataErrorDialogShowing: Boolean = false - private fun startCamera() { val cameraProviderFuture = try { ProcessCameraProvider.getInstance(this) @@ -132,14 +140,8 @@ class QRScanActivity : AbstractActivity() { importRemoteProfileFromString(value) return true } catch (e: Exception) { - if (invalidRawDataErrorDialogShowing) return false - - invalidRawDataErrorDialogShowing = true - lifecycleScope.launch { - errorDialogBuilder(e) { _, _ -> - invalidRawDataErrorDialogShowing = false - }.show() + errorDialogBuilder(e).show() } } return false @@ -155,11 +157,19 @@ class QRScanActivity : AbstractActivity() { finish() } + override fun onPrepareOptionsMenu(menu: Menu?): Boolean { + if (!useVendorAnalyzer) { + menu!!.findItem(R.id.action_use_vendor_analyzer).also { + it.isEnabled = false + it.isChecked = false + } + } + return true + } + override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.qr_scan_menu, menu) - if (vendorAnalyzer == null) { - menu.findItem(R.id.action_use_vendor_analyzer).isEnabled = false - } else { + if (useVendorAnalyzer) { menu.findItem(R.id.action_use_vendor_analyzer).isChecked = true } return true diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profileoverride/PerAppProxyActivity.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profileoverride/PerAppProxyActivity.kt index 2e6f3929f3..990d30408d 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profileoverride/PerAppProxyActivity.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profileoverride/PerAppProxyActivity.kt @@ -53,24 +53,25 @@ class PerAppProxyActivity : AbstractActivity() { inner class PackageCache( private val packageInfo: PackageInfo, + private val appInfo: ApplicationInfo, ) { val packageName: String get() = packageInfo.packageName - val uid get() = packageInfo.applicationInfo.uid + val uid get() = packageInfo.applicationInfo!!.uid val installTime get() = packageInfo.firstInstallTime val updateTime get() = packageInfo.lastUpdateTime - val isSystem get() = packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 1 + val isSystem get() = appInfo.flags and ApplicationInfo.FLAG_SYSTEM == 1 val isOffline get() = packageInfo.requestedPermissions?.contains(Manifest.permission.INTERNET) != true - val isDisabled get() = packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_INSTALLED == 0 + val isDisabled get() = appInfo.flags and ApplicationInfo.FLAG_INSTALLED == 0 val applicationIcon by lazy { - packageInfo.applicationInfo.loadIcon(packageManager) + appInfo.loadIcon(packageManager) } val applicationLabel by lazy { - packageInfo.applicationInfo.loadLabel(packageManager).toString() + appInfo.loadLabel(packageManager).toString() } } @@ -130,7 +131,8 @@ class PerAppProxyActivity : AbstractActivity() { val packages = mutableListOf() for (packageInfo in installedPackages) { if (packageInfo.packageName == packageName) continue - packages.add(PackageCache(packageInfo)) + val appInfo = packageInfo.applicationInfo ?: continue + packages.add(PackageCache(packageInfo, appInfo)) } val selectedPackageNames = Settings.perAppProxyList.toMutableSet() val selectedUIDs = mutableSetOf() @@ -699,6 +701,7 @@ class PerAppProxyActivity : AbstractActivity() { packageName, packageManagerFlags ) } + val appInfo = packageInfo.applicationInfo ?: return false packageInfo.services?.forEach { if (it.name.matches(chinaAppRegex)) { Log.d("PerAppProxyActivity", "Match service ${it.name} in $packageName") @@ -723,7 +726,7 @@ class PerAppProxyActivity : AbstractActivity() { return true } } - ZipFile(File(packageInfo.applicationInfo.publicSourceDir)).use { + ZipFile(File(appInfo.publicSourceDir)).use { for (packageEntry in it.entries()) { if (packageEntry.name.startsWith("firebase-")) return false } diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/utils/CommandClient.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/utils/CommandClient.kt index 6b9582f881..4b6c3bb2aa 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/utils/CommandClient.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/utils/CommandClient.kt @@ -20,7 +20,7 @@ import kotlinx.coroutines.launch open class CommandClient( private val scope: CoroutineScope, private val connectionType: ConnectionType, - private val handler: Handler + private val handler: Handler, ) { enum class ConnectionType { @@ -31,16 +31,19 @@ open class CommandClient( fun onConnected() {} fun onDisconnected() {} + fun updateStatus(status: StatusMessage) {} - fun updateGroups(newGroups: MutableList) {} + fun clearLogs() {} fun appendLogs(message: List) {} + + fun updateGroups(newGroups: MutableList) {} + fun initializeClashMode(modeList: List, currentMode: String) {} fun updateClashMode(newMode: String) {} } - private var commandClient: CommandClient? = null private val clientHandler = ClientHandler() fun connect() { @@ -52,7 +55,7 @@ open class CommandClient( ConnectionType.Log -> Libbox.CommandLog ConnectionType.ClashMode -> Libbox.CommandClashMode } - options.statusInterval = 2 * 1000 * 1000 * 1000 + options.statusInterval = 1 * 1000 * 1000 * 1000 val commandClient = CommandClient(clientHandler, options) scope.launch(Dispatchers.IO) { for (i in 1..10) { @@ -119,10 +122,7 @@ open class CommandClient( handler.appendLogs(messageList.toList()) } - override fun writeStatus(message: StatusMessage?) { - if (message == null) { - return - } + override fun writeStatus(message: StatusMessage) { handler.updateStatus(message) } diff --git a/sing-box/clients/android/app/src/main/res/values/strings.xml b/sing-box/clients/android/app/src/main/res/values/strings.xml index 16654a56d1..80a3535462 100644 --- a/sing-box/clients/android/app/src/main/res/values/strings.xml +++ b/sing-box/clients/android/app/src/main/res/values/strings.xml @@ -75,6 +75,8 @@ Start command server Create service Start service + Deprecated Warning + Documentation Status Memory diff --git a/sing-box/clients/android/app/src/play/java/io/nekohasekai/sfa/vendor/MLKitQRCodeAnalyzer.kt b/sing-box/clients/android/app/src/play/java/io/nekohasekai/sfa/vendor/MLKitQRCodeAnalyzer.kt index 9e27c9279a..4ac8132767 100644 --- a/sing-box/clients/android/app/src/play/java/io/nekohasekai/sfa/vendor/MLKitQRCodeAnalyzer.kt +++ b/sing-box/clients/android/app/src/play/java/io/nekohasekai/sfa/vendor/MLKitQRCodeAnalyzer.kt @@ -29,7 +29,9 @@ class MLKitQRCodeAnalyzer( override fun analyze(image: ImageProxy) { if (image.image == null) return - if (failureOccurred && System.currentTimeMillis() - failureTimestamp < 1000L) { + val nowMills = System.currentTimeMillis() + if (failureOccurred && nowMills - failureTimestamp < 5000L) { + failureTimestamp = nowMills Log.d("MLKitQRCodeAnalyzer", "throttled analysis since error occurred in previous pass") image.close() return diff --git a/sing-box/clients/android/build.gradle b/sing-box/clients/android/build.gradle index 5765378f01..9958810d7e 100644 --- a/sing-box/clients/android/build.gradle +++ b/sing-box/clients/android/build.gradle @@ -5,8 +5,8 @@ buildscript { } plugins { - id 'com.android.application' version '8.7.0' apply false - id 'com.android.library' version '8.7.0' apply false + id 'com.android.application' version '8.7.2' apply false + id 'com.android.library' version '8.7.2' apply false id 'org.jetbrains.kotlin.android' version '1.9.23' apply false id 'com.google.devtools.ksp' version '1.9.23-1.0.20' apply false id 'com.github.triplet.play' version '3.8.4' apply false diff --git a/sing-box/clients/android/settings.gradle b/sing-box/clients/android/settings.gradle index c7eb8d7d86..3195007290 100644 --- a/sing-box/clients/android/settings.gradle +++ b/sing-box/clients/android/settings.gradle @@ -10,6 +10,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven { url "https://jitpack.io" } } } rootProject.name = "sing-box" diff --git a/sing-box/clients/android/version.properties b/sing-box/clients/android/version.properties index 1265e0ae2b..6895ae725b 100644 --- a/sing-box/clients/android/version.properties +++ b/sing-box/clients/android/version.properties @@ -1,3 +1,3 @@ -VERSION_CODE=401 -VERSION_NAME=1.10.1 -GO_VERSION=go1.23.2 +VERSION_CODE=423 +VERSION_NAME=1.10.2 +GO_VERSION=go1.23.3 diff --git a/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/DashboardView.swift b/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/DashboardView.swift index 6221a600d9..c7c851aa4c 100644 --- a/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/DashboardView.swift +++ b/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/DashboardView.swift @@ -83,6 +83,7 @@ public struct DashboardView: View { } struct DashboardView1: View { + @Environment(\.openURL) var openURL @EnvironmentObject private var environments: ExtensionEnvironments @EnvironmentObject private var profile: ExtensionProfile @State private var alert: Alert? @@ -100,6 +101,9 @@ public struct DashboardView: View { if newValue == .disconnecting || newValue == .connected { Task { await checkServiceError() + if newValue == .connected { + await checkDeprecatedNotes() + } } } else if newValue == .connecting { notStarted = true @@ -115,6 +119,45 @@ public struct DashboardView: View { } } + private nonisolated func checkDeprecatedNotes() async { + do { + let reports = try LibboxNewStandaloneCommandClient()!.getDeprecatedNotes() + if reports.hasNext() { + await MainActor.run { + loopShowDeprecateNotes(reports) + } + } + } catch { + await MainActor.run { + alert = Alert(error) + } + } + } + + @MainActor + private func loopShowDeprecateNotes(_ reports: any LibboxDeprecatedNoteIteratorProtocol) { + if reports.hasNext() { + let report = reports.next()! + alert = Alert( + title: Text("Deprecated Warning"), + message: Text(report.message()), + primaryButton: .default(Text("Documentation")) { + openURL(URL(string: report.migrationLink)!) + Task.detached { + try await Task.sleep(nanoseconds: 300 * MSEC_PER_SEC) + await loopShowDeprecateNotes(reports) + } + }, + secondaryButton: .cancel(Text("Ok")) { + Task.detached { + try await Task.sleep(nanoseconds: 300 * MSEC_PER_SEC) + await loopShowDeprecateNotes(reports) + } + } + ) + } + } + private nonisolated func checkServiceError() async { var error: NSError? let message = LibboxReadServiceError(&error) diff --git a/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/ExtensionStatusView.swift b/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/ExtensionStatusView.swift index a525b91614..3ab21f156a 100644 --- a/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/ExtensionStatusView.swift +++ b/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/ExtensionStatusView.swift @@ -5,6 +5,7 @@ import SwiftUI public struct ExtensionStatusView: View { @Environment(\.scenePhase) private var scenePhase @StateObject private var commandClient = CommandClient(.status) + @State private var columnCount: Int = 4 @State private var alert: Alert? diff --git a/sing-box/clients/apple/ApplicationLibrary/Views/Groups/GroupView.swift b/sing-box/clients/apple/ApplicationLibrary/Views/Groups/GroupView.swift index 8d06140dbd..646aabfa12 100644 --- a/sing-box/clients/apple/ApplicationLibrary/Views/Groups/GroupView.swift +++ b/sing-box/clients/apple/ApplicationLibrary/Views/Groups/GroupView.swift @@ -52,6 +52,7 @@ public struct GroupView: View { } .alertBinding($alert) .padding([.top, .bottom], 8) + .animation(.easeInOut, value: group.isExpand) } public var body: some View { diff --git a/sing-box/clients/apple/Library/Network/CommandClient.swift b/sing-box/clients/apple/Library/Network/CommandClient.swift index b88c7017a0..bf235f7db8 100644 --- a/sing-box/clients/apple/Library/Network/CommandClient.swift +++ b/sing-box/clients/apple/Library/Network/CommandClient.swift @@ -14,7 +14,6 @@ public class CommandClient: ObservableObject { private let logMaxLines: Int private var commandClient: LibboxCommandClient? private var connectTask: Task? - @Published public var isConnected: Bool @Published public var status: LibboxStatusMessage? @Published public var groups: [LibboxOutboundGroup]? @@ -173,7 +172,7 @@ public class CommandClient: ObservableObject { } DispatchQueue.main.async { [self] in if commandClient.logList.count >= commandClient.logMaxLines { - commandClient.logList.removeSubrange(0 ..< Int(messageList.len())) + commandClient.logList.removeFirst() } while messageList.hasNext() { commandClient.logList.append(messageList.next()) diff --git a/sing-box/clients/apple/Library/Network/ExtensionPlatformInterface.swift b/sing-box/clients/apple/Library/Network/ExtensionPlatformInterface.swift index f29705eeb3..2f315b4e90 100644 --- a/sing-box/clients/apple/Library/Network/ExtensionPlatformInterface.swift +++ b/sing-box/clients/apple/Library/Network/ExtensionPlatformInterface.swift @@ -1,6 +1,7 @@ import Foundation import Libbox import NetworkExtension +import UserNotifications #if canImport(CoreWLAN) import CoreWLAN #endif @@ -39,7 +40,10 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc if let error { throw error } - settings.dnsSettings = NEDNSSettings(servers: [dnsServer]) + let dnsSettings = NEDNSSettings(servers: [dnsServer]) + dnsSettings.matchDomains = [""] + dnsSettings.matchDomainsNoSearch = true + settings.dnsSettings = dnsSettings var ipv4Address: [String] = [] var ipv4Mask: [String] = [] @@ -335,4 +339,28 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc func reset() { networkSettings = nil } + + public func send(_ notification: LibboxNotification?) throws { + #if !os(tvOS) + guard let notification else { + return + } + let center = UNUserNotificationCenter.current() + let content = UNMutableNotificationContent() + + content.title = notification.title + content.subtitle = notification.subtitle + content.body = notification.body + if !notification.openURL.isEmpty { + content.userInfo["OPEN_URL"] = notification.openURL + content.categoryIdentifier = "OPEN_URL" + } + content.interruptionLevel = .active + let request = UNNotificationRequest(identifier: notification.identifier, content: content, trigger: nil) + try runBlocking { + try await center.requestAuthorization(options: [.alert]) + try await center.add(request) + } + #endif + } } diff --git a/sing-box/clients/apple/MacLibrary/ApplicationDelegate.swift b/sing-box/clients/apple/MacLibrary/ApplicationDelegate.swift index 9cbe221ba1..078bc0dbc1 100644 --- a/sing-box/clients/apple/MacLibrary/ApplicationDelegate.swift +++ b/sing-box/clients/apple/MacLibrary/ApplicationDelegate.swift @@ -3,11 +3,25 @@ import ApplicationLibrary import Foundation import Libbox import Library +import UserNotifications -open class ApplicationDelegate: NSObject, NSApplicationDelegate { +open class ApplicationDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate { public func applicationDidFinishLaunching(_: Notification) { NSLog("Here I stand") LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false) + let notificationCenter = UNUserNotificationCenter.current() + notificationCenter.setNotificationCategories([ + UNNotificationCategory( + identifier: "OPEN_URL", + actions: [ + UNNotificationAction(identifier: "COPY_URL", title: "Copy URL", options: .foreground, icon: UNNotificationActionIcon(systemImageName: "clipboard.fill")), + UNNotificationAction(identifier: "OPEN_URL", title: "Open", options: .foreground, icon: UNNotificationActionIcon(systemImageName: "safari.fill")), + ], + intentIdentifiers: [] + ), + ] + ) + notificationCenter.delegate = self let event = NSAppleEventManager.shared().currentAppleEvent let launchedAsLogInItem = event?.eventID == kAEOpenApplication && @@ -34,6 +48,23 @@ open class ApplicationDelegate: NSObject, NSApplicationDelegate { } } + public func userNotificationCenter(_: UNUserNotificationCenter, willPresent _: UNNotification) async -> UNNotificationPresentationOptions { + .banner + } + + public func userNotificationCenter(_: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { + if let url = response.notification.request.content.userInfo["OPEN_URL"] as? String { + switch response.actionIdentifier { + case "COPY_URL": + NSPasteboard.general.setString(url, forType: .URL) + case "OPEN_URL": + fallthrough + default: + NSWorkspace.shared.open(URL(string: url)!) + } + } + } + public func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool { SharedPreferences.inDebug || !SharedPreferences.menuBarExtraInBackground.getBlocking() } diff --git a/sing-box/clients/apple/SFI/ApplicationDelegate.swift b/sing-box/clients/apple/SFI/ApplicationDelegate.swift index 01202425e0..6ab06c7053 100644 --- a/sing-box/clients/apple/SFI/ApplicationDelegate.swift +++ b/sing-box/clients/apple/SFI/ApplicationDelegate.swift @@ -4,17 +4,48 @@ import Libbox import Library import Network import UIKit +import UserNotifications -class ApplicationDelegate: NSObject, UIApplicationDelegate { +class ApplicationDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate { private var profileServer: ProfileServer? func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { NSLog("Here I stand") LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false) + let notificationCenter = UNUserNotificationCenter.current() + notificationCenter.setNotificationCategories([ + UNNotificationCategory( + identifier: "OPEN_URL", + actions: [ + UNNotificationAction(identifier: "COPY_URL", title: "Copy URL", options: .foreground, icon: UNNotificationActionIcon(systemImageName: "clipboard.fill")), + UNNotificationAction(identifier: "OPEN_URL", title: "Open", options: .foreground, icon: UNNotificationActionIcon(systemImageName: "safari.fill")), + ], + intentIdentifiers: [] + ), + ] + ) + notificationCenter.delegate = self setup() return true } + func userNotificationCenter(_: UNUserNotificationCenter, willPresent _: UNNotification) async -> UNNotificationPresentationOptions { + .banner + } + + func userNotificationCenter(_: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { + if let url = response.notification.request.content.userInfo["OPEN_URL"] as? String { + switch response.actionIdentifier { + case "COPY_URL": + UIPasteboard.general.string = url + case "OPEN_URL": + fallthrough + default: + await UIApplication.shared.open(URL(string: url)!) + } + } + } + private func setup() { do { try UIProfileUpdateTask.configure() diff --git a/sing-box/clients/apple/sing-box.xcodeproj/project.pbxproj b/sing-box/clients/apple/sing-box.xcodeproj/project.pbxproj index 70ef19d2b7..955925825c 100644 --- a/sing-box/clients/apple/sing-box.xcodeproj/project.pbxproj +++ b/sing-box/clients/apple/sing-box.xcodeproj/project.pbxproj @@ -483,7 +483,6 @@ 3A27D8FF2A89BE230031EBCC /* CommandClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandClient.swift; sourceTree = ""; }; 3A27D9012A89C6870031EBCC /* ExtensionEnvironments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionEnvironments.swift; sourceTree = ""; }; 3A2EAEEC2A6F4CBB00D00DE3 /* StandaloneApplicationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandaloneApplicationDelegate.swift; sourceTree = ""; }; - 3A334ECF2C0F621E00E9C577 /* ConnectionDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionDetailsView.swift; sourceTree = ""; }; 3A2F29EA2C998A5D007E024C /* Export.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Export.plist; sourceTree = ""; }; 3A334ECF2C0F621E00E9C577 /* ConnectionDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionDetailsView.swift; sourceTree = ""; }; 3A3AB2A62B70C146001815AE /* CoreView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreView.swift; sourceTree = ""; }; @@ -2148,7 +2147,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; SDKROOT = appletvos; @@ -2183,7 +2182,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; SDKROOT = appletvos; @@ -2488,7 +2487,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; OTHER_CODE_SIGN_FLAGS = "--deep"; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; @@ -2530,7 +2529,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; OTHER_CODE_SIGN_FLAGS = "--deep"; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; @@ -2553,7 +2552,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 284; + CURRENT_PROJECT_VERSION = 286; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 287TTNZF8L; ENABLE_HARDENED_RUNTIME = YES; @@ -2571,7 +2570,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; OTHER_CODE_SIGN_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; @@ -2593,7 +2592,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 284; + CURRENT_PROJECT_VERSION = 286; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 287TTNZF8L; ENABLE_HARDENED_RUNTIME = YES; @@ -2611,7 +2610,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; OTHER_CODE_SIGN_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; @@ -2739,7 +2738,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt.system; PRODUCT_NAME = "$(inherited)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2775,7 +2774,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt.system; PRODUCT_NAME = "$(inherited)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2817,7 +2816,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt.standalone; PRODUCT_NAME = SFM; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2858,7 +2857,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.0; + MARKETING_VERSION = 1.10.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt.standalone; PRODUCT_NAME = SFM; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/sing-box/common/tls/ech_server.go b/sing-box/common/tls/ech_server.go index ac3e6279c3..c38fe673d8 100644 --- a/sing-box/common/tls/ech_server.go +++ b/sing-box/common/tls/ech_server.go @@ -97,6 +97,10 @@ func (c *echServerConfig) startWatcher() error { if err != nil { return err } + err = c.watcher.Start() + if err != nil { + return err + } c.watcher = watcher return nil } @@ -232,7 +236,7 @@ func NewECHServer(ctx context.Context, logger log.Logger, options option.Inbound var echKey []byte if len(options.ECH.Key) > 0 { echKey = []byte(strings.Join(options.ECH.Key, "\n")) - } else if options.KeyPath != "" { + } else if options.ECH.KeyPath != "" { content, err := os.ReadFile(options.ECH.KeyPath) if err != nil { return nil, E.Cause(err, "read ECH key") diff --git a/sing-box/common/tls/std_server.go b/sing-box/common/tls/std_server.go index 7001bd3a04..e894dadee1 100644 --- a/sing-box/common/tls/std_server.go +++ b/sing-box/common/tls/std_server.go @@ -106,6 +106,10 @@ func (c *STDServerConfig) startWatcher() error { if err != nil { return err } + err = c.watcher.Start() + if err != nil { + return err + } c.watcher = watcher return nil } diff --git a/sing-box/docs/changelog.md b/sing-box/docs/changelog.md index ecdb7080c1..cf86a82e94 100644 --- a/sing-box/docs/changelog.md +++ b/sing-box/docs/changelog.md @@ -2,6 +2,16 @@ icon: material/alert-decagram --- +#### 1.11.0-alpha.19 + +* Fixes and improvements + +### 1.10.2 + +* Add deprecated warnings +* Fix proxying websocket connections in HTTP/mixed inbounds +* Fixes and improvements + #### 1.11.0-alpha.18 * Fixes and improvements diff --git a/sing-box/go.mod b/sing-box/go.mod index 83851285ee..cdb9341b82 100644 --- a/sing-box/go.mod +++ b/sing-box/go.mod @@ -25,14 +25,14 @@ require ( github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3 github.com/sagernet/quic-go v0.48.1-beta.1 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 - github.com/sagernet/sing v0.6.0-alpha.16 - github.com/sagernet/sing-dns v0.4.0-alpha.2 + github.com/sagernet/sing v0.6.0-alpha.17 + github.com/sagernet/sing-dns v0.4.0-alpha.3 github.com/sagernet/sing-mux v0.3.0-alpha.1 - github.com/sagernet/sing-quic v0.4.0-alpha.3 + github.com/sagernet/sing-quic v0.4.0-alpha.4 github.com/sagernet/sing-shadowsocks v0.2.7 github.com/sagernet/sing-shadowsocks2 v0.2.0 - github.com/sagernet/sing-shadowtls v0.2.0-alpha.1 - github.com/sagernet/sing-tun v0.6.0-alpha.8 + github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 + github.com/sagernet/sing-tun v0.6.0-alpha.9 github.com/sagernet/sing-vmess v0.1.12 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 github.com/sagernet/utls v1.6.7 @@ -53,6 +53,8 @@ require ( howett.net/plist v1.0.1 ) +//replace github.com/sagernet/sing => ../sing + require ( github.com/ajg/form v1.5.1 // indirect github.com/andybalholm/brotli v1.0.6 // indirect diff --git a/sing-box/go.sum b/sing-box/go.sum index 6feb1dad2c..c001e8ae69 100644 --- a/sing-box/go.sum +++ b/sing-box/go.sum @@ -110,24 +110,22 @@ github.com/sagernet/quic-go v0.48.1-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.6.0-alpha.16 h1:Ml+nJa8J9d+Svqv2pBvJoet+8PF302Snb6wcMUXaoy4= -github.com/sagernet/sing v0.6.0-alpha.16/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing-dns v0.4.0-alpha.2 h1:0x5WjrO+Ifk9sqJlHRz/tKENHwoEinQ8HQCHAhpJHAQ= -github.com/sagernet/sing-dns v0.4.0-alpha.2/go.mod h1:ZiXcacKL54jSSYZMbYF3qKNFkkW674Jt+85YCmK64K8= +github.com/sagernet/sing v0.6.0-alpha.17 h1:y//jVrBjJMW6tRpA/ElT7+Snp3DHEJvO60D+DByg/Es= +github.com/sagernet/sing v0.6.0-alpha.17/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing-dns v0.4.0-alpha.3 h1:TcAQdz68Gs28VD9o9zDIW7IS8A9LZDruTPI9g9JbGHA= +github.com/sagernet/sing-dns v0.4.0-alpha.3/go.mod h1:9LHcYKg2bGQpbtXrfNbopz8ok/zBK9ljiI2kmFG9JKg= github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg= github.com/sagernet/sing-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE= -github.com/sagernet/sing-quic v0.4.0-alpha.3 h1:2svvOqgQCJg7FNrIrLTaRB6oDzXPiIyWIt9csjZxD6Q= -github.com/sagernet/sing-quic v0.4.0-alpha.3/go.mod h1:Fmnpy0XoyYdjJrxNqEyl3LC9uLibMNNbxG7dt6HATY4= +github.com/sagernet/sing-quic v0.4.0-alpha.4 h1:P9xAx3nIfcqb9M8jfgs0uLm+VxCcaY++FCqaBfHY3dQ= +github.com/sagernet/sing-quic v0.4.0-alpha.4/go.mod h1:h5RkKTmUhudJKzK7c87FPXD5w1bJjVyxMN9+opZcctA= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= -github.com/sagernet/sing-shadowtls v0.1.5-0.20241117084441-2711c0c857f0 h1:zH35YfgT29AphYX8OWDftjun4ClA+oTptUkKLPC0KeY= -github.com/sagernet/sing-shadowtls v0.1.5-0.20241117084441-2711c0c857f0/go.mod h1:9wA+bA/j7RiGPNKo7As8neMTu/PRU9FDpFhU5yVT4lE= -github.com/sagernet/sing-shadowtls v0.2.0-alpha.1 h1:Mu2mp1TRaHY+yL+oxMP9XQIQwvwYLTVg8jhuOQbF/XY= -github.com/sagernet/sing-shadowtls v0.2.0-alpha.1/go.mod h1:9wA+bA/j7RiGPNKo7As8neMTu/PRU9FDpFhU5yVT4lE= -github.com/sagernet/sing-tun v0.6.0-alpha.8 h1:HhXyUvXxtaXgT+IILZMq6kbrAyDbUwbN+Df/XxpL7Vo= -github.com/sagernet/sing-tun v0.6.0-alpha.8/go.mod h1:JkgiLLnQUXln1zLGVoJqUwAulJGT0xoiPU4/pYF1fhU= +github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0= +github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA= +github.com/sagernet/sing-tun v0.6.0-alpha.9 h1:Qf667035KnlydZ+ftj3U4HH+oddi3RdyKzBiCcnSgaI= +github.com/sagernet/sing-tun v0.6.0-alpha.9/go.mod h1:TgvxE2YD7O9c/unHju0nWAGBGsVppWIuju13vlmdllM= github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg= github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= diff --git a/sing-box/test/go.mod b/sing-box/test/go.mod index 42b2c00471..a232fede5b 100644 --- a/sing-box/test/go.mod +++ b/sing-box/test/go.mod @@ -13,9 +13,9 @@ require ( github.com/docker/go-connections v0.5.0 github.com/gofrs/uuid/v5 v5.3.0 github.com/sagernet/quic-go v0.48.1-beta.1 - github.com/sagernet/sing v0.6.0-alpha.16 - github.com/sagernet/sing-dns v0.4.0-alpha.2 - github.com/sagernet/sing-quic v0.4.0-alpha.3 + github.com/sagernet/sing v0.6.0-alpha.17 + github.com/sagernet/sing-dns v0.4.0-alpha.3 + github.com/sagernet/sing-quic v0.4.0-alpha.4 github.com/sagernet/sing-shadowsocks v0.2.7 github.com/sagernet/sing-shadowsocks2 v0.2.0 github.com/spyzhov/ajson v0.9.4 @@ -25,7 +25,7 @@ require ( ) require ( - github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/go-winio v0.4.14 // indirect github.com/ajg/form v1.5.1 // indirect github.com/andybalholm/brotli v1.0.6 // indirect github.com/caddyserver/certmagic v0.20.0 // indirect @@ -33,7 +33,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/cretz/bine v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/distribution/reference v0.5.0 // indirect + github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -68,10 +68,10 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/onsi/ginkgo/v2 v2.9.7 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/oschwald/maxminddb-golang v1.12.0 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/pkg/errors v0.8.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect @@ -84,8 +84,8 @@ require ( github.com/sagernet/nftables v0.3.0-beta.4 // indirect github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect github.com/sagernet/sing-mux v0.3.0-alpha.1 // indirect - github.com/sagernet/sing-shadowtls v0.2.0-alpha.1 // indirect - github.com/sagernet/sing-tun v0.6.0-alpha.8 // indirect + github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 // indirect + github.com/sagernet/sing-tun v0.6.0-alpha.9 // indirect github.com/sagernet/sing-vmess v0.1.12 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect github.com/sagernet/utls v1.6.7 // indirect @@ -94,12 +94,12 @@ require ( github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect github.com/vishvananda/netns v0.0.4 // indirect github.com/zeebo/blake3 v0.2.3 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/sdk v1.31.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect @@ -111,7 +111,7 @@ require ( golang.org/x/text v0.20.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.24.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/sing-box/test/go.sum b/sing-box/test/go.sum index 769969b48d..6d5cc3effe 100644 --- a/sing-box/test/go.sum +++ b/sing-box/test/go.sum @@ -1,7 +1,7 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= @@ -19,8 +19,8 @@ github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbe github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -62,8 +62,8 @@ github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5X github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= @@ -78,6 +78,7 @@ github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6K github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= @@ -113,14 +114,14 @@ github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs= github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY= github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= @@ -146,22 +147,22 @@ github.com/sagernet/quic-go v0.48.1-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.6.0-alpha.16 h1:Ml+nJa8J9d+Svqv2pBvJoet+8PF302Snb6wcMUXaoy4= -github.com/sagernet/sing v0.6.0-alpha.16/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing-dns v0.4.0-alpha.2 h1:0x5WjrO+Ifk9sqJlHRz/tKENHwoEinQ8HQCHAhpJHAQ= -github.com/sagernet/sing-dns v0.4.0-alpha.2/go.mod h1:ZiXcacKL54jSSYZMbYF3qKNFkkW674Jt+85YCmK64K8= +github.com/sagernet/sing v0.6.0-alpha.17 h1:y//jVrBjJMW6tRpA/ElT7+Snp3DHEJvO60D+DByg/Es= +github.com/sagernet/sing v0.6.0-alpha.17/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing-dns v0.4.0-alpha.3 h1:TcAQdz68Gs28VD9o9zDIW7IS8A9LZDruTPI9g9JbGHA= +github.com/sagernet/sing-dns v0.4.0-alpha.3/go.mod h1:9LHcYKg2bGQpbtXrfNbopz8ok/zBK9ljiI2kmFG9JKg= github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg= github.com/sagernet/sing-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE= -github.com/sagernet/sing-quic v0.4.0-alpha.3 h1:2svvOqgQCJg7FNrIrLTaRB6oDzXPiIyWIt9csjZxD6Q= -github.com/sagernet/sing-quic v0.4.0-alpha.3/go.mod h1:Fmnpy0XoyYdjJrxNqEyl3LC9uLibMNNbxG7dt6HATY4= +github.com/sagernet/sing-quic v0.4.0-alpha.4 h1:P9xAx3nIfcqb9M8jfgs0uLm+VxCcaY++FCqaBfHY3dQ= +github.com/sagernet/sing-quic v0.4.0-alpha.4/go.mod h1:h5RkKTmUhudJKzK7c87FPXD5w1bJjVyxMN9+opZcctA= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= -github.com/sagernet/sing-shadowtls v0.2.0-alpha.1 h1:Mu2mp1TRaHY+yL+oxMP9XQIQwvwYLTVg8jhuOQbF/XY= -github.com/sagernet/sing-shadowtls v0.2.0-alpha.1/go.mod h1:9wA+bA/j7RiGPNKo7As8neMTu/PRU9FDpFhU5yVT4lE= -github.com/sagernet/sing-tun v0.6.0-alpha.8 h1:HhXyUvXxtaXgT+IILZMq6kbrAyDbUwbN+Df/XxpL7Vo= -github.com/sagernet/sing-tun v0.6.0-alpha.8/go.mod h1:JkgiLLnQUXln1zLGVoJqUwAulJGT0xoiPU4/pYF1fhU= +github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0= +github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA= +github.com/sagernet/sing-tun v0.6.0-alpha.9 h1:Qf667035KnlydZ+ftj3U4HH+oddi3RdyKzBiCcnSgaI= +github.com/sagernet/sing-tun v0.6.0-alpha.9/go.mod h1:TgvxE2YD7O9c/unHju0nWAGBGsVppWIuju13vlmdllM= github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg= github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= @@ -172,11 +173,14 @@ github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYASco github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8/go.mod h1:K4J7/npM+VAMUeUmTa2JaA02JmyheP0GpRBOUvn3ecc= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spyzhov/ajson v0.9.4 h1:MVibcTCgO7DY4IlskdqIlCmDOsUOZ9P7oKj8ifdcf84= github.com/spyzhov/ajson v0.9.4/go.mod h1:a6oSw0MMb7Z5aD2tPoPO+jq11ETKgXUr2XktHdT8Wt8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -193,20 +197,20 @@ github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0/go.mod h1:wZcGmeVO9nzP67aYSLDqXNWK87EZWhi7JWj1v7ZXf94= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -242,8 +246,10 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -274,10 +280,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= diff --git a/small/luci-app-passwall/Makefile b/small/luci-app-passwall/Makefile index db3778313e..4a14c500fb 100644 --- a/small/luci-app-passwall/Makefile +++ b/small/luci-app-passwall/Makefile @@ -6,8 +6,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall -PKG_VERSION:=4.78-4 -PKG_RELEASE:= +PKG_VERSION:=24.11.18 +PKG_RELEASE:=2 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/small/luci-app-passwall/luasrc/passwall/util_sing-box.lua b/small/luci-app-passwall/luasrc/passwall/util_sing-box.lua index 6a74cd40a1..d4f516878b 100644 --- a/small/luci-app-passwall/luasrc/passwall/util_sing-box.lua +++ b/small/luci-app-passwall/luasrc/passwall/util_sing-box.lua @@ -927,11 +927,9 @@ function gen_config(var) if node.protocol == "_shunt" then local rules = {} - local preproxy_enabled = node.preproxy_enabled == "1" - local preproxy_rule_name = "main" - local preproxy_tag = "main" - local preproxy_node_id = node["main_node"] - local preproxy_node = preproxy_enabled and preproxy_node_id and uci:get_all(appname, preproxy_node_id) or nil + local preproxy_rule_name = node.preproxy_enabled == "1" and "main" or nil + local preproxy_tag = preproxy_rule_name + local preproxy_node_id = preproxy_rule_name and node["main_node"] or nil local function gen_shunt_node(rule_name, _node_id) if not rule_name then return nil, nil end @@ -956,7 +954,6 @@ function gen_config(var) } local _outbound = gen_outbound(flag, _node, rule_name) if _outbound then - _outbound.tag = _outbound.tag .. ":" .. _node.remarks table.insert(outbounds, _outbound) rule_outboundTag = _outbound.tag end @@ -966,10 +963,10 @@ function gen_config(var) if not _node then return nil, nil end if api.is_normal_node(_node) then - local proxy = preproxy_enabled and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id + local use_proxy = preproxy_tag and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id local copied_outbound for index, value in ipairs(outbounds) do - if value["_id"] == _node_id and value["_flag_proxy_tag"] == preproxy_tag then + if value["_id"] == _node_id and value["_flag_proxy_tag"] == (use_proxy and preproxy_tag or nil) then copied_outbound = api.clone(value) break end @@ -979,7 +976,7 @@ function gen_config(var) table.insert(outbounds, copied_outbound) rule_outboundTag = copied_outbound.tag else - if proxy then + if use_proxy then local pre_proxy = nil if _node.type ~= "sing-box" then pre_proxy = true @@ -1006,7 +1003,7 @@ function gen_config(var) end end - local _outbound = gen_outbound(flag, _node, rule_name, { tag = proxy and preproxy_tag or nil }) + local _outbound = gen_outbound(flag, _node, rule_name, { tag = use_proxy and preproxy_tag or nil }) if _outbound then _outbound.tag = _outbound.tag .. ":" .. _node.remarks rule_outboundTag = set_outbound_detour(_node, _outbound, outbounds, rule_name) @@ -1030,12 +1027,10 @@ function gen_config(var) return rule_outboundTag end - if preproxy_node then + if preproxy_tag and preproxy_node_id then local preproxy_outboundTag = gen_shunt_node(preproxy_rule_name, preproxy_node_id) if preproxy_outboundTag then preproxy_tag = preproxy_outboundTag - else - preproxy_node = nil end end --default_node diff --git a/small/luci-app-passwall/luasrc/passwall/util_xray.lua b/small/luci-app-passwall/luasrc/passwall/util_xray.lua index 04d46f0568..30d56e1410 100644 --- a/small/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/small/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -758,16 +758,15 @@ function gen_config(var) end -- new balancer local blc_nodes = _node.balancing_node - local length = #blc_nodes local valid_nodes = {} - for i = 1, length do + for i = 1, #blc_nodes do local blc_node_id = blc_nodes[i] local blc_node_tag = "blc-" .. blc_node_id local is_new_blc_node = true for _, outbound in ipairs(outbounds) do - if outbound.tag == blc_node_tag then + if outbound.tag:find("^" .. blc_node_tag) == 1 then is_new_blc_node = false - valid_nodes[#valid_nodes + 1] = blc_node_tag + valid_nodes[#valid_nodes + 1] = outbound.tag break end end @@ -777,7 +776,7 @@ function gen_config(var) if outbound then outbound.tag = outbound.tag .. ":" .. blc_node.remarks table.insert(outbounds, outbound) - valid_nodes[#valid_nodes + 1] = blc_node_tag + valid_nodes[#valid_nodes + 1] = outbound.tag end end end @@ -1241,7 +1240,9 @@ function gen_config(var) } }) else - if COMMON.default_outbound_tag then + if COMMON.default_balancer_tag then + dns_outbound_tag = nil + elseif COMMON.default_outbound_tag then dns_outbound_tag = COMMON.default_outbound_tag end end @@ -1262,9 +1263,9 @@ function gen_config(var) table.insert(outbounds, { tag = "dns-out", protocol = "dns", - proxySettings = { + proxySettings = dns_outbound_tag and { tag = dns_outbound_tag - }, + } or nil, settings = { address = remote_dns_tcp_server, port = tonumber(remote_dns_tcp_port), @@ -1288,6 +1289,7 @@ function gen_config(var) remote_dns_tcp_server }, port = tonumber(remote_dns_tcp_port), + balancerTag = COMMON.default_balancer_tag, outboundTag = dns_outbound_tag }) if _remote_dns_host then @@ -1299,6 +1301,7 @@ function gen_config(var) _remote_dns_host }, port = tonumber(remote_dns_doh_port), + balancerTag = COMMON.default_balancer_tag, outboundTag = dns_outbound_tag }) end @@ -1311,6 +1314,7 @@ function gen_config(var) remote_dns_doh_ip }, port = tonumber(remote_dns_doh_port), + balancerTag = COMMON.default_balancer_tag, outboundTag = dns_outbound_tag }) end diff --git a/small/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm b/small/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm index 849bb6dac4..6a15a52f71 100644 --- a/small/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm +++ b/small/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm @@ -812,6 +812,11 @@ local api = require "luci.passwall.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); @@ -851,7 +856,7 @@ local api = require "luci.passwall.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } } } else { @@ -922,6 +927,11 @@ local api = require "luci.passwall.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); @@ -961,7 +971,7 @@ local api = require "luci.passwall.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } if (m.hash) { @@ -1001,8 +1011,13 @@ local api = require "luci.passwall.api" ssm.net = ssm.net.toLowerCase(); if (ssm.net === "kcp" || ssm.net === "mkcp") ssm.net = "mkcp" + if (dom_prefix == "singbox_" && ssm.net === "raw") { + ssm.net = "tcp"; + } else if (dom_prefix == "xray_" && ssm.net === "tcp") { + ssm.net = "raw"; + } opt.set(dom_prefix + 'transport', ssm.net); - if (ssm.net === "raw") { + if (ssm.net === "raw" || ssm.net === "tcp") { opt.set(dom_prefix + 'tcp_guise', (ssm.host && ssm.path) ? "http" : "none"); if (ssm.host && ssm.path) { opt.set(dom_prefix + 'tcp_guise_http_host', ssm.host); @@ -1109,6 +1124,11 @@ local api = require "luci.passwall.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); @@ -1148,7 +1168,7 @@ local api = require "luci.passwall.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } else if (queryParam.type === "xhttp" || queryParam.type === "splithttp") { opt.set(dom_prefix + 'xhttp_host', queryParam.host || ""); opt.set(dom_prefix + 'xhttp_path', queryParam.path || ""); diff --git a/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 73f5fb7eb9..ada7b9b88a 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -442,10 +442,13 @@ local function processData(szType, content, add_mode, add_from) -- result.mux = 1 -- result.mux_concurrency = 8 - if not info.net then - info.net = "tcp" - end + if not info.net then info.net = "tcp" end info.net = string.lower(info.net) + if result.type == "sing-box" and info.net == "raw" then + info.net = "tcp" + elseif result.type == "Xray" and info.net == "tcp" then + info.net = "raw" + end result.transport = info.net if info.net == 'ws' then result.ws_host = info.host @@ -514,7 +517,7 @@ local function processData(szType, content, add_mode, add_from) result.tls = "0" end - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "raw" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -602,7 +605,7 @@ local function processData(szType, content, add_mode, add_from) if ss_type_default == "xray" and has_xray then result.type = 'Xray' result.protocol = 'shadowsocks' - result.transport = 'tcp' + result.transport = 'raw' end if ss_type_default == "sing-box" and has_singbox then result.type = 'sing-box' @@ -643,6 +646,11 @@ local function processData(szType, content, add_mode, add_from) if params.type then params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if result.type ~= "SS-Rust" and result.type ~= "SS" then if params.type == 'ws' then @@ -699,7 +707,7 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end result.tls = "0" if params.security == "tls" or params.security == "reality" then @@ -783,10 +791,13 @@ local function processData(szType, content, add_mode, add_from) result.tls_allowInsecure = allowInsecure_default and "1" or "0" end - if not params.type then - params.type = "tcp" - end + if not params.type then params.type = "tcp" end params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if params.type == 'ws' then result.ws_host = params.host @@ -842,9 +853,9 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end - if info.net == 'xhttp' or info.net == 'splithttp' then + if params.type == 'xhttp' or params.type == 'splithttp' then result.xhttp_host = params.host result.xhttp_path = params.path end @@ -857,7 +868,7 @@ local function processData(szType, content, add_mode, add_from) result.flow = params.flow or nil - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "raw" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -920,10 +931,13 @@ local function processData(szType, content, add_mode, add_from) result.address = host_port end - if not params.type then - params.type = "tcp" - end + if not params.type then params.type = "tcp" end params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if params.type == 'ws' then result.ws_host = params.host @@ -979,9 +993,9 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end - if info.net == 'xhttp' or info.net == 'splithttp' then + if params.type == 'xhttp' or params.type == 'splithttp' then result.xhttp_host = params.host result.xhttp_path = params.path end @@ -1011,7 +1025,7 @@ local function processData(szType, content, add_mode, add_from) result.port = port result.tls_allowInsecure = allowInsecure_default and "1" or "0" - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "raw" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end diff --git a/small/luci-app-passwall2/Makefile b/small/luci-app-passwall2/Makefile index 579aacaf5c..52ec5c6685 100644 --- a/small/luci-app-passwall2/Makefile +++ b/small/luci-app-passwall2/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=24.11.17 -PKG_RELEASE:=2 +PKG_VERSION:=24.11.18 +PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index 26590fb41d..20650ff6d8 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -918,14 +918,9 @@ function gen_config(var) if node.protocol == "_shunt" then local rules = {} - local preproxy_enabled = node.preproxy_enabled == "1" - local preproxy_rule_name = "main" - local preproxy_tag = "main" - local preproxy_node_id = node["main_node"] - local preproxy_node = preproxy_enabled and preproxy_node_id and uci:get_all(appname, preproxy_node_id) or nil - if preproxy_node then - preproxy_tag = preproxy_tag .. ":" .. preproxy_node.remarks - end + local preproxy_rule_name = node.preproxy_enabled == "1" and "main" or nil + local preproxy_tag = preproxy_rule_name + local preproxy_node_id = preproxy_rule_name and node["main_node"] or nil local function gen_shunt_node(rule_name, _node_id) if not rule_name then return nil end @@ -950,7 +945,6 @@ function gen_config(var) } local _outbound = gen_outbound(flag, _node, rule_name) if _outbound then - _outbound.tag = _outbound.tag .. ":" .. _node.remarks table.insert(outbounds, _outbound) rule_outboundTag = _outbound.tag end @@ -960,10 +954,10 @@ function gen_config(var) if not _node then return nil end if api.is_normal_node(_node) then - local proxy = preproxy_enabled and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id + local use_proxy = preproxy_tag and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id local copied_outbound for index, value in ipairs(outbounds) do - if value["_id"] == _node_id and value["_flag_proxy_tag"] == preproxy_tag then + if value["_id"] == _node_id and value["_flag_proxy_tag"] == (use_proxy and preproxy_tag or nil) then copied_outbound = api.clone(value) break end @@ -973,7 +967,7 @@ function gen_config(var) table.insert(outbounds, copied_outbound) rule_outboundTag = copied_outbound.tag else - if proxy then + if use_proxy then local pre_proxy = nil if _node.type ~= "sing-box" then pre_proxy = true @@ -999,7 +993,8 @@ function gen_config(var) }) end end - local _outbound = gen_outbound(flag, _node, rule_name, { tag = proxy and preproxy_tag or nil }) + + local _outbound = gen_outbound(flag, _node, rule_name, { tag = use_proxy and preproxy_tag or nil }) if _outbound then _outbound.tag = _outbound.tag .. ":" .. _node.remarks rule_outboundTag = set_outbound_detour(_node, _outbound, outbounds, rule_name) @@ -1023,10 +1018,10 @@ function gen_config(var) return rule_outboundTag end - if preproxy_node then - proxy_outboundTag = gen_shunt_node(preproxy_rule_name, preproxy_node_id) - if not proxy_outboundTag then - preproxy_node = nil + if preproxy_tag and preproxy_node_id then + local preproxy_outboundTag = gen_shunt_node(preproxy_rule_name, preproxy_node_id) + if preproxy_outboundTag then + preproxy_tag = preproxy_outboundTag end end --default_node diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 816fa4ef6d..b482126ace 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -756,16 +756,15 @@ function gen_config(var) end -- new balancer local blc_nodes = _node.balancing_node - local length = #blc_nodes local valid_nodes = {} - for i = 1, length do + for i = 1, #blc_nodes do local blc_node_id = blc_nodes[i] local blc_node_tag = "blc-" .. blc_node_id local is_new_blc_node = true for _, outbound in ipairs(outbounds) do - if outbound.tag == blc_node_tag then + if outbound.tag:find("^" .. blc_node_tag) == 1 then is_new_blc_node = false - valid_nodes[#valid_nodes + 1] = blc_node_tag + valid_nodes[#valid_nodes + 1] = outbound.tag break end end @@ -775,7 +774,7 @@ function gen_config(var) if outbound then outbound.tag = outbound.tag .. ":" .. blc_node.remarks table.insert(outbounds, outbound) - valid_nodes[#valid_nodes + 1] = blc_node_tag + valid_nodes[#valid_nodes + 1] = outbound.tag end end end @@ -1050,6 +1049,7 @@ function gen_config(var) local domain_table = { shunt_rule_name = e[".name"], outboundTag = outboundTag, + balancerTag = balancerTag, domain = {}, } domains = {} @@ -1058,7 +1058,7 @@ function gen_config(var) table.insert(domains, w) table.insert(domain_table.domain, w) end) - if outboundTag and outboundTag ~= "nil" then + if (outboundTag and outboundTag ~= "nil") or (balancerTag and balancerTag ~= "nil") then table.insert(dns_domain_rules, api.clone(domain_table)) end if #domains == 0 then domains = nil end @@ -1107,16 +1107,15 @@ function gen_config(var) end end end) ---[[ - if default_outboundTag or default_balancerTag then + + if default_balancerTag then table.insert(rules, { - _flag = "default", - outboundTag = default_outboundTag, + ruleTag = "default", balancerTag = default_balancerTag, network = "tcp,udp" }) end -]] + routing = { domainStrategy = node.domainStrategy or "AsIs", domainMatcher = node.domainMatcher or "hybrid", @@ -1395,7 +1394,7 @@ function gen_config(var) --按分流顺序DNS if dns_domain_rules and #dns_domain_rules > 0 then for index, value in ipairs(dns_domain_rules) do - if value.outboundTag and value.domain then + if value.domain and (value.outboundTag or value.balancerTag) then local dns_server = nil if value.outboundTag == "direct" then dns_server = api.clone(_direct_dns) diff --git a/small/v2ray-geodata/Makefile b/small/v2ray-geodata/Makefile index e83d9daede..189caef42d 100644 --- a/small/v2ray-geodata/Makefile +++ b/small/v2ray-geodata/Makefile @@ -30,7 +30,7 @@ define Download/geosite HASH:=f04433837b88a3f49d7cd6517c91e8f5de4e4496f3d88ef3b7c6be5bb63f4c6f endef -GEOSITE_IRAN_VER:=202411151505 +GEOSITE_IRAN_VER:=202411180037 GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER) define Download/geosite-ir URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/ diff --git a/v2rayn/README.md b/v2rayn/README.md index 1724e118e6..cfbea55892 100644 --- a/v2rayn/README.md +++ b/v2rayn/README.md @@ -9,13 +9,19 @@ A GUI client for Windows and Linux, support [Xray core](https://github.com/XTLS/ ## How to use -- If you are new to this, please download v2rayN-With-Core.zip from [releases](https://github.com/2dust/v2rayN/releases) -- Otherwise please download v2rayN.zip (you will also need to download cores in the bin directory) -- Run v2rayN.exe +Check [Release files introduction](https://github.com/2dust/v2rayN/wiki/Release-files-introduction) and select the version you need to download +### Windows +- Run `v2rayN.exe` +### Linux +- `chmod +x v2rayN` Run `./v2rayN` +``` +Debian 9+ +Ubuntu 16.04+ +Fedora 30+ +``` ## Requirements -- (6.35 and above)[Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) -- (6.33 and below)[Microsoft .NET 6.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) +- [Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) - [Supported cores](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores) diff --git a/v2rayn/v2rayN/AmazTool/AmazTool.csproj b/v2rayn/v2rayN/AmazTool/AmazTool.csproj index 37193d628b..05874af37f 100644 --- a/v2rayn/v2rayN/AmazTool/AmazTool.csproj +++ b/v2rayn/v2rayN/AmazTool/AmazTool.csproj @@ -8,5 +8,10 @@ Copyright © 2017-2024 (GPLv3) 1.3.0 + + + + + \ No newline at end of file diff --git a/v2rayn/v2rayN/AmazTool/en-US.json b/v2rayn/v2rayN/AmazTool/Assets/en-US.json similarity index 100% rename from v2rayn/v2rayN/AmazTool/en-US.json rename to v2rayn/v2rayN/AmazTool/Assets/en-US.json diff --git a/v2rayn/v2rayN/AmazTool/zh-CN.json b/v2rayn/v2rayN/AmazTool/Assets/zh-CN.json similarity index 100% rename from v2rayn/v2rayN/AmazTool/zh-CN.json rename to v2rayn/v2rayN/AmazTool/Assets/zh-CN.json diff --git a/v2rayn/v2rayN/AmazTool/LocalizationHelper.cs b/v2rayn/v2rayN/AmazTool/LocalizationHelper.cs index 3804564ce5..4af352c6ed 100644 --- a/v2rayn/v2rayN/AmazTool/LocalizationHelper.cs +++ b/v2rayn/v2rayN/AmazTool/LocalizationHelper.cs @@ -1,11 +1,12 @@ -using System.Globalization; +using System.Globalization; +using System.Reflection; using System.Text.Json; namespace AmazTool { public class LocalizationHelper { - private static Dictionary languageResources = new(); + private static Dictionary _languageResources = []; static LocalizationHelper() { @@ -13,51 +14,46 @@ namespace AmazTool LoadLanguageResources(); } - /// - /// 加载外部 JSON 文件中的语言资源 - /// private static void LoadLanguageResources() { try { - string currentLanguage = CultureInfo.CurrentCulture.Name; + var currentLanguage = CultureInfo.CurrentCulture.Name; if (currentLanguage != "zh-CN" && currentLanguage != "en-US") { currentLanguage = "en-US"; } - string jsonFilePath = $"{currentLanguage}.json"; - if (!File.Exists(jsonFilePath)) - { - jsonFilePath = "en-US.json"; - } + var resourceName = $"AmazTool.Assets.{currentLanguage}.json"; + var assembly = Assembly.GetExecutingAssembly(); - var json = File.ReadAllText(jsonFilePath); + using var stream = assembly.GetManifestResourceStream(resourceName); + if (stream == null) return; + + using StreamReader reader = new(stream); + var json = reader.ReadToEnd(); if (!string.IsNullOrEmpty(json)) { - languageResources = JsonSerializer.Deserialize>(json) ?? new Dictionary(); + _languageResources = JsonSerializer.Deserialize>(json) ?? new Dictionary(); } } + catch (IOException ex) + { + Console.WriteLine($"Failed to read language resource file: {ex.Message}"); + } + catch (JsonException ex) + { + Console.WriteLine($"Failed to parse JSON data: {ex.Message}"); + } catch (Exception ex) { - Console.WriteLine($"Failed to load language resources: {ex.Message}"); - languageResources = []; // 初始化为空字典 + Console.WriteLine($"Unexpected error occurred: {ex.Message}"); } } - /// - /// 获取系统当前语言的本地化字符串 - /// - /// 要翻译的关键字 - /// 对应语言的本地化字符串,如果没有找到则返回关键字 public static string GetLocalizedValue(string key) { - if (languageResources != null && languageResources.TryGetValue(key, out var translation)) - { - return translation; - } - - return key; + return _languageResources.TryGetValue(key, out var translation) ? translation : key; } } } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs index e181eb30cc..57e94557a2 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs @@ -259,7 +259,7 @@ namespace ServiceLib.Handler return _config.TunModeItem.EnableTun && eCoreType == ECoreType.sing_box && Utils.IsLinux() - && _config.TunModeItem.LinuxSudoPwd.IsNotEmpty() + //&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty() ; } @@ -275,7 +275,6 @@ namespace ServiceLib.Handler return null; } - var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType); try { Process proc = new() @@ -294,14 +293,10 @@ namespace ServiceLib.Handler } }; + var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType); if (isNeedSudo) { - proc.StartInfo.FileName = $"/bin/sudo"; - proc.StartInfo.Arguments = $"-S {fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath).AppendQuotes())}"; - proc.StartInfo.WorkingDirectory = null; - proc.StartInfo.StandardInputEncoding = Encoding.UTF8; - proc.StartInfo.RedirectStandardInput = true; - Logging.SaveLog(proc.StartInfo.Arguments); + await RunProcessAsLinuxRoot(proc, fileName, coreInfo, configPath); } var startUpErrorMessage = new StringBuilder(); @@ -326,7 +321,7 @@ namespace ServiceLib.Handler } proc.Start(); - if (isNeedSudo) + if (isNeedSudo && _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()) { var pwd = DesUtils.Decrypt(_config.TunModeItem.LinuxSudoPwd); await Task.Delay(10); @@ -362,6 +357,37 @@ namespace ServiceLib.Handler } } + private async Task RunProcessAsLinuxRoot(Process proc, string fileName, CoreInfo coreInfo, string configPath) + { + var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath).AppendQuotes())}"; + + //Prefer shell scripts + var shFilePath = Utils.GetBinPath("run_as_root.sh"); + File.Delete(shFilePath); + var sb = new StringBuilder(); + sb.AppendLine("#!/bin/sh"); + sb.AppendLine(cmdLine); + await File.WriteAllTextAsync(shFilePath, sb.ToString()); + await Utils.SetLinuxChmod(shFilePath); + + //Replace command + var args = File.Exists(shFilePath) ? shFilePath : cmdLine; + if (_config.TunModeItem.LinuxSudoPwd.IsNotEmpty()) + { + proc.StartInfo.FileName = $"/bin/sudo"; + proc.StartInfo.Arguments = $"-S {args}"; + } + else + { + proc.StartInfo.FileName = $"/bin/pkexec"; + proc.StartInfo.Arguments = $"{args}"; + } + proc.StartInfo.WorkingDirectory = null; + proc.StartInfo.StandardInputEncoding = Encoding.UTF8; + proc.StartInfo.RedirectStandardInput = true; + Logging.SaveLog(proc.StartInfo.Arguments); + } + private async Task KillProcess(Process? proc) { if (proc is null) diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 9fd66a6e4f..c281a4adc2 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1370,7 +1370,7 @@ Linux系统的sudo密码 - 密码已加密且只存储在本地文件中,无密码无法开启Tun + 密码已加密且只存储在本地文件中,无密码则每次都要输入 请先在Tun模式设置中设置sudo密码 diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index 0243c1f326..2d18ce2ebd 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1370,7 +1370,7 @@ Linux系統的sudo密碼 - 密碼已加密且只儲存在本機檔案中,無密碼無法開啟Tun + 密碼已加密且只儲存在本機檔案中,無密碼則每次都要輸入 請先在Tun模式設定中設定sudo密碼 diff --git a/v2rayn/v2rayN/ServiceLib/ServiceLib.csproj b/v2rayn/v2rayN/ServiceLib/ServiceLib.csproj index d2f0c93992..52c068dfc0 100644 --- a/v2rayn/v2rayN/ServiceLib/ServiceLib.csproj +++ b/v2rayn/v2rayN/ServiceLib/ServiceLib.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 7.1.2 + 7.1.3 diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs index 3298f63639..89fbefc5d7 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs @@ -416,16 +416,16 @@ namespace ServiceLib.ViewModels // When running as a non-administrator, reboot to administrator mode if (EnableTun && AllowEnableTun() == false) { - _config.TunModeItem.EnableTun = false; if (Utils.IsWindows()) { + _config.TunModeItem.EnableTun = false; Locator.Current.GetService()?.RebootAsAdmin(); + return; } - else if (Utils.IsLinux()) - { - NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty); - } - return; + //else if (Utils.IsLinux()) + //{ + // NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty); + //} } await ConfigHandler.SaveConfig(_config); Locator.Current.GetService()?.Reload(); diff --git a/v2rayn/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs b/v2rayn/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs index a2bfa298f7..4508daa53a 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs +++ b/v2rayn/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs @@ -356,7 +356,7 @@ namespace v2rayN.Desktop.Views item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel); item2.DisplayIndex = displayIndex++; } - if (item.Name.StartsWith("to")) + if (item.Name.ToLower().StartsWith("to")) { if (!_config.GuiItem.EnableStatistics) { diff --git a/v2rayn/v2rayN/v2rayN/Views/ProfilesView.xaml.cs b/v2rayn/v2rayN/v2rayN/Views/ProfilesView.xaml.cs index 23459fc14c..e39c7dffc3 100644 --- a/v2rayn/v2rayN/v2rayN/Views/ProfilesView.xaml.cs +++ b/v2rayn/v2rayN/v2rayN/Views/ProfilesView.xaml.cs @@ -338,7 +338,7 @@ namespace v2rayN.Views item2.Width = item.Width; item2.DisplayIndex = displayIndex++; } - if (item.Name.StartsWith("to")) + if (item.Name.ToLower().StartsWith("to")) { if (!_config.GuiItem.EnableStatistics) { diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/AngApplication.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/AngApplication.kt index e198182281..0f144106e4 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/AngApplication.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/AngApplication.kt @@ -7,6 +7,7 @@ import androidx.multidex.MultiDexApplication import androidx.work.Configuration import androidx.work.WorkManager import com.tencent.mmkv.MMKV +import com.v2ray.ang.AppConfig.ANG_PACKAGE import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.util.Utils @@ -22,7 +23,7 @@ class AngApplication : MultiDexApplication() { } private val workManagerConfiguration: Configuration = Configuration.Builder() - .setDefaultProcessName("${BuildConfig.APPLICATION_ID}:bg") + .setDefaultProcessName("${ANG_PACKAGE}:bg") .build() override fun onCreate() { @@ -37,7 +38,7 @@ class AngApplication : MultiDexApplication() { MMKV.initialize(this) - Utils.setNightMode(application) + Utils.setNightMode() // Initialize WorkManager with the custom configuration WorkManager.initialize(this, workManagerConfiguration) diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/NetworkType.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/NetworkType.kt index 5e4b5dbef8..f598805aed 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/NetworkType.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/NetworkType.kt @@ -6,9 +6,10 @@ enum class NetworkType(val type: String) { WS("ws"), HTTP_UPGRADE("httpupgrade"), SPLIT_HTTP("splithttp"), + XHTTP("xhttp"), HTTP("http"), H2("h2"), - QUIC("quic"), + //QUIC("quic"), GRPC("grpc"); companion object { diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ProfileItem.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ProfileItem.kt index 4eaac0b5f1..0b7f3430c4 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ProfileItem.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ProfileItem.kt @@ -30,6 +30,7 @@ data class ProfileItem( var mode: String? = null, var serviceName: String? = null, var authority: String? = null, + var xhttpMode: String? = null, var security: String? = null, var sni: String? = null, @@ -87,6 +88,7 @@ data class ProfileItem( && this.mode == obj.mode && this.serviceName == obj.serviceName && this.authority == obj.authority + && this.xhttpMode == obj.xhttpMode && this.security == obj.security && this.sni == obj.sni diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt index 9ea7b5960b..31a505615b 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt @@ -206,7 +206,7 @@ data class V2rayConfig( var kcpSettings: KcpSettingsBean? = null, var wsSettings: WsSettingsBean? = null, var httpupgradeSettings: HttpupgradeSettingsBean? = null, - var splithttpSettings: SplithttpSettingsBean? = null, + var xhttpSettings: XhttpSettingsBean? = null, var httpSettings: HttpSettingsBean? = null, var tlsSettings: TlsSettingsBean? = null, var quicSettings: QuicSettingBean? = null, @@ -275,11 +275,10 @@ data class V2rayConfig( val acceptProxyProtocol: Boolean? = null ) - data class SplithttpSettingsBean( + data class XhttpSettingsBean( var path: String? = null, var host: String? = null, - val maxUploadSize: Int? = null, - val maxConcurrentUploads: Int? = null + var mode: String? = null, ) data class HttpSettingsBean( @@ -396,12 +395,12 @@ data class V2rayConfig( httpupgradeSettings = httpupgradeSetting } - "splithttp" -> { - val splithttpSetting = SplithttpSettingsBean() - splithttpSetting.host = host.orEmpty() - sni = splithttpSetting.host - splithttpSetting.path = path ?: "/" - splithttpSettings = splithttpSetting + "splithttp","xhttp" -> { + val xhttpSetting = XhttpSettingsBean() + xhttpSetting.host = host.orEmpty() + sni = xhttpSetting.host + xhttpSetting.path = path ?: "/" + xhttpSettings = xhttpSetting } "h2", "http" -> { @@ -413,13 +412,13 @@ data class V2rayConfig( httpSettings = h2Setting } - "quic" -> { - val quicsetting = QuicSettingBean() - quicsetting.security = quicSecurity ?: "none" - quicsetting.key = key.orEmpty() - quicsetting.header.type = headerType ?: "none" - quicSettings = quicsetting - } +// "quic" -> { +// val quicsetting = QuicSettingBean() +// quicsetting.security = quicSecurity ?: "none" +// quicsetting.key = key.orEmpty() +// quicsetting.header.type = headerType ?: "none" +// quicSettings = quicsetting +// } "grpc" -> { val grpcSetting = GrpcSettingsBean() @@ -581,12 +580,12 @@ data class V2rayConfig( ) } - "splithttp" -> { - val splithttpSetting = streamSettings?.splithttpSettings ?: return null + "splithttp" ,"xhttp"-> { + val xhttpSettings = streamSettings?.xhttpSettings ?: return null listOf( "", - splithttpSetting.host, - splithttpSetting.path + xhttpSettings.host, + xhttpSettings.path ) } @@ -599,14 +598,14 @@ data class V2rayConfig( ) } - "quic" -> { - val quicSetting = streamSettings?.quicSettings ?: return null - listOf( - quicSetting.header.type, - quicSetting.security, - quicSetting.key - ) - } +// "quic" -> { +// val quicSetting = streamSettings?.quicSettings ?: return null +// listOf( +// quicSetting.header.type, +// quicSetting.security, +// quicSetting.key +// ) +// } "grpc" -> { val grpcSetting = streamSettings?.grpcSettings ?: return null diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt index a73eb6157f..d4d76161ef 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt @@ -1,6 +1,5 @@ package com.v2ray.ang.fmt -import com.v2ray.ang.AppConfig import com.v2ray.ang.dto.NetworkType import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.extension.isNotNullEmpty @@ -55,22 +54,28 @@ open class FmtBase { config.seed.let { if (it.isNotNullEmpty()) dicQuery["seed"] = it.orEmpty() } } - NetworkType.WS, NetworkType.HTTP_UPGRADE, NetworkType.SPLIT_HTTP -> { + NetworkType.WS, NetworkType.HTTP_UPGRADE -> { config.host.let { if (it.isNotNullEmpty()) dicQuery["host"] = it.orEmpty() } config.path.let { if (it.isNotNullEmpty()) dicQuery["path"] = it.orEmpty() } } + NetworkType.SPLIT_HTTP, NetworkType.XHTTP -> { + config.host.let { if (it.isNotNullEmpty()) dicQuery["host"] = it.orEmpty() } + config.path.let { if (it.isNotNullEmpty()) dicQuery["path"] = it.orEmpty() } + config.xhttpMode.let { if (it.isNotNullEmpty()) dicQuery["mode"] = it.orEmpty() } + } + NetworkType.HTTP, NetworkType.H2 -> { dicQuery["type"] = "http" config.host.let { if (it.isNotNullEmpty()) dicQuery["host"] = it.orEmpty() } config.path.let { if (it.isNotNullEmpty()) dicQuery["path"] = it.orEmpty() } } - NetworkType.QUIC -> { - dicQuery["headerType"] = config.headerType?.ifEmpty { "none" }.orEmpty() - config.quicSecurity.let { if (it.isNotNullEmpty()) dicQuery["quicSecurity"] = it.orEmpty() } - config.quicKey.let { if (it.isNotNullEmpty()) dicQuery["key"] = it.orEmpty() } - } +// NetworkType.QUIC -> { +// dicQuery["headerType"] = config.headerType?.ifEmpty { "none" }.orEmpty() +// config.quicSecurity.let { if (it.isNotNullEmpty()) dicQuery["quicSecurity"] = it.orEmpty() } +// config.quicKey.let { if (it.isNotNullEmpty()) dicQuery["key"] = it.orEmpty() } +// } NetworkType.GRPC -> { config.mode.let { if (it.isNotNullEmpty()) dicQuery["mode"] = it.orEmpty() } diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt index 477c101dde..b828ffacf9 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt @@ -36,6 +36,7 @@ object VlessFmt : FmtBase() { config.mode = queryParam["mode"] config.serviceName = queryParam["serviceName"] config.authority = queryParam["authority"] + config.xhttpMode = queryParam["mode"] config.security = queryParam["security"] config.insecure = if (queryParam["allowInsecure"].isNullOrEmpty()) { @@ -85,6 +86,7 @@ object VlessFmt : FmtBase() { profileItem.serviceName, profileItem.authority, ) + outboundBean?.streamSettings?.xhttpSettings?.mode = profileItem.xhttpMode outboundBean?.streamSettings?.populateTlsSettings( profileItem.security.orEmpty(), diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt index a8fe469ea5..1fc7a66f97 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt @@ -58,10 +58,10 @@ object VmessFmt : FmtBase() { config.seed = vmessQRCode.path } - NetworkType.QUIC -> { - config.quicSecurity = vmessQRCode.host - config.quicKey = vmessQRCode.path - } +// NetworkType.QUIC -> { +// config.quicSecurity = vmessQRCode.host +// config.quicKey = vmessQRCode.path +// } NetworkType.GRPC -> { config.mode = vmessQRCode.type @@ -98,10 +98,10 @@ object VmessFmt : FmtBase() { vmessQRCode.path = config.seed.orEmpty() } - NetworkType.QUIC -> { - vmessQRCode.host = config.quicSecurity.orEmpty() - vmessQRCode.path = config.quicKey.orEmpty() - } +// NetworkType.QUIC -> { +// vmessQRCode.host = config.quicSecurity.orEmpty() +// vmessQRCode.path = config.quicKey.orEmpty() +// } NetworkType.GRPC -> { vmessQRCode.type = config.mode.orEmpty() diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt index 57f256488c..dad69f32e0 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt @@ -79,6 +79,10 @@ class ServerActivity : BaseActivity() { private val alpns: Array by lazy { resources.getStringArray(R.array.streamsecurity_alpn) } + private val xhttpMode: Array by lazy { + resources.getStringArray(R.array.xhttp_mode) + } + // Kotlin synthetics was used, but since it is removed in 1.8. We switch to old manual approach. // We don't use AndroidViewBinding because, it is better to share similar logics for different @@ -150,14 +154,18 @@ class ServerActivity : BaseActivity() { ArrayAdapter(this@ServerActivity, android.R.layout.simple_spinner_item, types) adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) sp_header_type?.adapter = adapter - sp_header_type_title?.text = if (networks[position] == "grpc") - getString(R.string.server_lab_mode_type) else - getString(R.string.server_lab_head_type) + sp_header_type_title?.text = + when (networks[position]) { + "grpc" -> getString(R.string.server_lab_mode_type) + "xhttp" -> getString(R.string.server_lab_xhttp_mode) + else -> getString(R.string.server_lab_head_type) + }.orEmpty() sp_header_type?.setSelection( Utils.arrayFind( types, when (networks[position]) { "grpc" -> config?.mode + "xhttp" -> config?.xhttpMode else -> config?.headerType }.orEmpty() ) @@ -165,7 +173,7 @@ class ServerActivity : BaseActivity() { et_request_host?.text = Utils.getEditable( when (networks[position]) { - "quic" -> config?.quicSecurity + //"quic" -> config?.quicSecurity "grpc" -> config?.authority else -> config?.host }.orEmpty() @@ -173,7 +181,7 @@ class ServerActivity : BaseActivity() { et_path?.text = Utils.getEditable( when (networks[position]) { "kcp" -> config?.seed - "quic" -> config?.quicKey + //"quic" -> config?.quicKey "grpc" -> config?.serviceName else -> config?.path }.orEmpty() @@ -185,9 +193,9 @@ class ServerActivity : BaseActivity() { "tcp" -> R.string.server_lab_request_host_http "ws" -> R.string.server_lab_request_host_ws "httpupgrade" -> R.string.server_lab_request_host_httpupgrade - "splithttp" -> R.string.server_lab_request_host_splithttp + "splithttp", "xhttp" -> R.string.server_lab_request_host_xhttp "h2" -> R.string.server_lab_request_host_h2 - "quic" -> R.string.server_lab_request_host_quic + //"quic" -> R.string.server_lab_request_host_quic "grpc" -> R.string.server_lab_request_host_grpc else -> R.string.server_lab_request_host } @@ -200,9 +208,9 @@ class ServerActivity : BaseActivity() { "kcp" -> R.string.server_lab_path_kcp "ws" -> R.string.server_lab_path_ws "httpupgrade" -> R.string.server_lab_path_httpupgrade - "splithttp" -> R.string.server_lab_path_splithttp + "splithttp", "xhttp" -> R.string.server_lab_path_xhttp "h2" -> R.string.server_lab_path_h2 - "quic" -> R.string.server_lab_path_quic + //"quic" -> R.string.server_lab_path_quic "grpc" -> R.string.server_lab_path_grpc else -> R.string.server_lab_path } @@ -509,6 +517,7 @@ class ServerActivity : BaseActivity() { profileItem.mode = transportTypes(networks[network])[type] profileItem.serviceName = path profileItem.authority = requestHost + profileItem.xhttpMode = transportTypes(networks[network])[type] } private fun saveTls(config: ProfileItem) { @@ -544,7 +553,7 @@ class ServerActivity : BaseActivity() { tcpTypes } - "kcp", "quic" -> { + "kcp" -> { kcpAndQuicTypes } @@ -552,6 +561,10 @@ class ServerActivity : BaseActivity() { grpcModes } + "xhttp" -> { + xhttpMode + } + else -> { arrayOf("---") } diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt index a919512166..58b6e05d19 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt @@ -396,7 +396,7 @@ object Utils { } - fun setNightMode(context: Context) { + fun setNightMode() { when (MmkvManager.decodeSettingsString(AppConfig.PREF_UI_MODE_NIGHT, "0")) { "0" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) "1" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt index 311c1a4a97..cc1cca4cf7 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt @@ -81,7 +81,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application // } } if (key == AppConfig.PREF_UI_MODE_NIGHT) { - Utils.setNightMode(getApplication()) + Utils.setNightMode() } } } diff --git a/v2rayng/V2rayNG/app/src/main/res/values-ar/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-ar/strings.xml index e4c3670e6c..41042e19ac 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-ar/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-ar/strings.xml @@ -56,14 +56,14 @@ http host ws host httpupgrade host - splithttp host + xhttp host h2 host QUIC security gRPC Authority path ws path httpupgrade path - splithttp path + xhttp path h2 path QUIC key kcp seed @@ -119,6 +119,7 @@ Port Hopping Port Hopping Interval pinSHA256 + XHTTP Mode جار التحميل diff --git a/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml index 890a8c69a5..0c09b1ccc6 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml @@ -55,14 +55,14 @@ http হোস্ট ws হোস্ট httpupgrade হোস্ট - splithttp হোস্ট + xhttp হোস্ট h2 হোস্ট QUIC নিরাপত্তা gRPC কর্তৃপক্ষ পথ ws পথ httpupgrade পথ - splithttp পথ + xhttp পথ h2 পথ QUIC কী kcp বীজ @@ -118,6 +118,7 @@ Port Hopping Port Hopping Interval pinSHA256 + XHTTP Mode লোড হচ্ছে diff --git a/v2rayng/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml index 358e591df1..8309964f15 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml @@ -55,14 +55,14 @@ هاست http هاست ws هاست httpupgrade - هاست splithttp + هاست xhttp هاست h2 ٱمنیت QUIC اختیار gRPC تور تور ws تور httpupgrade - تور splithttp + تور xhttp تور h2 کیلیت QUIC سید kcp @@ -117,6 +117,7 @@ پورت گوم (درگا سرورن ز نۊ هؽل اکونه) فاسله پورت گوم (سانیه) pinSHA256 + XHTTP Mode هون بارونی بۊ diff --git a/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml index 43763a30ff..db7a91f588 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml @@ -54,14 +54,14 @@ http host ws host httpupgrade host - splithttp host + xhttp host h2 host QUIC security gRPC Authority path ws path httpupgrade path - splithttp path + xhttp path h2 path QUIC key kcp seed @@ -112,6 +112,7 @@ پورت پرش (درگاه سرور را بازنویسی می کند) فاصله پورت پرش (ثانیه) pinSHA256 + XHTTP Mode URL را اضافه کنید diff --git a/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml index cf3e153e63..fd9c59cf9c 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml @@ -54,14 +54,14 @@ Узел HTTP Узел WS Узел HTTPUpgrade - Узел SplitHTTP + Узел SplitHTTP Узел H2 Шифрование QUIC Полномочия gRPC Путь Путь WS Путь HTTPUpgrade - Путь SplitHTTP + Путь SplitHTTP Путь H2 Ключ QUIC Сид KCP @@ -117,6 +117,7 @@ Переключение портов Интервал переключения портов pinSHA256 + XHTTP Mode Загрузка… diff --git a/v2rayng/V2rayNG/app/src/main/res/values-vi/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-vi/strings.xml index 73944fc55a..27c78d8a98 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-vi/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-vi/strings.xml @@ -54,14 +54,14 @@ http host ws host httpupgrade host - splithttp host + xhttp host h2 host QUIC security gRPC Authority path ws path httpupgrade path - splithttp path + xhttp path h2 path QUIC key kcp seed @@ -112,6 +112,7 @@ Port Hopping Port Hopping Interval pinSHA256 + XHTTP Mode Thêm URL nội dung diff --git a/v2rayng/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml index d4feabfe2f..dd82f33e9d 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml @@ -54,14 +54,14 @@ http host ws host httpupgrade host - splithttp host + xhttp host h2 host QUIC 加密方式 gRPC Authority path ws path httpupgrade path - splithttp path + xhttp path h2 path QUIC 加密密钥 kcp seed @@ -112,6 +112,7 @@ 跳跃端口(会覆盖服务器端口) 端口跳跃间隔(秒) SHA256证书指纹 + XHTTP 模式 添加资产网址 diff --git a/v2rayng/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml index 54bff2d29a..1e64aba0a5 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml @@ -54,14 +54,14 @@ http host ws host httpupgrade host - splithttp host + xhttp host h2 host QUIC 加密方式 gRPC Authority path ws path httpupgrade path - splithttp path + xhttp path h2 path QUIC 加密金鑰 kcp seed @@ -112,6 +112,7 @@ 跳躍連接埠(會覆蓋伺服器連接埠) 連接埠跳躍間隔(秒) SHA256憑證指紋 + XHTTP 模式 新增資產網址 diff --git a/v2rayng/V2rayNG/app/src/main/res/values/arrays.xml b/v2rayng/V2rayNG/app/src/main/res/values/arrays.xml index 76c8965826..dce02b9502 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values/arrays.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values/arrays.xml @@ -26,9 +26,9 @@ kcp ws httpupgrade + xhttp splithttp h2 - quic grpc @@ -205,4 +205,10 @@ direct block - + + + auto + packet-up + stream-up + + \ No newline at end of file diff --git a/v2rayng/V2rayNG/app/src/main/res/values/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values/strings.xml index 720c4c59ab..3ac2cb297d 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values/strings.xml @@ -55,14 +55,14 @@ http host ws host httpupgrade host - splithttp host + xhttp host h2 host QUIC security gRPC Authority path ws path httpupgrade path - splithttp path + xhttp path h2 path QUIC key kcp seed @@ -118,6 +118,7 @@ Port Hopping(will override the port) Port Hopping Interval pinSHA256 + XHTTP Mode Loading diff --git a/xray-core/go.mod b/xray-core/go.mod index c149b23f46..f81174d744 100644 --- a/xray-core/go.mod +++ b/xray-core/go.mod @@ -28,7 +28,7 @@ require ( golang.org/x/sys v0.27.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 google.golang.org/grpc v1.67.1 - google.golang.org/protobuf v1.35.1 + google.golang.org/protobuf v1.35.2 gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h12.io/socks v1.0.3 lukechampine.com/blake3 v1.3.0 diff --git a/xray-core/go.sum b/xray-core/go.sum index 75b45600e8..d94428a830 100644 --- a/xray-core/go.sum +++ b/xray-core/go.sum @@ -129,8 +129,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/xray-core/transport/internet/splithttp/splithttp_test.go b/xray-core/transport/internet/splithttp/splithttp_test.go index b01727e034..c349f8f5df 100644 --- a/xray-core/transport/internet/splithttp/splithttp_test.go +++ b/xray-core/transport/internet/splithttp/splithttp_test.go @@ -424,8 +424,8 @@ func Test_maxUpload(t *testing.T) { ProtocolSettings: &Config{ Path: "/sh", ScMaxEachPostBytes: &RandRangeConfig{ - From: 100, - To: 100, + From: 10000, + To: 10000, }, }, } @@ -434,7 +434,7 @@ func Test_maxUpload(t *testing.T) { listen, err := ListenSH(context.Background(), net.LocalHostIP, listenPort, streamSettings, func(conn stat.Connection) { go func(c stat.Connection) { defer c.Close() - var b [1024]byte + var b [10240]byte c.SetReadDeadline(time.Now().Add(2 * time.Second)) n, err := c.Read(b[:]) if err != nil { @@ -452,11 +452,11 @@ func Test_maxUpload(t *testing.T) { conn, err := Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), listenPort), streamSettings) // send a slightly too large upload - var upload [101]byte + var upload [10001]byte _, err = conn.Write(upload[:]) common.Must(err) - var b [1024]byte + var b [10240]byte n, _ := io.ReadFull(conn, b[:]) fmt.Println("string is", n) if string(b[:n]) != "Response" { @@ -464,7 +464,7 @@ func Test_maxUpload(t *testing.T) { } common.Must(conn.Close()) - if uploadSize > 100 || uploadSize == 0 { + if uploadSize > 10000 || uploadSize == 0 { t.Error("incorrect upload size: ", uploadSize) } diff --git a/yass/README.md b/yass/README.md index 3c71c7609b..b9575df2bc 100644 --- a/yass/README.md +++ b/yass/README.md @@ -13,7 +13,7 @@ yass is an efficient forward proxy client supporting http/socks4/socks4a/socks5/ Because we are reusing chromium's network stack directly, we are following [chromium's release schedule](https://chromiumdash.appspot.com/schedule) and delivering new versions based on its beta branch. -- [Latest M132's Release (1.16.x)](https://github.com/Chilledheart/yass/releases/tag/1.16.0) will become Stable Release since _Jan 14, 2025_ (Extended Support). +- [Latest M132's Release (1.16.x)](https://github.com/Chilledheart/yass/releases/tag/1.16.1) will become Stable Release since _Jan 14, 2025_ (Extended Support). - [Latest M131's Release (1.15.x)](https://github.com/Chilledheart/yass/releases/tag/1.15.3) has become Stable Release since _Nov 12, 2024_. - [Latest M130's Release (1.14.x)](https://github.com/Chilledheart/yass/releases/tag/1.14.5) has become Stable Release since _Oct 15, 2024_ (Extended Support). - [Latest M129's Release (1.13.x)](https://github.com/Chilledheart/yass/releases/tag/1.13.3) has become Stable Release since _Sep 17, 2024_. @@ -174,39 +174,39 @@ Start from wiki's [Guide](https://github.com/Chilledheart/yass/wiki/Debug-Guide) [mlkem]: https://datatracker.ietf.org/doc/draft-connolly-tls-mlkem-key-agreement/ [kyber]: https://datatracker.ietf.org/doc/draft-tls-westerbaan-xyber768d00/ -[gtk3_rpm_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-gtk3.el8.x86_64.1.16.0.rpm -[gtk3_deb_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-gtk3-ubuntu-16.04-xenial_amd64.1.16.0.deb -[qt5_rpm_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-qt5.el8.x86_64.1.16.0.rpm -[qt5_deb_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-qt5-ubuntu-16.04-xenial_amd64.1.16.0.deb -[gtk4_rpm_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-gtk4.lp155.x86_64.1.16.0.rpm -[gtk4_deb_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-gtk4-ubuntu-22.04-jammy_amd64.1.16.0.deb -[qt6_rpm_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-qt6.lp155.x86_64.1.16.0.rpm -[qt6_deb_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-qt6-ubuntu-22.04-jammy_amd64.1.16.0.deb +[gtk3_rpm_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-gtk3.el8.x86_64.1.16.1.rpm +[gtk3_deb_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-gtk3-ubuntu-16.04-xenial_amd64.1.16.1.deb +[qt5_rpm_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-qt5.el8.x86_64.1.16.1.rpm +[qt5_deb_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-qt5-ubuntu-16.04-xenial_amd64.1.16.1.deb +[gtk4_rpm_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-gtk4.lp155.x86_64.1.16.1.rpm +[gtk4_deb_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-gtk4-ubuntu-22.04-jammy_amd64.1.16.1.deb +[qt6_rpm_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-qt6.lp155.x86_64.1.16.1.rpm +[qt6_deb_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-qt6-ubuntu-22.04-jammy_amd64.1.16.1.deb -[qt6_flatpak_x86_64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-x86_64-1.16.0.flatpak +[qt6_flatpak_x86_64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-x86_64-1.16.1.flatpak -[cli_tgz_amd64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-release-amd64-1.16.0.tgz -[cli_tgz_i386_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-release-amd64-1.16.0.tgz -[cli_tgz_arm64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-release-arm64-1.16.0.tgz -[cli_tgz_loongarch64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-release-loongarch64-1.16.0.tgz -[cli_tgz_riscv64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-release-riscv64-1.16.0.tgz -[cli_tgz_riscv32_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-release-riscv32-1.16.0.tgz +[cli_tgz_amd64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-release-amd64-1.16.1.tgz +[cli_tgz_i386_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-release-amd64-1.16.1.tgz +[cli_tgz_arm64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-release-arm64-1.16.1.tgz +[cli_tgz_loongarch64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-release-loongarch64-1.16.1.tgz +[cli_tgz_riscv64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-release-riscv64-1.16.1.tgz +[cli_tgz_riscv32_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-release-riscv32-1.16.1.tgz -[cli_openwrt_amd64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-openwrt-release-x86_64-1.16.0.tgz -[cli_openwrt_i486_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-openwrt-release-i486-1.16.0.tgz -[cli_openwrt_aarch64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-openwrt-release-aarch64-1.16.0.tgz +[cli_openwrt_amd64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-openwrt-release-x86_64-1.16.1.tgz +[cli_openwrt_i486_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-openwrt-release-i486-1.16.1.tgz +[cli_openwrt_aarch64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-openwrt-release-aarch64-1.16.1.tgz -[cli_musl_amd64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-musl-release-amd64-1.16.0.tgz -[cli_musl_i386_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-musl-release-i386-1.16.0.tgz -[cli_musl_aarch64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-musl-release-aarch64-1.16.0.tgz -[cli_musl_armhf_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass_cli-linux-musl-release-armhf-1.16.0.tgz +[cli_musl_amd64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-musl-release-amd64-1.16.1.tgz +[cli_musl_i386_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-musl-release-i386-1.16.1.tgz +[cli_musl_aarch64_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-musl-release-aarch64-1.16.1.tgz +[cli_musl_armhf_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass_cli-linux-musl-release-armhf-1.16.1.tgz -[android_64_apk_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-android-release-arm64-1.16.0.apk -[android_32_apk_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-android-release-arm-1.16.0.apk +[android_64_apk_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-android-release-arm64-1.16.1.apk +[android_32_apk_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-android-release-arm-1.16.1.apk -[windows_64_installer_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-mingw-win7-release-x86_64-1.16.0-system-installer.exe -[windows_32_installer_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-mingw-winxp-release-i686-1.16.0-system-installer.exe +[windows_64_installer_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-mingw-win7-release-x86_64-1.16.1-system-installer.exe +[windows_32_installer_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-mingw-winxp-release-i686-1.16.1-system-installer.exe -[windows_arm64_installer_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-mingw-release-aarch64-1.16.0-system-installer.exe -[macos_intel_dmg_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-macos-release-x64-1.16.0.dmg -[macos_arm_dmg_url]: https://github.com/Chilledheart/yass/releases/download/1.16.0/yass-macos-release-arm64-1.16.0.dmg +[windows_arm64_installer_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-mingw-release-aarch64-1.16.1-system-installer.exe +[macos_intel_dmg_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-macos-release-x64-1.16.1.dmg +[macos_arm_dmg_url]: https://github.com/Chilledheart/yass/releases/download/1.16.1/yass-macos-release-arm64-1.16.1.dmg diff --git a/yass/debian/changelog b/yass/debian/changelog index bb840728db..31da192ecd 100644 --- a/yass/debian/changelog +++ b/yass/debian/changelog @@ -1,3 +1,15 @@ +yass (1.16.1-1) UNRELEASED; urgency=medium + + * tls: add adjust system trusted CA folder for linux. + * tls: --capath now accepts separated list of directories. + * cli: handle http/1.1 keepalive for different host properly. + * cli: increase nofile to 65536 (systemd). + * network: increase parallel_max to 65535. + * network: apply keep alive on connections between client and browsers. + * tls: use builtin ca store universally. + * tls: ship GTS Root R4 with supplementary ca. + + -- Chilledheart Mon, 18 Nov 2024 16:48:23 +0800 yass (1.16.0-1) UNRELEASED; urgency=medium * bump to chromium 132 dependents. diff --git a/yass/doc/yass_cli.1 b/yass/doc/yass_cli.1 index e512fa1668..edb64513e6 100644 --- a/yass/doc/yass_cli.1 +++ b/yass/doc/yass_cli.1 @@ -72,10 +72,10 @@ Enable padding support\. Load CA certs from the OS\. .TP \fB\-\-cacert\fR \fIfile\fR -Tells where to use the specified certificate \fIfile\fR to verify the peer\. +CA certificate \fIfile\fR to verify peer against\. .TP \fB\-\-capath\fR \fIdir\fR -Tells where to use the specified certificate \fIdir\fR to verify the peer\. +CA directory \fIdir\fR to verify peer against\. It is a colon separated list of directories\. .TP \fB\-\-certificate_chain_file\fR \fIfile\fR Use custom certificate chain provided by \fIfile\fR to verify server's certificate (optional by https and http2)\. @@ -101,8 +101,11 @@ Specify \fIalgo\fR as TCP congestion control algorithm for underlying TCP connec See \fB/proc/sys/net/ipv4/tcp_allowed_congestion_control\fR for available options and \fBtcp\fR(7)\. .SH "ENVIRONMENT VARIABLES" .TP -\fBYASS_CA_BUNDLE\fR -Use as the path of ca\-bundle\.crt file\. Same effect with \fB\-\-cacert\fR \fIfile\fR\. +\fBSSL_CERT_FILE\fR +Use as the path of CA certificate to verify peer against\. Same effect with \fB\-\-cacert\fR \fIfile\fR\. +.TP +\fBSSL_CERT_DIR\fR +Use as the path of CA directory to verify peer against\. Same effect with \fB\-\-capath\fR \fIdir\fR\. It is a colon separated list of directories\. .SH "COPYRIGHT" Copyright (C) 2019\-2024 Chilledheart\. All rights reserved\. .SH "SEE ALSO" diff --git a/yass/doc/yass_cli.md b/yass/doc/yass_cli.md index c2b54977b3..99ef917385 100644 --- a/yass/doc/yass_cli.md +++ b/yass/doc/yass_cli.md @@ -86,10 +86,10 @@ See . Load CA certs from the OS. * `--cacert` _file_: - Tells where to use the specified certificate _file_ to verify the peer. + CA certificate _file_ to verify peer against. * `--capath` _dir_: - Tells where to use the specified certificate _dir_ to verify the peer. + CA directory _dir_ to verify peer against. It is a colon separated list of directories. * `--certificate_chain_file` _file_: Use custom certificate chain provided by _file_ to verify server's certificate (optional by https and http2). @@ -116,8 +116,11 @@ See . ## ENVIRONMENT VARIABLES -* `YASS_CA_BUNDLE`: - Use as the path of ca-bundle.crt file. Same effect with `--cacert` _file_. +* `SSL_CERT_FILE`: + Use as the path of CA certificate to verify peer against. Same effect with `--cacert` _file_. + +* `SSL_CERT_DIR`: + Use as the path of CA directory to verify peer against. Same effect with `--capath` _dir_. It is a colon separated list of directories. ## COPYRIGHT diff --git a/yass/doc/yass_server.1 b/yass/doc/yass_server.1 index 0cc0b17c71..6d0486d06d 100644 --- a/yass/doc/yass_server.1 +++ b/yass/doc/yass_server.1 @@ -72,10 +72,10 @@ Enable padding support\. Load CA certs from the OS\. .TP \fB\-\-cacert\fR \fIfile\fR -Tells where to use the specified certificate \fIfile\fR to verify the peer\. +CA certificate \fIfile\fR to verify peer against\. .TP \fB\-\-capath\fR \fIdir\fR -Tells where to use the specified certificate \fIdir\fR to verify the peer\. +CA directory \fIdir\fR to verify peer against\. It is a colon separated list of directories\. .TP \fB\-\-certificate_chain_file\fR \fIfile\fR Use custom certificate chain provided by \fIfile\fR to verify server's private key (required by https and http2)\. @@ -110,8 +110,11 @@ Specify \fIalgo\fR as TCP congestion control algorithm for underlying TCP connec See \fB/proc/sys/net/ipv4/tcp_allowed_congestion_control\fR for available options and \fBtcp\fR(7)\. .SH "ENVIRONMENT VARIABLES" .TP -\fBYASS_CA_BUNDLE\fR -Use as the path of ca\-bundle\.crt file\. Same effect with \fB\-\-cacert\fR \fIfile\fR\. +\fBSSL_CERT_FILE\fR +Use as the path of CA certificate to verify peer against\. Same effect with \fB\-\-cacert\fR \fIfile\fR\. +.TP +\fBSSL_CERT_DIR\fR +Use as the path of CA directory to verify peer against\. Same effect with \fB\-\-capath\fR \fIdir\fR\. It is a colon separated list of directories\. .SH "COPYRIGHT" Copyright (C) 2019\-2024 Chilledheart\. All rights reserved\. .SH "SEE ALSO" diff --git a/yass/doc/yass_server.md b/yass/doc/yass_server.md index 57b898d37b..9c8d265e85 100644 --- a/yass/doc/yass_server.md +++ b/yass/doc/yass_server.md @@ -85,10 +85,10 @@ See . Load CA certs from the OS. * `--cacert` _file_: - Tells where to use the specified certificate _file_ to verify the peer. + CA certificate _file_ to verify peer against. * `--capath` _dir_: - Tells where to use the specified certificate _dir_ to verify the peer. + CA directory _dir_ to verify peer against. It is a colon separated list of directories. * `--certificate_chain_file` _file_: Use custom certificate chain provided by _file_ to verify server's private key (required by https and http2). @@ -124,8 +124,11 @@ See . ## ENVIRONMENT VARIABLES -* `YASS_CA_BUNDLE`: - Use as the path of ca-bundle.crt file. Same effect with `--cacert` _file_. +* `SSL_CERT_FILE`: + Use as the path of CA certificate to verify peer against. Same effect with `--cacert` _file_. + +* `SSL_CERT_DIR`: + Use as the path of CA directory to verify peer against. Same effect with `--capath` _dir_. It is a colon separated list of directories. ## COPYRIGHT diff --git a/yass/src/cli/cli_connection.cpp b/yass/src/cli/cli_connection.cpp index ef0307a4ff..6a6f1a6996 100644 --- a/yass/src/cli/cli_connection.cpp +++ b/yass/src/cli/cli_connection.cpp @@ -1724,12 +1724,9 @@ std::shared_ptr CliConnection::GetNextUpstreamBuf(asio::error_code& ec, if (http_is_keep_alive_) { if (http_keep_alive_remaining_bytes_ < (int64_t)read) { - LOG(INFO) << "Connection (client) " << connection_id() << " re-used"; - upstream_readable_ = false; - upstream_writable_ = false; - ss_request_.reset(); - channel_->close(); - channel_.reset(); + DCHECK_EQ(ss::domain, ss_request_->address_type()); + DCHECK_EQ(http_host_, ss_request_->domain_name()); + DCHECK_EQ(http_port_, ss_request_->port()); ec = OnReadHttpRequest(buf); if (ec) { return nullptr; @@ -1738,17 +1735,37 @@ std::shared_ptr CliConnection::GetNextUpstreamBuf(asio::error_code& ec, ec = asio::error::invalid_argument; return nullptr; } - if (!buf->empty()) { - OnStreamRead(buf); + if (buf->empty()) { + buf.reset(); } - buf = nullptr; - ec = PerformCmdOpsHttp(); - if (ec) { + // ss_request_ isn't updated after OnReadHttpRequest(), + // so we are safe to use it to tell whether the new destination is different + if (ss_request_->domain_name() != http_host_ || ss_request_->port() != http_port_) { + LOG(INFO) << "Connection (client) " << connection_id() << " re-used"; + upstream_readable_ = false; + upstream_writable_ = false; + ss_request_.reset(); + channel_->close(); + channel_.reset(); + if (buf) { + OnStreamRead(buf); + buf.reset(); + } + ec = PerformCmdOpsHttp(); + if (ec) { + return nullptr; + } + SetState(state_stream); + DCHECK(!buf); + ec = asio::error::try_again; return nullptr; } + LOG(INFO) << "Connection (client) " << connection_id() << " connect (re-used) " << remote_domain(); SetState(state_stream); - ec = asio::error::try_again; - return nullptr; + if (!buf) { + ec = asio::error::try_again; + return nullptr; + } } else { http_keep_alive_remaining_bytes_ -= read; } diff --git a/yass/src/config/config.cpp b/yass/src/config/config.cpp index a0851e0aee..7a3feac9bf 100644 --- a/yass/src/config/config.cpp +++ b/yass/src/config/config.cpp @@ -465,8 +465,8 @@ void SetClientUsageMessage(std::string_view exec_path) { --limit_rate Limits the rate of response transmission to a client. Uint can be (none), k, m. --padding_support Enable padding support --ca_native Load CA certs from the OS - --cacert Tells where to use the specified certificate file to verify the peer - --capath Tells where to use the specified certificate dir to verify the peer + --cacert CA certificate to verify peer against + --capath CA directory to verify peer against --certificate_chain_file Use custom certificate chain file to verify server's certificate -k, --insecure_mode Skip the verification step and proceed without checking --tls13_early_data Enable 0RTTI Early Data @@ -488,8 +488,8 @@ void SetServerUsageMessage(std::string_view exec_path) { --limit_rate Limits the rate of response transmission to a client. Uint can be (none), k, m. --padding_support Enable padding support --ca_native Load CA certs from the OS - --cacert Tells where to use the specified certificate file to verify the peer - --capath Tells where to use the specified certificate dir to verify the peer + --cacert CA certificate to verify peer against + --capath CA directory to verify peer against --certificate_chain_file Use custom certificate chain file to verify server's certificate --private_key_file Use custom private key file to secure connection between server and client --private_key_password Use custom private key password to decrypt server's encrypted private key diff --git a/yass/src/config/config_tls.cpp b/yass/src/config/config_tls.cpp index becfa6ef36..f5705edc01 100644 --- a/yass/src/config/config_tls.cpp +++ b/yass/src/config/config_tls.cpp @@ -25,10 +25,20 @@ ABSL_FLAG(bool, "Or '-k', This option makes to skip the verification step and proceed without checking (Client Only)"); ABSL_FLAG(std::string, cacert, - getenv("YASS_CA_BUNDLE") ? getenv("YASS_CA_BUNDLE") : "", - "Tells where to use the specified certificate file to verify the peer. " - "You can override it with YASS_CA_BUNDLE environment variable"); -ABSL_FLAG(std::string, capath, "", "Tells where to use the specified certificate directory to verify the peer"); + getenv("SSL_CERT_FILE") ? getenv("SSL_CERT_FILE") : "", + "CA certificate to verify peer against. " + "You can override it with SSL_CERT_FILE environment variable."); +ABSL_FLAG(std::string, + capath, + getenv("SSL_CERT_DIR") ? getenv("SSL_CERT_DIR") : "", + "CA directory to verify peer against. " + "You can override it with SSL_CERT_DIR environment variable. " +#ifdef _WIN32 + "It is a semicolon separated list of directories." +#else + "It is a colon separated list of directories." +#endif +); ABSL_FLAG(bool, tls13_early_data, true, "Enable 0RTTI Early Data (risk at production)"); diff --git a/yass/src/net/asio_ssl.cpp b/yass/src/net/asio_ssl.cpp index 135bcecfc5..c4b8149705 100644 --- a/yass/src/net/asio_ssl.cpp +++ b/yass/src/net/asio_ssl.cpp @@ -34,6 +34,12 @@ #include "third_party/boringssl/src/pki/trust_store.h" #endif +#if defined(_WIN32) +#define DIR_HASH_SEPARATOR ';' +#else +#define DIR_HASH_SEPARATOR ':' +#endif + ABSL_FLAG(bool, ca_native, false, "Load CA certs from the OS."); std::ostream& operator<<(std::ostream& o, asio::error_code ec) { @@ -406,21 +412,21 @@ static int load_ca_to_ssl_ctx_path(SSL_CTX* ssl_ctx, const std::string& dir_path return count; } -static std::optional load_ca_to_ssl_ctx_yass_ca_bundle(SSL_CTX* ssl_ctx) { +static bool load_ca_to_ssl_ctx_yass_ca_bundle(SSL_CTX* ssl_ctx) { #ifdef _WIN32 #define CA_BUNDLE L"yass-ca-bundle.crt" // The windows version will automatically look for a CA certs file named 'ca-bundle.crt', // either in the same directory as yass.exe, or in the Current Working Directory, // or in any folder along your PATH. - std::vector ca_bundles; + std::vector wca_bundles; // 1. search under executable directory std::wstring exe_path; CHECK(GetExecutablePath(&exe_path)); std::filesystem::path exe_dir = std::filesystem::path(exe_path).parent_path(); - ca_bundles.push_back(exe_dir / CA_BUNDLE); + wca_bundles.push_back(exe_dir / CA_BUNDLE); // 2. search under current directory std::wstring current_dir; @@ -435,7 +441,7 @@ static std::optional load_ca_to_ssl_ctx_yass_ca_bundle(SSL_CTX* ssl_ctx) { current_dir = std::wstring(buf, ret); } - ca_bundles.push_back(std::filesystem::path(current_dir) / CA_BUNDLE); + wca_bundles.push_back(std::filesystem::path(current_dir) / CA_BUNDLE); // 3. search under path directory std::string path; @@ -449,58 +455,66 @@ static std::optional load_ca_to_ssl_ctx_yass_ca_bundle(SSL_CTX* ssl_ctx) { // to by lpBuffer, not including the terminating null character. path = SysWideToUTF8(std::wstring(buf, ret)); } - std::vector paths = absl::StrSplit(path, ';'); + std::vector paths = absl::StrSplit(path, DIR_HASH_SEPARATOR); for (const auto& path : paths) { if (path.empty()) continue; - ca_bundles.push_back(std::filesystem::path(path) / CA_BUNDLE); + wca_bundles.push_back(std::filesystem::path(path) / CA_BUNDLE); } - for (const auto& wca_bundle : ca_bundles) { + for (const auto& wca_bundle : wca_bundles) { auto ca_bundle = SysWideToUTF8(wca_bundle); VLOG(1) << "Attempt to load ca bundle from: " << ca_bundle; int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); if (result > 0) { LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; - return result; + return true; } } #undef CA_BUNDLE #endif - return std::nullopt; + return false; } -static std::optional load_ca_to_ssl_ctx_cacert(SSL_CTX* ssl_ctx) { +static bool load_ca_to_ssl_ctx_cacert(SSL_CTX* ssl_ctx) { + bool loaded = false; + int count = 0; if (absl::GetFlag(FLAGS_ca_native)) { + loaded = true; int result = load_ca_to_ssl_ctx_system(ssl_ctx); if (!result) { LOG(WARNING) << "Loading ca bundle failure from system"; } - return result; + count += result; } std::string ca_bundle = absl::GetFlag(FLAGS_cacert); if (!ca_bundle.empty()) { + loaded = true; int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); if (result) { LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; + count += result; } else { print_openssl_error(); LOG(WARNING) << "Loading ca bundle failure from: " << ca_bundle; } - return result; } std::string ca_path = absl::GetFlag(FLAGS_capath); if (!ca_path.empty()) { - int result = load_ca_to_ssl_ctx_path(ssl_ctx, ca_path); - if (result) { - LOG(INFO) << "Loaded ca from directory: " << ca_path << " with " << result << " certificates"; - } else { - LOG(WARNING) << "Loading ca directory failure from: " << ca_path; + loaded = true; + std::vector paths = absl::StrSplit(ca_path, DIR_HASH_SEPARATOR); + for (const auto& path : paths) { + int result = load_ca_to_ssl_ctx_path(ssl_ctx, path); + if (result) { + LOG(INFO) << "Loaded ca from directory: " << path << " with " << result << " certificates"; + count += result; + } else { + LOG(WARNING) << "Loading ca directory failure from: " << path; + } } - return result; } - return load_ca_to_ssl_ctx_yass_ca_bundle(ssl_ctx); + return loaded; } #ifdef _WIN32 @@ -757,14 +771,25 @@ out: int count = 0; // cert list copied from golang src/crypto/x509/root_unix.go static const char* ca_bundle_paths[] = { - "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. - "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL - "/etc/ssl/ca-bundle.pem", // OpenSUSE - "/etc/openssl/certs/ca-certificates.crt", // NetBSD - "/etc/ssl/cert.pem", // OpenBSD - "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly - "/etc/pki/tls/cacert.pem", // OpenELEC - "/etc/certs/ca-certificates.crt", // Solaris 11.2+ +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) + "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7 + "/etc/ssl/cert.pem", // Alpine Linux +#endif +#if BUILDFLAG(IS_BSD) + "/usr/local/etc/ssl/cert.pem", // FreeBSD + "/etc/ssl/cert.pem", // OpenBSD + "/usr/local/share/certs/ca-root-nss.crt", // DragonFly + "/etc/openssl/certs/ca-certificates.crt", // NetBSD +#endif +#if BUILDFLAG(IS_SOLARIS) + "/etc/certs/ca-certificates.crt", // Solaris 11.2+ + "/etc/ssl/certs/ca-certificates.crt", // Joyent SmartOS + "/etc/ssl/cacert.pem", // OmniOS +#endif }; for (auto ca_bundle : ca_bundle_paths) { int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); @@ -774,9 +799,22 @@ out: } } static const char* ca_paths[] = { - "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 - "/etc/pki/tls/certs", // Fedora/RHEL - "/system/etc/security/cacerts", // Android +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) + "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 + "/etc/pki/tls/certs", // Fedora/RHEL +#endif +#if BUILDFLAG(IS_ANDROID) + "/system/etc/security/cacerts", // Android system roots + "/data/misc/keychain/certs-added", // User trusted CA folder +#endif +#if BUILDFLAG(IS_BSD) + "/etc/ssl/certs", // FreeBSD 12.2+ + "/usr/local/share/certs", // FreeBSD + "/etc/openssl/certs", // NetBSD +#endif +#if BUILDFLAG(IS_SOLARIS) + "/etc/certs/CA", // Solaris +#endif }; for (auto ca_path : ca_paths) { @@ -857,14 +895,25 @@ out: int count = 0; // cert list copied from golang src/crypto/x509/root_unix.go static const char* ca_bundle_paths[] = { - "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. - "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL - "/etc/ssl/ca-bundle.pem", // OpenSUSE - "/etc/openssl/certs/ca-certificates.crt", // NetBSD - "/etc/ssl/cert.pem", // OpenBSD - "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly - "/etc/pki/tls/cacert.pem", // OpenELEC - "/etc/certs/ca-certificates.crt", // Solaris 11.2+ +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) + "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7 + "/etc/ssl/cert.pem", // Alpine Linux +#endif +#if BUILDFLAG(IS_BSD) + "/usr/local/etc/ssl/cert.pem", // FreeBSD + "/etc/ssl/cert.pem", // OpenBSD + "/usr/local/share/certs/ca-root-nss.crt", // DragonFly + "/etc/openssl/certs/ca-certificates.crt", // NetBSD +#endif +#if BUILDFLAG(IS_SOLARIS) + "/etc/certs/ca-certificates.crt", // Solaris 11.2+ + "/etc/ssl/certs/ca-certificates.crt", // Joyent SmartOS + "/etc/ssl/cacert.pem", // OmniOS +#endif }; for (auto ca_bundle : ca_bundle_paths) { int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); @@ -874,9 +923,22 @@ out: } } static const char* ca_paths[] = { - "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 - "/etc/pki/tls/certs", // Fedora/RHEL - "/system/etc/security/cacerts", // Android +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) + "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 + "/etc/pki/tls/certs", // Fedora/RHEL +#endif +#if BUILDFLAG(IS_ANDROID) + "/system/etc/security/cacerts", // Android system roots + "/data/misc/keychain/certs-added", // User trusted CA folder +#endif +#if BUILDFLAG(IS_BSD) + "/etc/ssl/certs", // FreeBSD 12.2+ + "/usr/local/share/certs", // FreeBSD + "/etc/openssl/certs", // NetBSD +#endif +#if BUILDFLAG(IS_SOLARIS) + "/etc/certs/CA", // Solaris +#endif }; for (auto ca_path : ca_paths) { @@ -891,18 +953,21 @@ out: } // loading ca certificates: -// 1. load --capath and --cacert certificates -// 2. load ca bundle from in sequence -// - builtin ca bundle if specified -// - yass-ca-bundle.crt if present (windows) -// - system ca certificates -// 3. force fallback to builtin ca bundle if step 2 failes +// 1. load --ca_native, --capath and --cacert certificates in sequence if specified +// 2. if step 1 succeeds, then goto step x. +// 3. load yass-ca-bundle.crt in path if present (windows-only) +// 4. if step 3 succeeds, then goto step x. +// 5. load ca bundle from in sequence +// - load user-added ca certificates on system +// - load builtin ca bundle +// - goto step x. +// x. load supplementary ca bundle if necessary void load_ca_to_ssl_ctx(SSL_CTX* ssl_ctx) { found_isrg_root_x1 = false; found_isrg_root_x2 = false; found_digicert_root_g2 = false; found_gts_root_r4 = false; - if (load_ca_to_ssl_ctx_cacert(ssl_ctx).has_value()) { + if (load_ca_to_ssl_ctx_cacert(ssl_ctx) || load_ca_to_ssl_ctx_yass_ca_bundle(ssl_ctx)) { goto done; } diff --git a/yass/src/win32/yass_cabundle.rc.in b/yass/src/win32/yass_cabundle.rc.in deleted file mode 100644 index 1a37b63a86..0000000000 --- a/yass/src/win32/yass_cabundle.rc.in +++ /dev/null @@ -1,3 +0,0 @@ -#include "resource.hpp" - -IDR_CA_BUNDLE RCDATA "@YASS_CA_BUNDLE_PATH@" diff --git a/yass/tools/build.go b/yass/tools/build.go index 210d39b8f5..e023a5f3a9 100644 --- a/yass/tools/build.go +++ b/yass/tools/build.go @@ -1155,7 +1155,7 @@ func buildStageExecuteBuildScript() { if systemNameFlag == "ios" && subSystemNameFlag == "simulator" { xcodeCmd := []string{"xcodebuild", "test", "-configuration", cmakeBuildTypeFlag, "-jobs", fmt.Sprintf("%d", cmakeBuildConcurrencyFlag), - "-scheme", "yass", "-destination", "platform=iOS Simulator,name=iPhone 16 Pro"} + "-scheme", "yass", "-destination", "platform=iOS Simulator,name=iPhone 16"} if !runTestFlag { cmdRun(xcodeCmd, true) } @@ -1187,7 +1187,7 @@ func buildStageExecuteBuildScript() { if systemNameFlag == "ios" && subSystemNameFlag == "simulator" { xcodeCmd := []string{"xcodebuild", "test", "-configuration", cmakeBuildTypeFlag, "-jobs", fmt.Sprintf("%d", cmakeBuildConcurrencyFlag), - "-scheme", "yass", "-destination", "platform=iOS Simulator,name=iPhone 16 Pro"} + "-scheme", "yass", "-destination", "platform=iOS Simulator,name=iPhone 16"} cmdRun(xcodeCmd, true) } else if systemNameFlag == "ios" { xcodeCmd := []string{"xcodebuild", "test", "-configuration", cmakeBuildTypeFlag, diff --git a/yass/yass.spec.in b/yass/yass.spec.in index 0cc7f8fa72..f6af8d3a43 100644 --- a/yass/yass.spec.in +++ b/yass/yass.spec.in @@ -318,6 +318,15 @@ for embedded devices and low end boxes. %systemd_postun_with_restart yass-redir.service %changelog +* Mon Nov 18 2024 Chilledheart - 1.16.1-1 + - tls: add adjust system trusted CA folder for linux + - tls: --capath now accepts separated list of directories + - cli: handle http/1.1 keepalive for different host properly + - cli: increase nofile to 65536 (systemd) + - network: increase parallel_max to 65535 + - network: apply keep alive on connections between client and browsers + - tls: use builtin ca store universally + - tls: ship GTS Root R4 with supplementary ca * Tue Nov 12 2024 Chilledheart - 1.16.0-1 - bump to chromium 132 dependents - build: add an option to enable/disable assertions diff --git a/yt-dlp/CONTRIBUTORS b/yt-dlp/CONTRIBUTORS index a9a0557426..9b8207b28b 100644 --- a/yt-dlp/CONTRIBUTORS +++ b/yt-dlp/CONTRIBUTORS @@ -695,3 +695,15 @@ KBelmin kesor MellowKyler Wesley107772 +a13ssandr0 +ChocoLZS +doe1080 +hugovdev +jshumphrey +julionc +manavchaudhary1 +powergold1 +Sakura286 +SamDecrock +stratus-ss +subrat-lima diff --git a/yt-dlp/Changelog.md b/yt-dlp/Changelog.md index 2648b9fe22..41a2da744d 100644 --- a/yt-dlp/Changelog.md +++ b/yt-dlp/Changelog.md @@ -4,6 +4,64 @@ # To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master --> +### 2024.11.18 + +#### Important changes +- **Login with OAuth is no longer supported for YouTube** +Due to a change made by the site, yt-dlp is longer able to support OAuth login for YouTube. [Read more](https://github.com/yt-dlp/yt-dlp/issues/11462#issuecomment-2471703090) + +#### Core changes +- [Catch broken Cryptodome installations](https://github.com/yt-dlp/yt-dlp/commit/b83ca24eb72e1e558b0185bd73975586c0bc0546) ([#11486](https://github.com/yt-dlp/yt-dlp/issues/11486)) by [seproDev](https://github.com/seproDev) +- **utils** + - [Fix `join_nonempty`, add `**kwargs` to `unpack`](https://github.com/yt-dlp/yt-dlp/commit/39d79c9b9cf23411d935910685c40aa1a2fdb409) ([#11559](https://github.com/yt-dlp/yt-dlp/issues/11559)) by [Grub4K](https://github.com/Grub4K) + - `subs_list_to_dict`: [Add `lang` default parameter](https://github.com/yt-dlp/yt-dlp/commit/c014fbcddcb4c8f79d914ac5bb526758b540ea33) ([#11508](https://github.com/yt-dlp/yt-dlp/issues/11508)) by [Grub4K](https://github.com/Grub4K) + +#### Extractor changes +- [Allow `ext` override for thumbnails](https://github.com/yt-dlp/yt-dlp/commit/eb64ae7d5def6df2aba74fb703e7f168fb299865) ([#11545](https://github.com/yt-dlp/yt-dlp/issues/11545)) by [bashonly](https://github.com/bashonly) +- **adobepass**: [Fix provider requests](https://github.com/yt-dlp/yt-dlp/commit/85fdc66b6e01d19a94b4f39b58e3c0cf23600902) ([#11472](https://github.com/yt-dlp/yt-dlp/issues/11472)) by [bashonly](https://github.com/bashonly) +- **archive.org**: [Fix comments extraction](https://github.com/yt-dlp/yt-dlp/commit/f2a4983df7a64c4e93b56f79dbd16a781bd90206) ([#11527](https://github.com/yt-dlp/yt-dlp/issues/11527)) by [jshumphrey](https://github.com/jshumphrey) +- **bandlab**: [Add extractors](https://github.com/yt-dlp/yt-dlp/commit/6365e92589e4bc17b8fffb0125a716d144ad2137) ([#11535](https://github.com/yt-dlp/yt-dlp/issues/11535)) by [seproDev](https://github.com/seproDev) +- **chaturbate** + - [Extract from API and support impersonation](https://github.com/yt-dlp/yt-dlp/commit/720b3dc453c342bc2e8df7dbc0acaab4479de46c) ([#11555](https://github.com/yt-dlp/yt-dlp/issues/11555)) by [powergold1](https://github.com/powergold1) (With fixes in [7cecd29](https://github.com/yt-dlp/yt-dlp/commit/7cecd299e4a5ef1f0f044b2fedc26f17e41f15e3) by [seproDev](https://github.com/seproDev)) + - [Support alternate domains](https://github.com/yt-dlp/yt-dlp/commit/a9f85670d03ab993dc589f21a9ffffcad61392d5) ([#10595](https://github.com/yt-dlp/yt-dlp/issues/10595)) by [manavchaudhary1](https://github.com/manavchaudhary1) +- **cloudflarestream**: [Avoid extraction via videodelivery.net](https://github.com/yt-dlp/yt-dlp/commit/2db8c2e7d57a1784b06057c48e3e91023720d195) ([#11478](https://github.com/yt-dlp/yt-dlp/issues/11478)) by [hugovdev](https://github.com/hugovdev) +- **ctvnews** + - [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/f351440f1dc5b3dfbfc5737b037a869d946056fe) ([#11534](https://github.com/yt-dlp/yt-dlp/issues/11534)) by [bashonly](https://github.com/bashonly), [jshumphrey](https://github.com/jshumphrey) + - [Fix playlist ID extraction](https://github.com/yt-dlp/yt-dlp/commit/f9d98509a898737c12977b2e2117277bada2c196) ([#8892](https://github.com/yt-dlp/yt-dlp/issues/8892)) by [qbnu](https://github.com/qbnu) +- **digitalconcerthall**: [Support login with access/refresh tokens](https://github.com/yt-dlp/yt-dlp/commit/f7257588bdff5f0b0452635a66b253a783c97357) ([#11571](https://github.com/yt-dlp/yt-dlp/issues/11571)) by [bashonly](https://github.com/bashonly) +- **facebook**: [Fix formats extraction](https://github.com/yt-dlp/yt-dlp/commit/bacc31b05a04181b63100c481565256b14813a5e) ([#11513](https://github.com/yt-dlp/yt-dlp/issues/11513)) by [bashonly](https://github.com/bashonly) +- **gamedevtv**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8) ([#11368](https://github.com/yt-dlp/yt-dlp/issues/11368)) by [bashonly](https://github.com/bashonly), [stratus-ss](https://github.com/stratus-ss) +- **goplay**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/6b43a8d84b881d769b480ba6e20ec691e9d1b92d) ([#11466](https://github.com/yt-dlp/yt-dlp/issues/11466)) by [bashonly](https://github.com/bashonly), [SamDecrock](https://github.com/SamDecrock) +- **kenh14**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/eb15fd5a32d8b35ef515f7a3d1158c03025648ff) ([#3996](https://github.com/yt-dlp/yt-dlp/issues/3996)) by [krichbanana](https://github.com/krichbanana), [pzhlkj6612](https://github.com/pzhlkj6612) +- **litv**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/e079ffbda66de150c0a9ebef05e89f61bb4d5f76) ([#11071](https://github.com/yt-dlp/yt-dlp/issues/11071)) by [jiru](https://github.com/jiru) +- **mixchmovie**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/0ec9bfed4d4a52bfb4f8733da1acf0aeeae21e6b) ([#10897](https://github.com/yt-dlp/yt-dlp/issues/10897)) by [Sakura286](https://github.com/Sakura286) +- **patreon**: [Fix comments extraction](https://github.com/yt-dlp/yt-dlp/commit/1d253b0a27110d174c40faf8fb1c999d099e0cde) ([#11530](https://github.com/yt-dlp/yt-dlp/issues/11530)) by [bashonly](https://github.com/bashonly), [jshumphrey](https://github.com/jshumphrey) +- **pialive**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/d867f99622ef7fba690b08da56c39d739b822bb7) ([#10811](https://github.com/yt-dlp/yt-dlp/issues/10811)) by [ChocoLZS](https://github.com/ChocoLZS) +- **radioradicale**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/70c55cb08f780eab687e881ef42bb5c6007d290b) ([#5607](https://github.com/yt-dlp/yt-dlp/issues/5607)) by [a13ssandr0](https://github.com/a13ssandr0), [pzhlkj6612](https://github.com/pzhlkj6612) +- **reddit**: [Improve error handling](https://github.com/yt-dlp/yt-dlp/commit/7ea2787920cccc6b8ea30791993d114fbd564434) ([#11573](https://github.com/yt-dlp/yt-dlp/issues/11573)) by [bashonly](https://github.com/bashonly) +- **redgifsuser**: [Fix extraction](https://github.com/yt-dlp/yt-dlp/commit/d215fba7edb69d4fa665f43663756fd260b1489f) ([#11531](https://github.com/yt-dlp/yt-dlp/issues/11531)) by [jshumphrey](https://github.com/jshumphrey) +- **rutube**: [Rework extractors](https://github.com/yt-dlp/yt-dlp/commit/e398217aae19bb25f91797bfbe8a3243698d7f45) ([#11480](https://github.com/yt-dlp/yt-dlp/issues/11480)) by [seproDev](https://github.com/seproDev) +- **sonylivseries**: [Add `sort_order` extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/2009cb27e17014787bf63eaa2ada51293d54f22a) ([#11569](https://github.com/yt-dlp/yt-dlp/issues/11569)) by [bashonly](https://github.com/bashonly) +- **soop**: [Fix thumbnail extraction](https://github.com/yt-dlp/yt-dlp/commit/c699bafc5038b59c9afe8c2e69175fb66424c832) ([#11545](https://github.com/yt-dlp/yt-dlp/issues/11545)) by [bashonly](https://github.com/bashonly) +- **spankbang**: [Support browser impersonation](https://github.com/yt-dlp/yt-dlp/commit/8388ec256f7753b02488788e3cfa771f6e1db247) ([#11542](https://github.com/yt-dlp/yt-dlp/issues/11542)) by [jshumphrey](https://github.com/jshumphrey) +- **spreaker** + - [Support episode pages and access keys](https://github.com/yt-dlp/yt-dlp/commit/c39016f66df76d14284c705736ca73db8055d8de) ([#11489](https://github.com/yt-dlp/yt-dlp/issues/11489)) by [julionc](https://github.com/julionc) + - [Support podcast and feed pages](https://github.com/yt-dlp/yt-dlp/commit/c6737310619022248f5d0fd13872073cac168453) ([#10968](https://github.com/yt-dlp/yt-dlp/issues/10968)) by [subrat-lima](https://github.com/subrat-lima) +- **youtube** + - [Player client maintenance](https://github.com/yt-dlp/yt-dlp/commit/637d62a3a9fc723d68632c1af25c30acdadeeb85) ([#11528](https://github.com/yt-dlp/yt-dlp/issues/11528)) by [bashonly](https://github.com/bashonly), [seproDev](https://github.com/seproDev) + - [Remove broken OAuth support](https://github.com/yt-dlp/yt-dlp/commit/52c0ffe40ad6e8404d93296f575007b05b04c686) ([#11558](https://github.com/yt-dlp/yt-dlp/issues/11558)) by [bashonly](https://github.com/bashonly) + - tab: [Fix podcasts tab extraction](https://github.com/yt-dlp/yt-dlp/commit/37cd7660eaff397c551ee18d80507702342b0c2b) ([#11567](https://github.com/yt-dlp/yt-dlp/issues/11567)) by [seproDev](https://github.com/seproDev) + +#### Misc. changes +- **build** + - [Bump PyInstaller version pin to `>=6.11.1`](https://github.com/yt-dlp/yt-dlp/commit/f9c8deb4e5887ff5150e911ac0452e645f988044) ([#11507](https://github.com/yt-dlp/yt-dlp/issues/11507)) by [bashonly](https://github.com/bashonly) + - [Enable attestations for trusted publishing](https://github.com/yt-dlp/yt-dlp/commit/f13df591d4d7ca8e2f31b35c9c91e69ba9e9b013) ([#11420](https://github.com/yt-dlp/yt-dlp/issues/11420)) by [bashonly](https://github.com/bashonly) + - [Pin `websockets` version to >=13.0,<14](https://github.com/yt-dlp/yt-dlp/commit/240a7d43c8a67ffb86d44dc276805aa43c358dcc) ([#11488](https://github.com/yt-dlp/yt-dlp/issues/11488)) by [bashonly](https://github.com/bashonly) +- **cleanup** + - [Deprecate more compat functions](https://github.com/yt-dlp/yt-dlp/commit/f95a92b3d0169a784ee15a138fbe09d82b2754a1) ([#11439](https://github.com/yt-dlp/yt-dlp/issues/11439)) by [seproDev](https://github.com/seproDev) + - [Remove dead extractors](https://github.com/yt-dlp/yt-dlp/commit/10fc719bc7f1eef469389c5219102266ef411f29) ([#11566](https://github.com/yt-dlp/yt-dlp/issues/11566)) by [doe1080](https://github.com/doe1080) + - Miscellaneous: [da252d9](https://github.com/yt-dlp/yt-dlp/commit/da252d9d322af3e2178ac5eae324809502a0a862) by [bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K), [seproDev](https://github.com/seproDev) + ### 2024.11.04 #### Important changes diff --git a/yt-dlp/README.md b/yt-dlp/README.md index 09096218e8..dd3a3189ba 100644 --- a/yt-dlp/README.md +++ b/yt-dlp/README.md @@ -342,8 +342,9 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git extractor plugins; postprocessor plugins can only be loaded from the default plugin directories - --flat-playlist Do not extract the videos of a playlist, - only list them + --flat-playlist Do not extract a playlist's URL result + entries; some entry metadata may be missing + and downloading may be bypassed --no-flat-playlist Fully extract the videos of a playlist (default) --live-from-start Download livestreams from the start. @@ -1866,8 +1867,8 @@ The following extractors use this feature: #### bilibili * `prefer_multi_flv`: Prefer extracting flv formats over mp4 for older videos that still provide legacy formats -#### digitalconcerthall -* `prefer_combined_hls`: Prefer extracting combined/pre-merged video and audio HLS formats. This will exclude 4K/HEVC video and lossless/FLAC audio formats, which are only available as split video/audio HLS formats +#### sonylivseries +* `sort_order`: Episode sort order for series extraction - one of `asc` (ascending, oldest first) or `desc` (descending, newest first). Default is `asc` **Note**: These options may be changed/removed in the future without concern for backward compatibility diff --git a/yt-dlp/devscripts/changelog_override.json b/yt-dlp/devscripts/changelog_override.json index 08ea9666ed..906e5cf728 100644 --- a/yt-dlp/devscripts/changelog_override.json +++ b/yt-dlp/devscripts/changelog_override.json @@ -234,5 +234,10 @@ "when": "57212a5f97ce367590aaa5c3e9a135eead8f81f7", "short": "[ie/vimeo] Fix API retries (#11351)", "authors": ["bashonly"] + }, + { + "action": "add", + "when": "52c0ffe40ad6e8404d93296f575007b05b04c686", + "short": "[priority] **Login with OAuth is no longer supported for YouTube**\nDue to a change made by the site, yt-dlp is longer able to support OAuth login for YouTube. [Read more](https://github.com/yt-dlp/yt-dlp/issues/11462#issuecomment-2471703090)" } ] diff --git a/yt-dlp/supportedsites.md b/yt-dlp/supportedsites.md index fc79e4ae61..916735e08b 100644 --- a/yt-dlp/supportedsites.md +++ b/yt-dlp/supportedsites.md @@ -129,6 +129,8 @@ - **Bandcamp:album** - **Bandcamp:user** - **Bandcamp:weekly** + - **Bandlab** + - **BandlabPlaylist** - **BannedVideo** - **bbc**: [*bbc*](## "netrc machine") BBC - **bbc.co.uk**: [*bbc*](## "netrc machine") BBC iPlayer @@ -484,6 +486,7 @@ - **Gab** - **GabTV** - **Gaia**: [*gaia*](## "netrc machine") + - **GameDevTVDashboard**: [*gamedevtv*](## "netrc machine") - **GameJolt** - **GameJoltCommunity** - **GameJoltGame** @@ -651,6 +654,8 @@ - **Karaoketv** - **Katsomo**: (**Currently broken**) - **KelbyOne**: (**Currently broken**) + - **Kenh14Playlist** + - **Kenh14Video** - **Ketnet** - **khanacademy** - **khanacademy:unit** @@ -784,10 +789,6 @@ - **MicrosoftLearnSession** - **MicrosoftMedius** - **microsoftstream**: Microsoft Stream - - **mildom**: Record ongoing live by specific user in Mildom - - **mildom:clip**: Clip in Mildom - - **mildom:​user:vod**: Download all VODs from specific user in Mildom - - **mildom:vod**: VOD in Mildom - **minds** - **minds:channel** - **minds:group** @@ -798,6 +799,7 @@ - **MiTele**: mitele.es - **mixch** - **mixch:archive** + - **mixch:movie** - **mixcloud** - **mixcloud:playlist** - **mixcloud:user** @@ -1060,8 +1062,8 @@ - **PhilharmonieDeParis**: Philharmonie de Paris - **phoenix.de** - **Photobucket** + - **PiaLive** - **Piapro**: [*piapro*](## "netrc machine") - - **PIAULIZAPortal**: ulizaportal.jp - PIA LIVE STREAM - **Picarto** - **PicartoVod** - **Piksel** @@ -1088,8 +1090,6 @@ - **PodbayFMChannel** - **Podchaser** - **podomatic**: (**Currently broken**) - - **Pokemon** - - **PokemonWatch** - **PokerGo**: [*pokergo*](## "netrc machine") - **PokerGoCollection**: [*pokergo*](## "netrc machine") - **PolsatGo** @@ -1160,6 +1160,7 @@ - **RadioJavan**: (**Currently broken**) - **radiokapital** - **radiokapital:show** + - **RadioRadicale** - **RadioZetPodcast** - **radlive** - **radlive:channel** @@ -1367,9 +1368,7 @@ - **spotify**: Spotify episodes (**Currently broken**) - **spotify:show**: Spotify shows (**Currently broken**) - **Spreaker** - - **SpreakerPage** - **SpreakerShow** - - **SpreakerShowPage** - **SpringboardPlatform** - **Sprout** - **SproutVideo** @@ -1570,6 +1569,8 @@ - **UFCTV**: [*ufctv*](## "netrc machine") - **ukcolumn**: (**Currently broken**) - **UKTVPlay** + - **UlizaPlayer** + - **UlizaPortal**: ulizaportal.jp - **umg:de**: Universal Music Deutschland (**Currently broken**) - **Unistra** - **Unity**: (**Currently broken**) @@ -1587,8 +1588,6 @@ - **Varzesh3**: (**Currently broken**) - **Vbox7** - **Veo** - - **Veoh** - - **veoh:user** - **Vesti**: Вести.Ru (**Currently broken**) - **Vevo** - **VevoPlaylist** diff --git a/yt-dlp/yt_dlp/extractor/_extractors.py b/yt-dlp/yt_dlp/extractor/_extractors.py index 0d849c1697..967010826e 100644 --- a/yt-dlp/yt_dlp/extractor/_extractors.py +++ b/yt-dlp/yt_dlp/extractor/_extractors.py @@ -1520,8 +1520,8 @@ from .pgatour import PGATourIE from .philharmoniedeparis import PhilharmonieDeParisIE from .phoenix import PhoenixIE from .photobucket import PhotobucketIE +from .pialive import PiaLiveIE from .piapro import PiaproIE -from .piaulizaportal import PIAULIZAPortalIE from .picarto import ( PicartoIE, PicartoVodIE, @@ -2250,6 +2250,10 @@ from .ufctv import ( ) from .ukcolumn import UkColumnIE from .uktvplay import UKTVPlayIE +from .uliza import ( + UlizaPlayerIE, + UlizaPortalIE, +) from .umg import UMGDeIE from .unistra import UnistraIE from .unity import UnityIE diff --git a/yt-dlp/yt_dlp/extractor/bandlab.py b/yt-dlp/yt_dlp/extractor/bandlab.py index e48d5d3f76..64aa2ba70d 100644 --- a/yt-dlp/yt_dlp/extractor/bandlab.py +++ b/yt-dlp/yt_dlp/extractor/bandlab.py @@ -1,4 +1,3 @@ - from .common import InfoExtractor from ..utils import ( ExtractorError, diff --git a/yt-dlp/yt_dlp/extractor/common.py b/yt-dlp/yt_dlp/extractor/common.py index 2aa40a77a7..28a3adf936 100644 --- a/yt-dlp/yt_dlp/extractor/common.py +++ b/yt-dlp/yt_dlp/extractor/common.py @@ -3767,7 +3767,7 @@ class InfoExtractor: """ Merge subtitle dictionaries, language by language. """ if target is None: target = {} - for d in dicts: + for d in filter(None, dicts): for lang, subs in d.items(): target[lang] = cls._merge_subtitle_items(target.get(lang, []), subs) return target diff --git a/yt-dlp/yt_dlp/extractor/ctvnews.py b/yt-dlp/yt_dlp/extractor/ctvnews.py index ebed9eb2d3..6d33f85e4a 100644 --- a/yt-dlp/yt_dlp/extractor/ctvnews.py +++ b/yt-dlp/yt_dlp/extractor/ctvnews.py @@ -1,14 +1,27 @@ +import json import re +import urllib.parse from .common import InfoExtractor -from ..utils import orderedSet +from .ninecninemedia import NineCNineMediaIE +from ..utils import extract_attributes, orderedSet +from ..utils.traversal import find_element, traverse_obj class CTVNewsIE(InfoExtractor): - _VALID_URL = r'https?://(?:.+?\.)?ctvnews\.ca/(?:video\?(?:clip|playlist|bin)Id=|.*?)(?P[0-9.]+)' + _BASE_REGEX = r'https?://(?:[^.]+\.)?ctvnews\.ca/' + _VIDEO_ID_RE = r'(?P\d{5,})' + _PLAYLIST_ID_RE = r'(?P\d\.\d{5,})' + _VALID_URL = [ + rf'{_BASE_REGEX}video/c{_VIDEO_ID_RE}', + rf'{_BASE_REGEX}video(?:-gallery)?/?\?clipId={_VIDEO_ID_RE}', + rf'{_BASE_REGEX}video/?\?(?:playlist|bin)Id={_PLAYLIST_ID_RE}', + rf'{_BASE_REGEX}(?!video/)[^?#]*?{_PLAYLIST_ID_RE}/?(?:$|[?#])', + rf'{_BASE_REGEX}(?!video/)[^?#]+\?binId={_PLAYLIST_ID_RE}', + ] _TESTS = [{ 'url': 'http://www.ctvnews.ca/video?clipId=901995', - 'md5': '9b8624ba66351a23e0b6e1391971f9af', + 'md5': 'b608f466c7fa24b9666c6439d766ab7e', 'info_dict': { 'id': '901995', 'ext': 'flv', @@ -16,6 +29,33 @@ class CTVNewsIE(InfoExtractor): 'description': 'md5:958dd3b4f5bbbf0ed4d045c790d89285', 'timestamp': 1467286284, 'upload_date': '20160630', + 'categories': [], + 'season_number': 0, + 'season': 'Season 0', + 'tags': [], + 'series': 'CTV News National | Archive | Stories 2', + 'season_id': '57981', + 'thumbnail': r're:https?://.*\.jpg$', + 'duration': 764.631, + }, + }, { + 'url': 'https://barrie.ctvnews.ca/video/c3030933-here_s-what_s-making-news-for-nov--15?binId=1272429', + 'md5': '8b8c2b33c5c1803e3c26bc74ff8694d5', + 'info_dict': { + 'id': '3030933', + 'ext': 'flv', + 'title': 'Here’s what’s making news for Nov. 15', + 'description': 'Here are the top stories we’re working on for CTV News at 11 for Nov. 15', + 'thumbnail': 'http://images2.9c9media.com/image_asset/2021_2_22_a602e68e-1514-410e-a67a-e1f7cccbacab_png_2000x1125.jpg', + 'season_id': '58104', + 'season_number': 0, + 'tags': [], + 'season': 'Season 0', + 'categories': [], + 'series': 'CTV News Barrie', + 'upload_date': '20241116', + 'duration': 42.943, + 'timestamp': 1731722452, }, }, { 'url': 'http://www.ctvnews.ca/video?playlistId=1.2966224', @@ -31,6 +71,72 @@ class CTVNewsIE(InfoExtractor): 'id': '1.2876780', }, 'playlist_mincount': 100, + }, { + 'url': 'https://www.ctvnews.ca/it-s-been-23-years-since-toronto-called-in-the-army-after-a-major-snowstorm-1.5736957', + 'info_dict': + { + 'id': '1.5736957', + }, + 'playlist_mincount': 6, + }, { + 'url': 'https://www.ctvnews.ca/business/respondents-to-bank-of-canada-questionnaire-largely-oppose-creating-a-digital-loonie-1.6665797', + 'md5': '24bc4b88cdc17d8c3fc01dfc228ab72c', + 'info_dict': { + 'id': '2695026', + 'ext': 'flv', + 'season_id': '89852', + 'series': 'From CTV News Channel', + 'description': 'md5:796a985a23cacc7e1e2fafefd94afd0a', + 'season': '2023', + 'title': 'Bank of Canada asks public about digital currency', + 'categories': [], + 'tags': [], + 'upload_date': '20230526', + 'season_number': 2023, + 'thumbnail': 'http://images2.9c9media.com/image_asset/2019_3_28_35f5afc3-10f6-4d92-b194-8b9a86f55c6a_png_1920x1080.jpg', + 'timestamp': 1685105157, + 'duration': 253.553, + }, + }, { + 'url': 'https://stox.ctvnews.ca/video-gallery?clipId=582589', + 'md5': '135cc592df607d29dddc931f1b756ae2', + 'info_dict': { + 'id': '582589', + 'ext': 'flv', + 'categories': [], + 'timestamp': 1427906183, + 'season_number': 0, + 'duration': 125.559, + 'thumbnail': 'http://images2.9c9media.com/image_asset/2019_3_28_35f5afc3-10f6-4d92-b194-8b9a86f55c6a_png_1920x1080.jpg', + 'series': 'CTV News Stox', + 'description': 'CTV original footage of the rise and fall of the Berlin Wall.', + 'title': 'Berlin Wall', + 'season_id': '63817', + 'season': 'Season 0', + 'tags': [], + 'upload_date': '20150401', + }, + }, { + 'url': 'https://ottawa.ctvnews.ca/features/regional-contact/regional-contact-archive?binId=1.1164587#3023759', + 'md5': 'a14c0603557decc6531260791c23cc5e', + 'info_dict': { + 'id': '3023759', + 'ext': 'flv', + 'season_number': 2024, + 'timestamp': 1731798000, + 'season': '2024', + 'episode': 'Episode 125', + 'description': 'CTV News Ottawa at Six', + 'duration': 2712.076, + 'episode_number': 125, + 'upload_date': '20241116', + 'title': 'CTV News Ottawa at Six for Saturday, November 16, 2024', + 'thumbnail': 'http://images2.9c9media.com/image_asset/2019_3_28_35f5afc3-10f6-4d92-b194-8b9a86f55c6a_png_1920x1080.jpg', + 'categories': [], + 'tags': [], + 'series': 'CTV News Ottawa at Six', + 'season_id': '92667', + }, }, { 'url': 'http://www.ctvnews.ca/1.810401', 'only_matching': True, @@ -42,29 +148,35 @@ class CTVNewsIE(InfoExtractor): 'only_matching': True, }] + def _ninecninemedia_url_result(self, clip_id): + return self.url_result(f'9c9media:ctvnews_web:{clip_id}', NineCNineMediaIE, clip_id) + def _real_extract(self, url): page_id = self._match_id(url) - def ninecninemedia_url_result(clip_id): - return { - '_type': 'url_transparent', - 'id': clip_id, - 'url': f'9c9media:ctvnews_web:{clip_id}', - 'ie_key': 'NineCNineMedia', - } + if mobj := re.fullmatch(self._VIDEO_ID_RE, urllib.parse.urlparse(url).fragment): + page_id = mobj.group('id') - if page_id.isdigit(): - return ninecninemedia_url_result(page_id) - else: - webpage = self._download_webpage(f'http://www.ctvnews.ca/{page_id}', page_id, query={ - 'ot': 'example.AjaxPageLayout.ot', - 'maxItemsPerPage': 1000000, - }) - entries = [ninecninemedia_url_result(clip_id) for clip_id in orderedSet( - re.findall(r'clip\.id\s*=\s*(\d+);', webpage))] - if not entries: - webpage = self._download_webpage(url, page_id) - if 'getAuthStates("' in webpage: - entries = [ninecninemedia_url_result(clip_id) for clip_id in - self._search_regex(r'getAuthStates\("([\d+,]+)"', webpage, 'clip ids').split(',')] - return self.playlist_result(entries, page_id) + if re.fullmatch(self._VIDEO_ID_RE, page_id): + return self._ninecninemedia_url_result(page_id) + + webpage = self._download_webpage(f'https://www.ctvnews.ca/{page_id}', page_id, query={ + 'ot': 'example.AjaxPageLayout.ot', + 'maxItemsPerPage': 1000000, + }) + entries = [self._ninecninemedia_url_result(clip_id) + for clip_id in orderedSet(re.findall(r'clip\.id\s*=\s*(\d+);', webpage))] + if not entries: + webpage = self._download_webpage(url, page_id) + if 'getAuthStates("' in webpage: + entries = [self._ninecninemedia_url_result(clip_id) for clip_id in + self._search_regex(r'getAuthStates\("([\d+,]+)"', webpage, 'clip ids').split(',')] + else: + entries = [ + self._ninecninemedia_url_result(clip_id) for clip_id in + traverse_obj(webpage, ( + {find_element(tag='jasper-player-container', html=True)}, + {extract_attributes}, 'axis-ids', {json.loads}, ..., 'axisId', {str})) + ] + + return self.playlist_result(entries, page_id) diff --git a/yt-dlp/yt_dlp/extractor/digitalconcerthall.py b/yt-dlp/yt_dlp/extractor/digitalconcerthall.py index edb6fa9c08..4c4fe470da 100644 --- a/yt-dlp/yt_dlp/extractor/digitalconcerthall.py +++ b/yt-dlp/yt_dlp/extractor/digitalconcerthall.py @@ -1,7 +1,10 @@ +import time + from .common import InfoExtractor from ..networking.exceptions import HTTPError from ..utils import ( ExtractorError, + jwt_decode_hs256, parse_codecs, try_get, url_or_none, @@ -13,9 +16,6 @@ from ..utils.traversal import traverse_obj class DigitalConcertHallIE(InfoExtractor): IE_DESC = 'DigitalConcertHall extractor' _VALID_URL = r'https?://(?:www\.)?digitalconcerthall\.com/(?P[a-z]+)/(?Pfilm|concert|work)/(?P[0-9]+)-?(?P[0-9]+)?' - _OAUTH_URL = 'https://api.digitalconcerthall.com/v2/oauth2/token' - _USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15' - _ACCESS_TOKEN = None _NETRC_MACHINE = 'digitalconcerthall' _TESTS = [{ 'note': 'Playlist with only one video', @@ -69,59 +69,157 @@ class DigitalConcertHallIE(InfoExtractor): 'params': {'skip_download': 'm3u8'}, 'playlist_count': 1, }] + _LOGIN_HINT = ('Use --username token --password ACCESS_TOKEN where ACCESS_TOKEN ' + 'is the "access_token_production" from your browser local storage') + _REFRESH_HINT = 'or else use a "refresh_token" with --username refresh --password REFRESH_TOKEN' + _OAUTH_URL = 'https://api.digitalconcerthall.com/v2/oauth2/token' + _CLIENT_ID = 'dch.webapp' + _CLIENT_SECRET = '2ySLN+2Fwb' + _USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15' + _OAUTH_HEADERS = { + 'Accept': 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', + 'Origin': 'https://www.digitalconcerthall.com', + 'Referer': 'https://www.digitalconcerthall.com/', + 'User-Agent': _USER_AGENT, + } + _access_token = None + _access_token_expiry = 0 + _refresh_token = None - def _perform_login(self, username, password): - login_token = self._download_json( - self._OAUTH_URL, - None, 'Obtaining token', errnote='Unable to obtain token', data=urlencode_postdata({ + @property + def _access_token_is_expired(self): + return self._access_token_expiry - 30 <= int(time.time()) + + def _set_access_token(self, value): + self._access_token = value + self._access_token_expiry = traverse_obj(value, ({jwt_decode_hs256}, 'exp', {int})) or 0 + + def _cache_tokens(self, /): + self.cache.store(self._NETRC_MACHINE, 'tokens', { + 'access_token': self._access_token, + 'refresh_token': self._refresh_token, + }) + + def _fetch_new_tokens(self, invalidate=False): + if invalidate: + self.report_warning('Access token has been invalidated') + self._set_access_token(None) + + if not self._access_token_is_expired: + return + + if not self._refresh_token: + self._set_access_token(None) + self._cache_tokens() + raise ExtractorError( + 'Access token has expired or been invalidated. ' + 'Get a new "access_token_production" value from your browser ' + f'and try again, {self._REFRESH_HINT}', expected=True) + + # If we only have a refresh token, we need a temporary "initial token" for the refresh flow + bearer_token = self._access_token or self._download_json( + self._OAUTH_URL, None, 'Obtaining initial token', 'Unable to obtain initial token', + data=urlencode_postdata({ 'affiliate': 'none', 'grant_type': 'device', 'device_vendor': 'unknown', - # device_model 'Safari' gets split streams of 4K/HEVC video and lossless/FLAC audio - 'device_model': 'unknown' if self._configuration_arg('prefer_combined_hls') else 'Safari', - 'app_id': 'dch.webapp', + # device_model 'Safari' gets split streams of 4K/HEVC video and lossless/FLAC audio, + # but this is no longer effective since actual login is not possible anymore + 'device_model': 'unknown', + 'app_id': self._CLIENT_ID, 'app_distributor': 'berlinphil', - 'app_version': '1.84.0', - 'client_secret': '2ySLN+2Fwb', - }), headers={ - 'Accept': 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', - 'User-Agent': self._USER_AGENT, - })['access_token'] + 'app_version': '1.95.0', + 'client_secret': self._CLIENT_SECRET, + }), headers=self._OAUTH_HEADERS)['access_token'] + try: - login_response = self._download_json( - self._OAUTH_URL, - None, note='Logging in', errnote='Unable to login', data=urlencode_postdata({ - 'grant_type': 'password', - 'username': username, - 'password': password, + response = self._download_json( + self._OAUTH_URL, None, 'Refreshing token', 'Unable to refresh token', + data=urlencode_postdata({ + 'grant_type': 'refresh_token', + 'refresh_token': self._refresh_token, + 'client_id': self._CLIENT_ID, + 'client_secret': self._CLIENT_SECRET, }), headers={ - 'Accept': 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', - 'Referer': 'https://www.digitalconcerthall.com', - 'Authorization': f'Bearer {login_token}', - 'User-Agent': self._USER_AGENT, + **self._OAUTH_HEADERS, + 'Authorization': f'Bearer {bearer_token}', }) - except ExtractorError as error: - if isinstance(error.cause, HTTPError) and error.cause.status == 401: - raise ExtractorError('Invalid username or password', expected=True) + except ExtractorError as e: + if isinstance(e.cause, HTTPError) and e.cause.status == 401: + self._set_access_token(None) + self._refresh_token = None + self._cache_tokens() + raise ExtractorError('Your tokens have been invalidated', expected=True) raise - self._ACCESS_TOKEN = login_response['access_token'] + + self._set_access_token(response['access_token']) + if refresh_token := traverse_obj(response, ('refresh_token', {str})): + self.write_debug('New refresh token granted') + self._refresh_token = refresh_token + self._cache_tokens() + + def _perform_login(self, username, password): + self.report_login() + + if username == 'refresh': + self._refresh_token = password + self._fetch_new_tokens() + + if username == 'token': + if not traverse_obj(password, {jwt_decode_hs256}): + raise ExtractorError( + f'The access token passed to yt-dlp is not valid. {self._LOGIN_HINT}', expected=True) + self._set_access_token(password) + self._cache_tokens() + + if username in ('refresh', 'token'): + if self.get_param('cachedir') is not False: + token_type = 'access' if username == 'token' else 'refresh' + self.to_screen(f'Your {token_type} token has been cached to disk. To use the cached ' + 'token next time, pass --username cache along with any password') + return + + if username != 'cache': + raise ExtractorError( + 'Login with username and password is no longer supported ' + f'for this site. {self._LOGIN_HINT}, {self._REFRESH_HINT}', expected=True) + + # Try cached access_token + cached_tokens = self.cache.load(self._NETRC_MACHINE, 'tokens', default={}) + self._set_access_token(cached_tokens.get('access_token')) + self._refresh_token = cached_tokens.get('refresh_token') + if not self._access_token_is_expired: + return + + # Try cached refresh_token + self._fetch_new_tokens(invalidate=True) def _real_initialize(self): - if not self._ACCESS_TOKEN: - self.raise_login_required(method='password') + if not self._access_token: + self.raise_login_required( + 'All content on this site is only available for registered users. ' + f'{self._LOGIN_HINT}, {self._REFRESH_HINT}', method=None) def _entries(self, items, language, type_, **kwargs): for item in items: video_id = item['id'] - stream_info = self._download_json( - self._proto_relative_url(item['_links']['streams']['href']), video_id, headers={ - 'Accept': 'application/json', - 'Authorization': f'Bearer {self._ACCESS_TOKEN}', - 'Accept-Language': language, - 'User-Agent': self._USER_AGENT, - }) + + for should_retry in (True, False): + self._fetch_new_tokens(invalidate=not should_retry) + try: + stream_info = self._download_json( + self._proto_relative_url(item['_links']['streams']['href']), video_id, headers={ + 'Accept': 'application/json', + 'Authorization': f'Bearer {self._access_token}', + 'Accept-Language': language, + 'User-Agent': self._USER_AGENT, + }) + break + except ExtractorError as error: + if should_retry and isinstance(error.cause, HTTPError) and error.cause.status == 401: + continue + raise formats = [] for m3u8_url in traverse_obj(stream_info, ('channel', ..., 'stream', ..., 'url', {url_or_none})): @@ -157,7 +255,6 @@ class DigitalConcertHallIE(InfoExtractor): 'Accept': 'application/json', 'Accept-Language': language, 'User-Agent': self._USER_AGENT, - 'Authorization': f'Bearer {self._ACCESS_TOKEN}', }) videos = [vid_info] if type_ == 'film' else traverse_obj(vid_info, ('_embedded', ..., ...)) diff --git a/yt-dlp/yt_dlp/extractor/facebook.py b/yt-dlp/yt_dlp/extractor/facebook.py index 91e2f3489c..c07efcd581 100644 --- a/yt-dlp/yt_dlp/extractor/facebook.py +++ b/yt-dlp/yt_dlp/extractor/facebook.py @@ -569,7 +569,7 @@ class FacebookIE(InfoExtractor): if dash_manifest: formats.extend(self._parse_mpd_formats( compat_etree_fromstring(urllib.parse.unquote_plus(dash_manifest)), - mpd_url=url_or_none(video.get('dash_manifest_url')) or mpd_url)) + mpd_url=url_or_none(vid_data.get('dash_manifest_url')) or mpd_url)) def process_formats(info): # Downloads with browser's User-Agent are rate limited. Working around diff --git a/yt-dlp/yt_dlp/extractor/litv.py b/yt-dlp/yt_dlp/extractor/litv.py index 93f926a9ff..df9d141de3 100644 --- a/yt-dlp/yt_dlp/extractor/litv.py +++ b/yt-dlp/yt_dlp/extractor/litv.py @@ -1,30 +1,32 @@ import json +import uuid from .common import InfoExtractor from ..utils import ( ExtractorError, int_or_none, + join_nonempty, smuggle_url, traverse_obj, try_call, unsmuggle_url, + urljoin, ) class LiTVIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?litv\.tv/(?:vod|promo)/[^/]+/(?:content\.do)?\?.*?\b(?:content_)?id=(?P[^&]+)' - - _URL_TEMPLATE = 'https://www.litv.tv/vod/%s/content.do?content_id=%s' - + _VALID_URL = r'https?://(?:www\.)?litv\.tv/(?:[^/?#]+/watch/|vod/[^/?#]+/content\.do\?content_id=)(?P[\w-]+)' + _URL_TEMPLATE = 'https://www.litv.tv/%s/watch/%s' + _GEO_COUNTRIES = ['TW'] _TESTS = [{ - 'url': 'https://www.litv.tv/vod/drama/content.do?brc_id=root&id=VOD00041610&isUHEnabled=true&autoPlay=1', + 'url': 'https://www.litv.tv/drama/watch/VOD00041610', 'info_dict': { 'id': 'VOD00041606', 'title': '花千骨', }, 'playlist_count': 51, # 50 episodes + 1 trailer }, { - 'url': 'https://www.litv.tv/vod/drama/content.do?brc_id=root&id=VOD00041610&isUHEnabled=true&autoPlay=1', + 'url': 'https://www.litv.tv/drama/watch/VOD00041610', 'md5': 'b90ff1e9f1d8f5cfcd0a44c3e2b34c7a', 'info_dict': { 'id': 'VOD00041610', @@ -32,16 +34,15 @@ class LiTVIE(InfoExtractor): 'title': '花千骨第1集', 'thumbnail': r're:https?://.*\.jpg$', 'description': '《花千骨》陸劇線上看。十六年前,平靜的村莊內,一名女嬰隨異相出生,途徑此地的蜀山掌門清虛道長算出此女命運非同一般,她體內散發的異香易招惹妖魔。一念慈悲下,他在村莊周邊設下結界阻擋妖魔入侵,讓其年滿十六後去蜀山,並賜名花千骨。', - 'categories': ['奇幻', '愛情', '中國', '仙俠'], + 'categories': ['奇幻', '愛情', '仙俠', '古裝'], 'episode': 'Episode 1', 'episode_number': 1, }, 'params': { 'noplaylist': True, }, - 'skip': 'Georestricted to Taiwan', }, { - 'url': 'https://www.litv.tv/promo/miyuezhuan/?content_id=VOD00044841&', + 'url': 'https://www.litv.tv/drama/watch/VOD00044841', 'md5': '88322ea132f848d6e3e18b32a832b918', 'info_dict': { 'id': 'VOD00044841', @@ -55,94 +56,62 @@ class LiTVIE(InfoExtractor): def _extract_playlist(self, playlist_data, content_type): all_episodes = [ self.url_result(smuggle_url( - self._URL_TEMPLATE % (content_type, episode['contentId']), + self._URL_TEMPLATE % (content_type, episode['content_id']), {'force_noplaylist': True})) # To prevent infinite recursion - for episode in traverse_obj(playlist_data, ('seasons', ..., 'episode', lambda _, v: v['contentId']))] + for episode in traverse_obj(playlist_data, ('seasons', ..., 'episodes', lambda _, v: v['content_id']))] - return self.playlist_result(all_episodes, playlist_data['contentId'], playlist_data.get('title')) + return self.playlist_result(all_episodes, playlist_data['content_id'], playlist_data.get('title')) def _real_extract(self, url): url, smuggled_data = unsmuggle_url(url, {}) - video_id = self._match_id(url) - webpage = self._download_webpage(url, video_id) + vod_data = self._search_nextjs_data(webpage, video_id)['props']['pageProps'] - if self._search_regex( - r'(?i)]*http-equiv="refresh"\s[^>]*content="[0-9]+;\s*url=https://www\.litv\.tv/"', - webpage, 'meta refresh redirect', default=False, group=0): - raise ExtractorError('No such content found', expected=True) + program_info = traverse_obj(vod_data, ('programInformation', {dict})) or {} + playlist_data = traverse_obj(vod_data, ('seriesTree')) + if playlist_data and self._yes_playlist(program_info.get('series_id'), video_id, smuggled_data): + return self._extract_playlist(playlist_data, program_info.get('content_type')) - program_info = self._parse_json(self._search_regex( - r'var\s+programInfo\s*=\s*([^;]+)', webpage, 'VOD data', default='{}'), - video_id) + asset_id = traverse_obj(program_info, ('assets', 0, 'asset_id', {str})) + if asset_id: # This is a VOD + media_type = 'vod' + else: # This is a live stream + asset_id = program_info['content_id'] + media_type = program_info['content_type'] + puid = try_call(lambda: self._get_cookies('https://www.litv.tv/')['PUID'].value) + if puid: + endpoint = 'get-urls' + else: + puid = str(uuid.uuid4()) + endpoint = 'get-urls-no-auth' + video_data = self._download_json( + f'https://www.litv.tv/api/{endpoint}', video_id, + data=json.dumps({'AssetId': asset_id, 'MediaType': media_type, 'puid': puid}).encode(), + headers={'Content-Type': 'application/json'}) - # In browsers `getProgramInfo` request is always issued. Usually this - # endpoint gives the same result as the data embedded in the webpage. - # If, for some reason, there are no embedded data, we do an extra request. - if 'assetId' not in program_info: - program_info = self._download_json( - 'https://www.litv.tv/vod/ajax/getProgramInfo', video_id, - query={'contentId': video_id}, - headers={'Accept': 'application/json'}) - - series_id = program_info['seriesId'] - if self._yes_playlist(series_id, video_id, smuggled_data): - playlist_data = self._download_json( - 'https://www.litv.tv/vod/ajax/getSeriesTree', video_id, - query={'seriesId': series_id}, headers={'Accept': 'application/json'}) - return self._extract_playlist(playlist_data, program_info['contentType']) - - video_data = self._parse_json(self._search_regex( - r'uiHlsUrl\s*=\s*testBackendData\(([^;]+)\);', - webpage, 'video data', default='{}'), video_id) - if not video_data: - payload = {'assetId': program_info['assetId']} - puid = try_call(lambda: self._get_cookies('https://www.litv.tv/')['PUID'].value) - if puid: - payload.update({ - 'type': 'auth', - 'puid': puid, - }) - endpoint = 'getUrl' - else: - payload.update({ - 'watchDevices': program_info['watchDevices'], - 'contentType': program_info['contentType'], - }) - endpoint = 'getMainUrlNoAuth' - video_data = self._download_json( - f'https://www.litv.tv/vod/ajax/{endpoint}', video_id, - data=json.dumps(payload).encode(), - headers={'Content-Type': 'application/json'}) - - if not video_data.get('fullpath'): - error_msg = video_data.get('errorMessage') - if error_msg == 'vod.error.outsideregionerror': + if error := traverse_obj(video_data, ('error', {dict})): + error_msg = traverse_obj(error, ('message', {str})) + if error_msg and 'OutsideRegionError' in error_msg: self.raise_geo_restricted('This video is available in Taiwan only') - if error_msg: + elif error_msg: raise ExtractorError(f'{self.IE_NAME} said: {error_msg}', expected=True) - raise ExtractorError(f'Unexpected result from {self.IE_NAME}') + raise ExtractorError(f'Unexpected error from {self.IE_NAME}') formats = self._extract_m3u8_formats( - video_data['fullpath'], video_id, ext='mp4', - entry_protocol='m3u8_native', m3u8_id='hls') + video_data['result']['AssetURLs'][0], video_id, ext='mp4', m3u8_id='hls') for a_format in formats: # LiTV HLS segments doesn't like compressions a_format.setdefault('http_headers', {})['Accept-Encoding'] = 'identity' - title = program_info['title'] + program_info.get('secondaryMark', '') - description = program_info.get('description') - thumbnail = program_info.get('imageFile') - categories = [item['name'] for item in program_info.get('category', [])] - episode = int_or_none(program_info.get('episode')) - return { 'id': video_id, 'formats': formats, - 'title': title, - 'description': description, - 'thumbnail': thumbnail, - 'categories': categories, - 'episode_number': episode, + 'title': join_nonempty('title', 'secondary_mark', delim='', from_dict=program_info), + **traverse_obj(program_info, { + 'description': ('description', {str}), + 'thumbnail': ('picture', {urljoin('https://p-cdnstatic.svc.litv.tv/')}), + 'categories': ('genres', ..., 'name', {str}), + 'episode_number': ('episode', {int_or_none}), + }), } diff --git a/yt-dlp/yt_dlp/extractor/pialive.py b/yt-dlp/yt_dlp/extractor/pialive.py new file mode 100644 index 0000000000..7469135c1b --- /dev/null +++ b/yt-dlp/yt_dlp/extractor/pialive.py @@ -0,0 +1,122 @@ +from .common import InfoExtractor +from ..utils import ( + ExtractorError, + clean_html, + extract_attributes, + get_element_by_class, + get_element_html_by_class, + multipart_encode, + str_or_none, + unified_timestamp, + url_or_none, +) +from ..utils.traversal import traverse_obj + + +class PiaLiveIE(InfoExtractor): + _VALID_URL = r'https?://player\.pia-live\.jp/stream/(?P[\w-]+)' + _PLAYER_ROOT_URL = 'https://player.pia-live.jp/' + _PIA_LIVE_API_URL = 'https://api.pia-live.jp' + _API_KEY = 'kfds)FKFps-dms9e' + _TESTS = [{ + 'url': 'https://player.pia-live.jp/stream/4JagFBEIM14s_hK9aXHKf3k3F3bY5eoHFQxu68TC6krUDqGOwN4d61dCWQYOd6CTxl4hjya9dsfEZGsM4uGOUdax60lEI4twsXGXf7crmz8Gk__GhupTrWxA7RFRVt76', + 'info_dict': { + 'id': '88f3109a-f503-4d0f-a9f7-9f39ac745d84', + 'display_id': '2431867_001', + 'title': 'こながめでたい日2024の視聴ページ | PIA LIVE STREAM(ぴあライブストリーム)', + 'live_status': 'was_live', + 'comment_count': int, + }, + 'params': { + 'getcomments': True, + 'skip_download': True, + 'ignore_no_formats_error': True, + }, + 'skip': 'The video is no longer available', + }, { + 'url': 'https://player.pia-live.jp/stream/4JagFBEIM14s_hK9aXHKf3k3F3bY5eoHFQxu68TC6krJdu0GVBVbVy01IwpJ6J3qBEm3d9TCTt1d0eWpsZGj7DrOjVOmS7GAWGwyscMgiThopJvzgWC4H5b-7XQjAfRZ', + 'info_dict': { + 'id': '9ce8b8ba-f6d1-4d1f-83a0-18c3148ded93', + 'display_id': '2431867_002', + 'title': 'こながめでたい日2024の視聴ページ | PIA LIVE STREAM(ぴあライブストリーム)', + 'live_status': 'was_live', + 'comment_count': int, + }, + 'params': { + 'getcomments': True, + 'skip_download': True, + 'ignore_no_formats_error': True, + }, + 'skip': 'The video is no longer available', + }] + + def _extract_var(self, variable, html): + return self._search_regex( + rf'(?:var|const|let)\s+{variable}\s*=\s*(["\'])(?P(?:(?!\1).)+)\1', + html, f'variable {variable}', group='value') + + def _real_extract(self, url): + video_key = self._match_id(url) + webpage = self._download_webpage(url, video_key) + + program_code = self._extract_var('programCode', webpage) + article_code = self._extract_var('articleCode', webpage) + title = self._html_extract_title(webpage) + + if get_element_html_by_class('play-end', webpage): + raise ExtractorError('The video is no longer available', expected=True, video_id=program_code) + + if start_info := clean_html(get_element_by_class('play-waiting__date', webpage)): + date, time = self._search_regex( + r'(?P\d{4}/\d{1,2}/\d{1,2})\([月火水木金土日]\)(?P