From a96af7ed1251226d2a9f4d60bd72bad80ee5ae1e Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Mon, 3 Nov 2025 19:37:22 +0100 Subject: [PATCH] Update On Mon Nov 3 19:37:21 CET 2025 --- .github/update.log | 1 + clash-meta-android/README.md | 2 +- clash-meta/adapter/adapter.go | 14 -- clash-meta/adapter/outbound/base.go | 8 +- clash-meta/adapter/parser.go | 8 +- clash-meta/common/maphash/comparable_go120.go | 2 + clash-meta/common/maphash/comparable_go124.go | 2 + clash-meta/common/maphash/maphash_test.go | 4 +- clash-meta/common/structure/structure.go | 6 + clash-meta/common/structure/structure_test.go | 20 ++ clash-meta/constant/adapters.go | 9 +- clash-meta/transport/vmess/http.go | 7 +- clash-nyanpasu/backend/Cargo.lock | 6 +- clash-nyanpasu/frontend/nyanpasu/package.json | 2 +- clash-nyanpasu/manifest/version.json | 4 +- clash-nyanpasu/package.json | 4 +- clash-nyanpasu/pnpm-lock.yaml | 170 ++++++++--------- .../mediatek/dts/mt7981b-huasifei-ws3006.dts | 21 +-- .../filogic/base-files/etc/board.d/01_leds | 19 +- mieru/apis/common/listen.go | 11 +- mieru/apis/server/interface.go | 9 +- mieru/apis/server/server.go | 7 +- mieru/pkg/protocol/mux.go | 73 +++++--- mieru/pkg/protocol/underlay_packet.go | 10 +- .../cmd/exampleapiserver/exampleapiserver.go | 7 +- mihomo/adapter/adapter.go | 14 -- mihomo/adapter/outbound/base.go | 8 +- mihomo/adapter/parser.go | 8 +- mihomo/common/maphash/comparable_go120.go | 2 + mihomo/common/maphash/comparable_go124.go | 2 + mihomo/common/maphash/maphash_test.go | 4 +- mihomo/common/structure/structure.go | 6 + mihomo/common/structure/structure_test.go | 20 ++ mihomo/constant/adapters.go | 9 +- mihomo/transport/vmess/http.go | 7 +- openwrt-packages/openlist2/Makefile | 8 +- .../src/local/http/http_client.rs | 1 + shadowsocks-rust/snap/snapcraft.yaml | 5 + small/v2ray-geodata/Makefile | 4 +- .../Common/{FileManager.cs => FileUtils.cs} | 2 +- v2rayn/v2rayN/ServiceLib/Common/WindowsJob.cs | 177 ------------------ .../ServiceLib/Handler/ConnectionHandler.cs | 36 +++- .../Handler/SysProxy/ProxySettingLinux.cs | 2 +- .../Handler/SysProxy/ProxySettingOSX.cs | 2 +- .../ServiceLib/Helper/HttpClientHelper.cs | 162 +--------------- .../ServiceLib/Manager/CoreAdminManager.cs | 4 +- .../v2rayN/ServiceLib/Manager/CoreManager.cs | 4 +- .../v2rayN/ServiceLib/Manager/TaskManager.cs | 6 +- .../{Common => Models}/SemanticVersion.cs | 2 +- .../Singbox/SingboxOutboundService.cs | 9 +- .../ServiceLib/Services/DownloadService.cs | 4 +- .../ServiceLib/Services/SpeedtestService.cs | 2 +- .../ServiceLib/Services/UpdateService.cs | 12 +- .../ServiceLib/Services/WindowsJobService.cs | 171 +++++++++++++++++ .../ViewModels/BackupAndRestoreViewModel.cs | 8 +- .../ViewModels/CheckUpdateViewModel.cs | 8 +- yt-dlp/yt_dlp/extractor/_extractors.py | 1 + yt-dlp/yt_dlp/extractor/nascar.py | 60 ++++++ 58 files changed, 584 insertions(+), 612 deletions(-) rename v2rayn/v2rayN/ServiceLib/Common/{FileManager.cs => FileUtils.cs} (99%) delete mode 100644 v2rayn/v2rayN/ServiceLib/Common/WindowsJob.cs rename v2rayn/v2rayN/ServiceLib/{Common => Models}/SemanticVersion.cs (99%) create mode 100644 v2rayn/v2rayN/ServiceLib/Services/WindowsJobService.cs create mode 100644 yt-dlp/yt_dlp/extractor/nascar.py diff --git a/.github/update.log b/.github/update.log index 23d52b29f7..f2be19df57 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1170,3 +1170,4 @@ Update On Thu Oct 30 19:42:18 CET 2025 Update On Fri Oct 31 19:38:32 CET 2025 Update On Sat Nov 1 19:37:41 CET 2025 Update On Sun Nov 2 19:34:13 CET 2025 +Update On Mon Nov 3 19:37:13 CET 2025 diff --git a/clash-meta-android/README.md b/clash-meta-android/README.md index 58a65bc9cb..5cc436f234 100644 --- a/clash-meta-android/README.md +++ b/clash-meta-android/README.md @@ -44,7 +44,7 @@ Feature of [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta) 5. Build ```bash - ./gradlew app:assembleMeta-AlphaRelease + ./gradlew app:assembleAlphaRelease ``` ### Automation diff --git a/clash-meta/adapter/adapter.go b/clash-meta/adapter/adapter.go index 4f127bcf6a..ef8d4ee347 100644 --- a/clash-meta/adapter/adapter.go +++ b/clash-meta/adapter/adapter.go @@ -51,26 +51,12 @@ func (p *Proxy) AliveForTestUrl(url string) bool { return p.alive.Load() } -// Dial implements C.Proxy -func (p *Proxy) Dial(metadata *C.Metadata) (C.Conn, error) { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) - defer cancel() - return p.DialContext(ctx, metadata) -} - // DialContext implements C.ProxyAdapter func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) { conn, err := p.ProxyAdapter.DialContext(ctx, metadata) return conn, err } -// DialUDP implements C.ProxyAdapter -func (p *Proxy) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout) - defer cancel() - return p.ListenPacketContext(ctx, metadata) -} - // ListenPacketContext implements C.ProxyAdapter func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata) diff --git a/clash-meta/adapter/outbound/base.go b/clash-meta/adapter/outbound/base.go index 04a0fa98ae..93f6e14256 100644 --- a/clash-meta/adapter/outbound/base.go +++ b/clash-meta/adapter/outbound/base.go @@ -263,7 +263,9 @@ func NewConn(c net.Conn, a C.ProxyAdapter) C.Conn { if _, ok := c.(syscall.Conn); !ok { // exclusion system conn like *net.TCPConn c = N.NewDeadlineConn(c) // most conn from outbound can't handle readDeadline correctly } - return &conn{N.NewExtendedConn(c), []string{a.Name()}, a.Addr()} + cc := &conn{N.NewExtendedConn(c), nil, a.Addr()} + cc.AppendToChains(a) + return cc } type packetConn struct { @@ -320,7 +322,9 @@ func newPacketConn(pc net.PacketConn, a ProxyAdapter) C.PacketConn { if _, ok := pc.(syscall.Conn); !ok { // exclusion system conn like *net.UDPConn epc = N.NewDeadlineEnhancePacketConn(epc) // most conn from outbound can't handle readDeadline correctly } - return &packetConn{epc, []string{a.Name()}, a.Name(), utils.NewUUIDV4().String(), a.Addr(), a.ResolveUDP} + cpc := &packetConn{epc, nil, a.Name(), utils.NewUUIDV4().String(), a.Addr(), a.ResolveUDP} + cpc.AppendToChains(a) + return cpc } type AddRef interface { diff --git a/clash-meta/adapter/parser.go b/clash-meta/adapter/parser.go index 56febe2817..3052ab107f 100644 --- a/clash-meta/adapter/parser.go +++ b/clash-meta/adapter/parser.go @@ -49,13 +49,7 @@ func ParseProxy(mapping map[string]any) (C.Proxy, error) { } proxy, err = outbound.NewHttp(*httpOption) case "vmess": - vmessOption := &outbound.VmessOption{ - HTTPOpts: outbound.HTTPOptions{ - Method: "GET", - Path: []string{"/"}, - }, - } - + vmessOption := &outbound.VmessOption{} err = decoder.Decode(mapping, vmessOption) if err != nil { break diff --git a/clash-meta/common/maphash/comparable_go120.go b/clash-meta/common/maphash/comparable_go120.go index 05256d67dd..b4ddad84c6 100644 --- a/clash-meta/common/maphash/comparable_go120.go +++ b/clash-meta/common/maphash/comparable_go120.go @@ -138,3 +138,5 @@ func escape[T any](x T) T { // ptrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) but as an ideal constant. // It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit). const ptrSize = 4 << (^uintptr(0) >> 63) + +const testComparableAllocations = false diff --git a/clash-meta/common/maphash/comparable_go124.go b/clash-meta/common/maphash/comparable_go124.go index 3a96edb661..4e5fcc33d0 100644 --- a/clash-meta/common/maphash/comparable_go124.go +++ b/clash-meta/common/maphash/comparable_go124.go @@ -11,3 +11,5 @@ func Comparable[T comparable](seed Seed, v T) uint64 { func WriteComparable[T comparable](h *Hash, x T) { maphash.WriteComparable(h, x) } + +const testComparableAllocations = true diff --git a/clash-meta/common/maphash/maphash_test.go b/clash-meta/common/maphash/maphash_test.go index 73887f2715..6cafe9cbee 100644 --- a/clash-meta/common/maphash/maphash_test.go +++ b/clash-meta/common/maphash/maphash_test.go @@ -423,7 +423,9 @@ func TestWriteComparableNoncommute(t *testing.T) { } func TestComparableAllocations(t *testing.T) { - t.Skip("test broken in old golang version") + if !testComparableAllocations { + t.Skip("test broken in old golang version") + } seed := MakeSeed() x := heapStr(t) allocs := testing.AllocsPerRun(10, func() { diff --git a/clash-meta/common/structure/structure.go b/clash-meta/common/structure/structure.go index 5bafc178e0..bf79f7dd27 100644 --- a/clash-meta/common/structure/structure.go +++ b/clash-meta/common/structure/structure.go @@ -53,6 +53,12 @@ func (d *Decoder) Decode(src map[string]any, dst any) error { key, omitKey, found := strings.Cut(tag, ",") omitempty := found && omitKey == "omitempty" + // As a special case, if the field tag is "-", the field is always omitted. + // Note that a field with name "-" can still be generated using the tag "-,". + if key == "-" { + continue + } + value, ok := src[key] if !ok { if d.option.KeyReplacer != nil { diff --git a/clash-meta/common/structure/structure_test.go b/clash-meta/common/structure/structure_test.go index fcdd853a63..06dffd0f32 100644 --- a/clash-meta/common/structure/structure_test.go +++ b/clash-meta/common/structure/structure_test.go @@ -288,3 +288,23 @@ func TestStructure_Null(t *testing.T) { assert.Nil(t, err) assert.Equal(t, s.Opt.Bar, "") } + +func TestStructure_Ignore(t *testing.T) { + rawMap := map[string]any{ + "-": "newData", + } + + s := struct { + MustIgnore string `test:"-"` + }{MustIgnore: "oldData"} + + err := decoder.Decode(rawMap, &s) + assert.Nil(t, err) + assert.Equal(t, s.MustIgnore, "oldData") + + // test omitempty + delete(rawMap, "-") + err = decoder.Decode(rawMap, &s) + assert.Nil(t, err) + assert.Equal(t, s.MustIgnore, "oldData") +} diff --git a/clash-meta/constant/adapters.go b/clash-meta/constant/adapters.go index ab48c47d23..97e9235b5c 100644 --- a/clash-meta/constant/adapters.go +++ b/clash-meta/constant/adapters.go @@ -139,8 +139,11 @@ type ProxyAdapter interface { // SupportUOT return UDP over TCP support SupportUOT() bool + // SupportWithDialer only for deprecated relay group, the new protocol does not need to be implemented. SupportWithDialer() NetWork + // DialContextWithDialer only for deprecated relay group, the new protocol does not need to be implemented. DialContextWithDialer(ctx context.Context, dialer Dialer, metadata *Metadata) (Conn, error) + // ListenPacketWithDialer only for deprecated relay group, the new protocol does not need to be implemented. ListenPacketWithDialer(ctx context.Context, dialer Dialer, metadata *Metadata) (PacketConn, error) // IsL3Protocol return ProxyAdapter working in L3 (tell dns module not pass the domain to avoid loopback) @@ -178,12 +181,6 @@ type Proxy interface { ExtraDelayHistories() map[string]ProxyState LastDelayForTestUrl(url string) uint16 URLTest(ctx context.Context, url string, expectedStatus utils.IntRanges[uint16]) (uint16, error) - - // Deprecated: use DialContext instead. - Dial(metadata *Metadata) (Conn, error) - - // Deprecated: use DialPacketConn instead. - DialUDP(metadata *Metadata) (PacketConn, error) } // AdapterType is enum of adapter type diff --git a/clash-meta/transport/vmess/http.go b/clash-meta/transport/vmess/http.go index 3c66fe6b24..94f1fbd351 100644 --- a/clash-meta/transport/vmess/http.go +++ b/clash-meta/transport/vmess/http.go @@ -3,7 +3,6 @@ package vmess import ( "bufio" "bytes" - "errors" "fmt" "net" "net/http" @@ -55,11 +54,11 @@ func (hc *httpConn) Write(b []byte) (int, error) { return hc.Conn.Write(b) } - if len(hc.cfg.Path) == 0 { - return -1, errors.New("path is empty") + path := "/" + if len(hc.cfg.Path) > 0 { + path = hc.cfg.Path[randv2.IntN(len(hc.cfg.Path))] } - path := hc.cfg.Path[randv2.IntN(len(hc.cfg.Path))] host := hc.cfg.Host if header := hc.cfg.Headers["Host"]; len(header) != 0 { host = header[randv2.IntN(len(header))] diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index b53c6d53ad..9bceba8c7c 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -2294,7 +2294,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -9886,9 +9886,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index c6c1b8ef34..b3ff7fdf41 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -56,7 +56,7 @@ "@csstools/normalize.css": "12.1.1", "@emotion/babel-plugin": "11.13.5", "@emotion/react": "11.14.0", - "@iconify/json": "2.2.402", + "@iconify/json": "2.2.403", "@monaco-editor/react": "4.7.0", "@tanstack/react-query": "5.90.6", "@tanstack/react-router": "1.134.9", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 17588bf464..7f9b2102d8 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.15", - "mihomo_alpha": "alpha-99e68e9", + "mihomo_alpha": "alpha-6fb1f79", "clash_rs": "v0.9.1", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.9.1-alpha+sha.4479974" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-11-01T22:21:17.190Z" + "updated_at": "2025-11-02T22:20:46.358Z" } diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index 9abf75c3d6..e611fd28d6 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -66,7 +66,7 @@ "@tauri-apps/cli": "2.8.4", "@types/fs-extra": "11.0.4", "@types/lodash-es": "4.17.12", - "@types/node": "24.9.2", + "@types/node": "24.10.0", "@typescript-eslint/eslint-plugin": "8.46.2", "@typescript-eslint/parser": "8.46.2", "autoprefixer": "10.4.21", @@ -85,7 +85,7 @@ "eslint-plugin-react-compiler": "19.1.0-rc.2", "eslint-plugin-react-hooks": "7.0.1", "globals": "16.5.0", - "knip": "5.66.4", + "knip": "5.67.0", "lint-staged": "16.2.6", "neostandard": "0.12.2", "npm-run-all2": "8.0.4", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index caa9a39187..7671a96b74 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -24,7 +24,7 @@ importers: devDependencies: '@commitlint/cli': specifier: 20.1.0 - version: 20.1.0(@types/node@24.9.2)(typescript@5.9.3) + version: 20.1.0(@types/node@24.10.0)(typescript@5.9.3) '@commitlint/config-conventional': specifier: 20.0.0 version: 20.0.0 @@ -47,8 +47,8 @@ importers: specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: 24.9.2 - version: 24.9.2 + specifier: 24.10.0 + version: 24.10.0 '@typescript-eslint/eslint-plugin': specifier: 8.46.2 version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.39.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.0(jiti@2.6.1))(typescript@5.9.3) @@ -104,8 +104,8 @@ importers: specifier: 16.5.0 version: 16.5.0 knip: - specifier: 5.66.4 - version: 5.66.4(@types/node@24.9.2)(typescript@5.9.3) + specifier: 5.67.0 + version: 5.67.0(@types/node@24.10.0)(typescript@5.9.3) lint-staged: specifier: 16.2.6 version: 16.2.6 @@ -346,8 +346,8 @@ importers: specifier: 11.14.0 version: 11.14.0(@types/react@19.2.2)(react@19.2.0) '@iconify/json': - specifier: 2.2.402 - version: 2.2.402 + specifier: 2.2.403 + version: 2.2.403 '@monaco-editor/react': specifier: 4.7.0 version: 4.7.0(monaco-editor@0.54.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -359,10 +359,10 @@ importers: version: 1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tanstack/react-router-devtools': specifier: 1.134.9 - version: 1.134.9(@tanstack/react-router@1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.134.9)(@types/node@24.9.2)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1) + version: 1.134.9(@tanstack/react-router@1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.134.9)(@types/node@24.10.0)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1) '@tanstack/router-plugin': specifier: 1.134.9 - version: 1.134.9(@tanstack/react-router@1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 1.134.9(@tanstack/react-router@1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) '@tauri-apps/plugin-clipboard-manager': specifier: 2.3.0 version: 2.3.0 @@ -398,13 +398,13 @@ importers: version: 13.15.4 '@vitejs/plugin-legacy': specifier: 7.2.1 - version: 7.2.1(terser@5.36.0)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 7.2.1(terser@5.36.0)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) '@vitejs/plugin-react': specifier: 5.1.0 - version: 5.1.0(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 5.1.0(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) '@vitejs/plugin-react-swc': specifier: 4.2.0 - version: 4.2.0(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 4.2.0(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) change-case: specifier: 5.4.4 version: 5.4.4 @@ -443,19 +443,19 @@ importers: version: 13.15.20 vite: specifier: 7.1.12 - version: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + version: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) vite-plugin-html: specifier: 3.2.2 - version: 3.2.2(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 3.2.2(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) vite-plugin-sass-dts: specifier: 1.3.34 - version: 1.3.34(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.93.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 1.3.34(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.93.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) vite-plugin-svgr: specifier: 4.5.0 - version: 4.5.0(rollup@4.46.2)(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 4.5.0(rollup@4.46.2)(typescript@5.9.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 5.1.4(typescript@5.9.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) zod: specifier: 4.1.12 version: 4.1.12 @@ -491,7 +491,7 @@ importers: version: 19.2.2 '@vitejs/plugin-react': specifier: 5.1.0 - version: 5.1.0(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 5.1.0(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) ahooks: specifier: 3.9.6 version: 3.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -521,10 +521,10 @@ importers: version: 4.1.16 vite: specifier: 7.1.12 - version: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + version: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 5.1.4(typescript@5.9.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) devDependencies: '@emotion/react': specifier: 11.14.0 @@ -549,7 +549,7 @@ importers: version: 5.2.0(typescript@5.9.3) vite-plugin-dts: specifier: 4.5.4 - version: 4.5.4(@types/node@24.9.2)(rollup@4.46.2)(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 4.5.4(@types/node@24.10.0)(rollup@4.46.2)(typescript@5.9.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)) scripts: dependencies: @@ -1821,8 +1821,8 @@ packages: prettier-plugin-ember-template-tag: optional: true - '@iconify/json@2.2.402': - resolution: {integrity: sha512-c4fqEUW+JrolUzwQJR5m4BgoAGGlTn8YjelJW1kc0k5b45/PztyNtLC+VT7Rwgc/sPYEDB4gwbQJCiwnJRku7A==} + '@iconify/json@2.2.403': + resolution: {integrity: sha512-TU27b9pVsbYuTKF7i/OHAB5rUscWhe85AEk0vPkDT1MMqV7ZWWxUk5B7j03JHacX5NCtggB1KiCz985wjc7HVQ==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -3534,8 +3534,8 @@ packages: '@types/node@16.18.108': resolution: {integrity: sha512-fj42LD82fSv6yN9C6Q4dzS+hujHj+pTv0IpRR3kI20fnYeS0ytBpjFO9OjmDowSPPt4lNKN46JLaKbCyP+BW2A==} - '@types/node@24.9.2': - resolution: {integrity: sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==} + '@types/node@24.10.0': + resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -6188,8 +6188,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - knip@5.66.4: - resolution: {integrity: sha512-HmTnxdmoHAvwKmFktRGY1++tXRI8J36eVrOpfj/ybTVVT1QBKBlbBEN1s3cJBx9UL+hXTZDNQif+gs7fUKldbw==} + knip@5.67.0: + resolution: {integrity: sha512-zVa7bUx4dPN2xqxCidz48C+74io9l43YQ6YjxBeMcYjIRjOZ8UTbB3FZhfrb+71QETxacYlfGCg0MPMpXZUKQw==} engines: {node: '>=18.18.0'} hasBin: true peerDependencies: @@ -9836,11 +9836,11 @@ snapshots: '@bufbuild/protobuf@2.5.2': {} - '@commitlint/cli@20.1.0(@types/node@24.9.2)(typescript@5.9.3)': + '@commitlint/cli@20.1.0(@types/node@24.10.0)(typescript@5.9.3)': dependencies: '@commitlint/format': 20.0.0 '@commitlint/lint': 20.0.0 - '@commitlint/load': 20.1.0(@types/node@24.9.2)(typescript@5.9.3) + '@commitlint/load': 20.1.0(@types/node@24.10.0)(typescript@5.9.3) '@commitlint/read': 20.0.0 '@commitlint/types': 20.0.0 tinyexec: 1.0.1 @@ -9887,7 +9887,7 @@ snapshots: '@commitlint/rules': 20.0.0 '@commitlint/types': 20.0.0 - '@commitlint/load@20.1.0(@types/node@24.9.2)(typescript@5.9.3)': + '@commitlint/load@20.1.0(@types/node@24.10.0)(typescript@5.9.3)': dependencies: '@commitlint/config-validator': 20.0.0 '@commitlint/execute-rule': 20.0.0 @@ -9895,7 +9895,7 @@ snapshots: '@commitlint/types': 20.0.0 chalk: 5.4.1 cosmiconfig: 9.0.0(typescript@5.9.3) - cosmiconfig-typescript-loader: 6.1.0(@types/node@24.9.2)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@24.10.0)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -10303,7 +10303,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@iconify/json@2.2.402': + '@iconify/json@2.2.403': dependencies: '@iconify/types': 2.0.0 pathe: 2.0.3 @@ -10359,23 +10359,23 @@ snapshots: '@material/material-color-utilities@0.3.0': {} - '@microsoft/api-extractor-model@7.30.3(@types/node@24.9.2)': + '@microsoft/api-extractor-model@7.30.3(@types/node@24.10.0)': dependencies: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@24.9.2) + '@rushstack/node-core-library': 5.11.0(@types/node@24.10.0) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.51.0(@types/node@24.9.2)': + '@microsoft/api-extractor@7.51.0(@types/node@24.10.0)': dependencies: - '@microsoft/api-extractor-model': 7.30.3(@types/node@24.9.2) + '@microsoft/api-extractor-model': 7.30.3(@types/node@24.10.0) '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@24.9.2) + '@rushstack/node-core-library': 5.11.0(@types/node@24.10.0) '@rushstack/rig-package': 0.5.3 - '@rushstack/terminal': 0.15.0(@types/node@24.9.2) - '@rushstack/ts-command-line': 4.23.5(@types/node@24.9.2) + '@rushstack/terminal': 0.15.0(@types/node@24.10.0) + '@rushstack/ts-command-line': 4.23.5(@types/node@24.10.0) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.8 @@ -11232,7 +11232,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/node-core-library@5.11.0(@types/node@24.9.2)': + '@rushstack/node-core-library@5.11.0(@types/node@24.10.0)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -11243,23 +11243,23 @@ snapshots: resolve: 1.22.8 semver: 7.5.4 optionalDependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 '@rushstack/rig-package@0.5.3': dependencies: resolve: 1.22.8 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.15.0(@types/node@24.9.2)': + '@rushstack/terminal@0.15.0(@types/node@24.10.0)': dependencies: - '@rushstack/node-core-library': 5.11.0(@types/node@24.9.2) + '@rushstack/node-core-library': 5.11.0(@types/node@24.10.0) supports-color: 8.1.1 optionalDependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 - '@rushstack/ts-command-line@4.23.5(@types/node@24.9.2)': + '@rushstack/ts-command-line@4.23.5(@types/node@24.10.0)': dependencies: - '@rushstack/terminal': 0.15.0(@types/node@24.9.2) + '@rushstack/terminal': 0.15.0(@types/node@24.10.0) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 @@ -11523,13 +11523,13 @@ snapshots: '@tanstack/query-core': 5.90.6 react: 19.2.0 - '@tanstack/react-router-devtools@1.134.9(@tanstack/react-router@1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.134.9)(@types/node@24.9.2)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)': + '@tanstack/react-router-devtools@1.134.9(@tanstack/react-router@1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.134.9)(@types/node@24.10.0)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)': dependencies: '@tanstack/react-router': 1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@tanstack/router-devtools-core': 1.134.9(@tanstack/router-core@1.134.9)(@types/node@24.9.2)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1) + '@tanstack/router-devtools-core': 1.134.9(@tanstack/router-core@1.134.9)(@types/node@24.10.0)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - '@tanstack/router-core' - '@types/node' @@ -11587,14 +11587,14 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/router-devtools-core@1.134.9(@tanstack/router-core@1.134.9)(@types/node@24.9.2)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)': + '@tanstack/router-devtools-core@1.134.9(@tanstack/router-core@1.134.9)(@types/node@24.10.0)(csstype@3.1.3)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(solid-js@1.9.5)(stylus@0.62.0)(terser@5.36.0)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)': dependencies: '@tanstack/router-core': 1.134.9 clsx: 2.1.1 goober: 2.1.16(csstype@3.1.3) solid-js: 1.9.5 tiny-invariant: 1.3.3 - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) optionalDependencies: csstype: 3.1.3 transitivePeerDependencies: @@ -11623,7 +11623,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.134.9(@tanstack/react-router@1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1))': + '@tanstack/router-plugin@1.134.9(@tanstack/react-router@1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.4 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) @@ -11641,7 +11641,7 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.134.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -11783,7 +11783,7 @@ snapshots: '@types/adm-zip@0.5.7': dependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 '@types/argparse@1.0.38': {} @@ -11814,12 +11814,12 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 24.9.2 + '@types/node': 24.10.0 '@types/responselike': 1.0.3 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 '@types/d3-array@3.2.1': {} @@ -11955,7 +11955,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 24.9.2 + '@types/node': 24.10.0 '@types/geojson@7946.0.14': {} @@ -11975,11 +11975,11 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 '@types/keyv@3.1.4': dependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 '@types/lodash-es@4.17.12': dependencies: @@ -11995,7 +11995,7 @@ snapshots: '@types/node@16.18.108': {} - '@types/node@24.9.2': + '@types/node@24.10.0': dependencies: undici-types: 7.16.0 @@ -12025,7 +12025,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 '@types/semver@7.7.1': {} @@ -12043,7 +12043,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 optional: true '@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.39.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.0(jiti@2.6.1))(typescript@5.9.3)': @@ -12254,7 +12254,7 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.10.1': optional: true - '@vitejs/plugin-legacy@7.2.1(terser@5.36.0)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1))': + '@vitejs/plugin-legacy@7.2.1(terser@5.36.0)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.0 '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.0) @@ -12269,19 +12269,19 @@ snapshots: regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.36.0 - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react-swc@4.2.0(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1))': + '@vitejs/plugin-react-swc@4.2.0(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.43 '@swc/core': 1.13.5 - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@5.1.0(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1))': + '@vitejs/plugin-react@5.1.0(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.4 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) @@ -12289,7 +12289,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.43 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -12966,9 +12966,9 @@ snapshots: core-js@3.46.0: {} - cosmiconfig-typescript-loader@6.1.0(@types/node@24.9.2)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3): + cosmiconfig-typescript-loader@6.1.0(@types/node@24.10.0)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3): dependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 cosmiconfig: 9.0.0(typescript@5.9.3) jiti: 2.6.1 typescript: 5.9.3 @@ -15028,10 +15028,10 @@ snapshots: kind-of@6.0.3: {} - knip@5.66.4(@types/node@24.9.2)(typescript@5.9.3): + knip@5.67.0(@types/node@24.10.0)(typescript@5.9.3): dependencies: '@nodelib/fs.walk': 1.2.8 - '@types/node': 24.9.2 + '@types/node': 24.10.0 fast-glob: 3.3.3 formatly: 0.3.0 jiti: 2.6.1 @@ -17637,9 +17637,9 @@ snapshots: - rollup - supports-color - vite-plugin-dts@4.5.4(@types/node@24.9.2)(rollup@4.46.2)(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): + vite-plugin-dts@4.5.4(@types/node@24.10.0)(rollup@4.46.2)(typescript@5.9.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): dependencies: - '@microsoft/api-extractor': 7.51.0(@types/node@24.9.2) + '@microsoft/api-extractor': 7.51.0(@types/node@24.10.0) '@rollup/pluginutils': 5.1.4(rollup@4.46.2) '@volar/typescript': 2.4.11 '@vue/language-core': 2.2.0(typescript@5.9.3) @@ -17650,13 +17650,13 @@ snapshots: magic-string: 0.30.17 typescript: 5.9.3 optionalDependencies: - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite-plugin-html@3.2.2(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): + vite-plugin-html@3.2.2(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): dependencies: '@rollup/pluginutils': 4.2.1 colorette: 2.0.20 @@ -17670,39 +17670,39 @@ snapshots: html-minifier-terser: 6.1.0 node-html-parser: 5.4.2 pathe: 0.2.0 - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) - vite-plugin-sass-dts@1.3.34(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.93.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): + vite-plugin-sass-dts@1.3.34(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.93.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): dependencies: postcss: 8.5.6 postcss-js: 4.0.1(postcss@8.5.6) prettier: 3.6.2 sass-embedded: 1.93.3 - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) - vite-plugin-svgr@4.5.0(rollup@4.46.2)(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): + vite-plugin-svgr@4.5.0(rollup@4.46.2)(typescript@5.9.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): dependencies: '@rollup/pluginutils': 5.2.0(rollup@4.46.2) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): + vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.9.3) optionalDependencies: - vite: 7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) + vite: 7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color - typescript - vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1): + vite@7.1.12(@types/node@24.10.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.93.3)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1): dependencies: esbuild: 0.25.0 fdir: 6.5.0(picomatch@4.0.3) @@ -17711,7 +17711,7 @@ snapshots: rollup: 4.46.2 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.9.2 + '@types/node': 24.10.0 fsevents: 2.3.3 jiti: 2.6.1 less: 4.2.0 diff --git a/lede/target/linux/mediatek/dts/mt7981b-huasifei-ws3006.dts b/lede/target/linux/mediatek/dts/mt7981b-huasifei-ws3006.dts index 7a8bb18ec4..2cbfc55222 100644 --- a/lede/target/linux/mediatek/dts/mt7981b-huasifei-ws3006.dts +++ b/lede/target/linux/mediatek/dts/mt7981b-huasifei-ws3006.dts @@ -98,8 +98,8 @@ gmac1: mac@1 { compatible = "mediatek,eth-mac"; reg = <1>; - phy-handle = <&phy0>; - phy-mode = "2500base-x"; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; nvmem-cells = <&macaddr_factory_4 2>; nvmem-cell-names = "mac-address"; @@ -117,20 +117,13 @@ interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; }; - phy0: ethernet-phy@0 { - compatible = "ethernet-phy-id03a2.9461"; - reg = <0>; - phy-mode = "gmii"; - nvmem-cells = <&phy_calibration>; - nvmem-cell-names = "phy-cal-data"; - }; - - phy6: ethernet-phy@6 { + phy1: ethernet-phy@1 { compatible = "ethernet-phy-ieee802.3-c45"; - reg = <6>; + reg = <1>; reset-assert-us = <100000>; reset-deassert-us = <100000>; - reset-gpios = <&pio 3 GPIO_ACTIVE_LOW>; + reset-gpios = <&pio 14 GPIO_ACTIVE_LOW>; + realtek,led-link-select = <0x0 0xa7 0xa7>; }; }; @@ -247,7 +240,7 @@ port@5 { reg = <5>; label = "wan"; - phy-handle = <&phy6>; + phy-handle = <&phy1>; phy-mode = "2500base-x"; }; diff --git a/lede/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds b/lede/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds index 1a74d6a3e6..25ada3ad86 100644 --- a/lede/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds +++ b/lede/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds @@ -22,13 +22,6 @@ bananapi,bpi-r4-poe) ucidef_set_led_netdev "lan2" "lan2" "mt7530-0:02:green:lan" "lan2" "link tx rx" ucidef_set_led_netdev "lan3" "lan3" "mt7530-0:03:green:lan" "lan3" "link tx rx" ;; -hf,m7986r1*) - ucidef_set_led_netdev "led-1" "LAN1" "led-1" "lan1" - ucidef_set_led_netdev "led-2" "LAN2" "led-2" "lan2" - ucidef_set_led_netdev "led-3" "LAN3" "led-3" "lan3" - ucidef_set_led_netdev "led-4" "LAN4" "led-4" "lan4" - ucidef_set_led_netdev "led-5" "WWAN" "led-5" "usb0" - ;; glinet,gl-x3000|\ glinet,gl-xe3000) ucidef_set_led_default "power" "POWER" "green:power" "1" @@ -40,6 +33,18 @@ glinet,gl-xe3000) ucidef_set_led_netdev "wlan2g" "WLAN2G" "green:wifi2g" "phy0-ap0" ucidef_set_led_netdev "wlan5g" "WLAN5G" "green:wifi5g" "phy1-ap0" ;; +hf,m7986r1*) + ucidef_set_led_netdev "led-1" "LAN1" "led-1" "lan1" + ucidef_set_led_netdev "led-2" "LAN2" "led-2" "lan2" + ucidef_set_led_netdev "led-3" "LAN3" "led-3" "lan3" + ucidef_set_led_netdev "led-4" "LAN4" "led-4" "lan4" + ucidef_set_led_netdev "led-5" "WWAN" "led-5" "usb0" + ;; +huasifei,ws3006) + ucidef_set_led_netdev "lan3" "LAN3" "green:gbe" "eth1" + ucidef_set_led_netdev "wan" "WAN" "green:wan" "wan" + ucidef_set_led_netdev "wlan" "WLAN" "green:wlan" "wlan1" + ;; imou,lc-hx3001|\ nokia,ea0326gmp) ucidef_set_led_netdev "lan" "LAN" "green:lan" "br-lan" diff --git a/mieru/apis/common/listen.go b/mieru/apis/common/listen.go index 919dcad3ab..023ebfad4a 100644 --- a/mieru/apis/common/listen.go +++ b/mieru/apis/common/listen.go @@ -20,10 +20,15 @@ import ( "net" ) -// ListenerFactory provides a way to create network listeners. -type ListenerFactory interface { +// StreamListenerFactory provides a way to create stream-oriented network listeners. +type StreamListenerFactory interface { Listen(ctx context.Context, network, address string) (net.Listener, error) +} + +// PacketListenerFactory provides a way to create packet-oriented network listeners. +type PacketListenerFactory interface { ListenPacket(ctx context.Context, network, address string) (net.PacketConn, error) } -var _ ListenerFactory = (*net.ListenConfig)(nil) +var _ StreamListenerFactory = (*net.ListenConfig)(nil) +var _ PacketListenerFactory = (*net.ListenConfig)(nil) diff --git a/mieru/apis/server/interface.go b/mieru/apis/server/interface.go index 275789e967..53d3db57d7 100644 --- a/mieru/apis/server/interface.go +++ b/mieru/apis/server/interface.go @@ -80,10 +80,15 @@ type ServerConfig struct { // Main configuration. Config *appctlpb.ServerConfig - // A listener factory to create network listeners. + // A listener factory to create stream-oriented network listeners. // // If this field is not set, a default listener factory is used. - ListenerFactory apicommon.ListenerFactory + StreamListenerFactory apicommon.StreamListenerFactory + + // A listener factory to create packet-oriented network listeners. + // + // If this field is not set, a default listener factory is used. + PacketListenerFactory apicommon.PacketListenerFactory } // NewServer creates a blank mieru server with no server config. diff --git a/mieru/apis/server/server.go b/mieru/apis/server/server.go index ef62411cd7..59e4f9283f 100644 --- a/mieru/apis/server/server.go +++ b/mieru/apis/server/server.go @@ -82,8 +82,11 @@ func (ms *mieruServer) Start() error { } ms.mux = protocol.NewMux(false) - if ms.config.ListenerFactory != nil { - ms.mux.SetListenerFactory(ms.config.ListenerFactory) + if ms.config.StreamListenerFactory != nil { + ms.mux.SetStreamListenerFactory(ms.config.StreamListenerFactory) + } + if ms.config.PacketListenerFactory != nil { + ms.mux.SetPacketListenerFactory(ms.config.PacketListenerFactory) } ms.mux.SetServerUsers(appctlcommon.UserListToMap(ms.config.Config.GetUsers())) mtu := common.DefaultMTU diff --git a/mieru/pkg/protocol/mux.go b/mieru/pkg/protocol/mux.go index 0925a47097..a0d7e876d6 100644 --- a/mieru/pkg/protocol/mux.go +++ b/mieru/pkg/protocol/mux.go @@ -44,21 +44,22 @@ const ( // Mux manages the sessions and underlays. type Mux struct { // ---- common fields ---- - isClient bool - endpoints []UnderlayProperties - underlays []Underlay - dialer apicommon.Dialer - resolver apicommon.DNSResolver - listenerFactory apicommon.ListenerFactory - chAccept chan net.Conn - acceptHasErr atomic.Bool - acceptErr chan error // this channel is closed when accept has error - used bool - done chan struct{} - ctx context.Context // mux master context - ctxCancelFunc context.CancelFunc // function to cancel master context when mux is closed - mu sync.Mutex - cleaner *time.Ticker + isClient bool + endpoints []UnderlayProperties + underlays []Underlay + dialer apicommon.Dialer + resolver apicommon.DNSResolver + streamListenerFactory apicommon.StreamListenerFactory + packetListenerFactory apicommon.PacketListenerFactory + chAccept chan net.Conn + acceptHasErr atomic.Bool + acceptErr chan error // this channel is closed when accept has error + used bool + done chan struct{} + ctx context.Context // mux master context + ctxCancelFunc context.CancelFunc // function to cancel master context when mux is closed + mu sync.Mutex + cleaner *time.Ticker // ---- client only fields ---- username string @@ -79,15 +80,16 @@ func NewMux(isClinet bool) *Mux { log.Infof("Initializing server multiplexer") } mux := &Mux{ - isClient: isClinet, - underlays: make([]Underlay, 0), - dialer: &net.Dialer{Timeout: 10 * time.Second, Control: sockopts.DefaultDialerControl()}, - resolver: &net.Resolver{}, - listenerFactory: &net.ListenConfig{Control: sockopts.DefaultListenerControl()}, - chAccept: make(chan net.Conn, sessionChanCapacity), - acceptErr: make(chan error), - done: make(chan struct{}), - cleaner: time.NewTicker(underlayCleanInterval), + isClient: isClinet, + underlays: make([]Underlay, 0), + dialer: &net.Dialer{Timeout: 10 * time.Second, Control: sockopts.DefaultDialerControl()}, + resolver: &net.Resolver{}, + streamListenerFactory: &net.ListenConfig{Control: sockopts.DefaultListenerControl()}, + packetListenerFactory: &net.ListenConfig{Control: sockopts.DefaultListenerControl()}, + chAccept: make(chan net.Conn, sessionChanCapacity), + acceptErr: make(chan error), + done: make(chan struct{}), + cleaner: time.NewTicker(underlayCleanInterval), } mux.ctx, mux.ctxCancelFunc = context.WithCancel(context.Background()) @@ -157,12 +159,21 @@ func (m *Mux) SetResolver(resolver apicommon.DNSResolver) *Mux { return m } -// SetListenerFactory updates the network listener factory used by the mux. -func (m *Mux) SetListenerFactory(listenerFactory apicommon.ListenerFactory) *Mux { +// SetStreamListenerFactory updates the stream-oriented network listener factory used by the mux. +func (m *Mux) SetStreamListenerFactory(listenerFactory apicommon.StreamListenerFactory) *Mux { m.mu.Lock() defer m.mu.Unlock() - m.listenerFactory = listenerFactory - log.Infof("Mux listener factory has been updated") + m.streamListenerFactory = listenerFactory + log.Infof("Mux stream listener factory has been updated") + return m +} + +// SetPacketListenerFactory updates the packet-oriented network listener factory used by the mux. +func (m *Mux) SetPacketListenerFactory(listenerFactory apicommon.PacketListenerFactory) *Mux { + m.mu.Lock() + defer m.mu.Unlock() + m.packetListenerFactory = listenerFactory + log.Infof("Mux packet listener factory has been updated") return m } @@ -389,7 +400,7 @@ func (m *Mux) acceptUnderlayLoop(ctx context.Context, properties UnderlayPropert } return } - rawListener, err := m.listenerFactory.Listen(ctx, tcpAddr.Network(), tcpAddr.String()) + rawListener, err := m.streamListenerFactory.Listen(ctx, tcpAddr.Network(), tcpAddr.String()) if err != nil { log.Errorf("Listen() failed: %v", err) if m.acceptHasErr.CompareAndSwap(false, true) { @@ -462,7 +473,7 @@ func (m *Mux) acceptUnderlayLoop(ctx context.Context, properties UnderlayPropert } return } - conn, err := m.listenerFactory.ListenPacket(ctx, udpAddr.Network(), udpAddr.String()) + conn, err := m.packetListenerFactory.ListenPacket(ctx, udpAddr.Network(), udpAddr.String()) if err != nil { log.Errorf("ListenPacket() failed: %v", err) if m.acceptHasErr.CompareAndSwap(false, true) { @@ -592,7 +603,7 @@ func (m *Mux) newUnderlay(ctx context.Context) (Underlay, error) { block.SetBlockContext(cipher.BlockContext{ UserName: m.username, }) - underlay, err = NewPacketUnderlay(ctx, p.RemoteAddr().Network(), p.RemoteAddr().String(), p.MTU(), block, m.resolver) + underlay, err = NewPacketUnderlay(ctx, m.packetListenerFactory, p.RemoteAddr().Network(), p.RemoteAddr().String(), p.MTU(), block, m.resolver) if err != nil { return nil, fmt.Errorf("NewUDPUnderlay() failed: %v", err) } diff --git a/mieru/pkg/protocol/underlay_packet.go b/mieru/pkg/protocol/underlay_packet.go index b74501c502..21843c2ade 100644 --- a/mieru/pkg/protocol/underlay_packet.go +++ b/mieru/pkg/protocol/underlay_packet.go @@ -30,7 +30,6 @@ import ( "github.com/enfein/mieru/v3/pkg/log" "github.com/enfein/mieru/v3/pkg/metrics" "github.com/enfein/mieru/v3/pkg/replay" - "github.com/enfein/mieru/v3/pkg/sockopts" "github.com/enfein/mieru/v3/pkg/stderror" ) @@ -67,7 +66,7 @@ var _ Underlay = &PacketUnderlay{} // "block" is the block encryption algorithm to encrypt packets. // // This function is only used by proxy client. -func NewPacketUnderlay(ctx context.Context, network, addr string, mtu int, block cipher.BlockCipher, resolver apicommon.DNSResolver) (*PacketUnderlay, error) { +func NewPacketUnderlay(ctx context.Context, packetListenerFactory apicommon.PacketListenerFactory, network, addr string, mtu int, block cipher.BlockCipher, resolver apicommon.DNSResolver) (*PacketUnderlay, error) { switch network { case "udp", "udp4", "udp6": default: @@ -82,12 +81,9 @@ func NewPacketUnderlay(ctx context.Context, network, addr string, mtu int, block return nil, fmt.Errorf("ResolveUDPAddr() failed: %w", err) } - conn, err := net.ListenUDP(network, localAddr) + conn, err := packetListenerFactory.ListenPacket(ctx, network, localAddr.String()) if err != nil { - return nil, fmt.Errorf("net.ListenUDP() failed: %w", err) - } - if err := sockopts.ApplyUDPControl(conn, sockopts.DefaultDialerControl()); err != nil { - return nil, fmt.Errorf("ApplyUDPControl() failed: %w", err) + return nil, fmt.Errorf("ListenPacket() failed: %w", err) } u := &PacketUnderlay{ baseUnderlay: *newBaseUnderlay(true, mtu), diff --git a/mieru/test/cmd/exampleapiserver/exampleapiserver.go b/mieru/test/cmd/exampleapiserver/exampleapiserver.go index 74e00b3f51..42a032bfc3 100644 --- a/mieru/test/cmd/exampleapiserver/exampleapiserver.go +++ b/mieru/test/cmd/exampleapiserver/exampleapiserver.go @@ -71,10 +71,9 @@ func main() { }, Users: []*appctlpb.User{ { - Name: username, - Password: password, - AllowPrivateIP: proto.Bool(true), - AllowLoopbackIP: proto.Bool(true), + Name: username, + Password: password, + // AllowPrivateIP and AllowLoopbackIP are not used by API. }, }, }, diff --git a/mihomo/adapter/adapter.go b/mihomo/adapter/adapter.go index 4f127bcf6a..ef8d4ee347 100644 --- a/mihomo/adapter/adapter.go +++ b/mihomo/adapter/adapter.go @@ -51,26 +51,12 @@ func (p *Proxy) AliveForTestUrl(url string) bool { return p.alive.Load() } -// Dial implements C.Proxy -func (p *Proxy) Dial(metadata *C.Metadata) (C.Conn, error) { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) - defer cancel() - return p.DialContext(ctx, metadata) -} - // DialContext implements C.ProxyAdapter func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) { conn, err := p.ProxyAdapter.DialContext(ctx, metadata) return conn, err } -// DialUDP implements C.ProxyAdapter -func (p *Proxy) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout) - defer cancel() - return p.ListenPacketContext(ctx, metadata) -} - // ListenPacketContext implements C.ProxyAdapter func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata) diff --git a/mihomo/adapter/outbound/base.go b/mihomo/adapter/outbound/base.go index 04a0fa98ae..93f6e14256 100644 --- a/mihomo/adapter/outbound/base.go +++ b/mihomo/adapter/outbound/base.go @@ -263,7 +263,9 @@ func NewConn(c net.Conn, a C.ProxyAdapter) C.Conn { if _, ok := c.(syscall.Conn); !ok { // exclusion system conn like *net.TCPConn c = N.NewDeadlineConn(c) // most conn from outbound can't handle readDeadline correctly } - return &conn{N.NewExtendedConn(c), []string{a.Name()}, a.Addr()} + cc := &conn{N.NewExtendedConn(c), nil, a.Addr()} + cc.AppendToChains(a) + return cc } type packetConn struct { @@ -320,7 +322,9 @@ func newPacketConn(pc net.PacketConn, a ProxyAdapter) C.PacketConn { if _, ok := pc.(syscall.Conn); !ok { // exclusion system conn like *net.UDPConn epc = N.NewDeadlineEnhancePacketConn(epc) // most conn from outbound can't handle readDeadline correctly } - return &packetConn{epc, []string{a.Name()}, a.Name(), utils.NewUUIDV4().String(), a.Addr(), a.ResolveUDP} + cpc := &packetConn{epc, nil, a.Name(), utils.NewUUIDV4().String(), a.Addr(), a.ResolveUDP} + cpc.AppendToChains(a) + return cpc } type AddRef interface { diff --git a/mihomo/adapter/parser.go b/mihomo/adapter/parser.go index 56febe2817..3052ab107f 100644 --- a/mihomo/adapter/parser.go +++ b/mihomo/adapter/parser.go @@ -49,13 +49,7 @@ func ParseProxy(mapping map[string]any) (C.Proxy, error) { } proxy, err = outbound.NewHttp(*httpOption) case "vmess": - vmessOption := &outbound.VmessOption{ - HTTPOpts: outbound.HTTPOptions{ - Method: "GET", - Path: []string{"/"}, - }, - } - + vmessOption := &outbound.VmessOption{} err = decoder.Decode(mapping, vmessOption) if err != nil { break diff --git a/mihomo/common/maphash/comparable_go120.go b/mihomo/common/maphash/comparable_go120.go index 05256d67dd..b4ddad84c6 100644 --- a/mihomo/common/maphash/comparable_go120.go +++ b/mihomo/common/maphash/comparable_go120.go @@ -138,3 +138,5 @@ func escape[T any](x T) T { // ptrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) but as an ideal constant. // It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit). const ptrSize = 4 << (^uintptr(0) >> 63) + +const testComparableAllocations = false diff --git a/mihomo/common/maphash/comparable_go124.go b/mihomo/common/maphash/comparable_go124.go index 3a96edb661..4e5fcc33d0 100644 --- a/mihomo/common/maphash/comparable_go124.go +++ b/mihomo/common/maphash/comparable_go124.go @@ -11,3 +11,5 @@ func Comparable[T comparable](seed Seed, v T) uint64 { func WriteComparable[T comparable](h *Hash, x T) { maphash.WriteComparable(h, x) } + +const testComparableAllocations = true diff --git a/mihomo/common/maphash/maphash_test.go b/mihomo/common/maphash/maphash_test.go index 73887f2715..6cafe9cbee 100644 --- a/mihomo/common/maphash/maphash_test.go +++ b/mihomo/common/maphash/maphash_test.go @@ -423,7 +423,9 @@ func TestWriteComparableNoncommute(t *testing.T) { } func TestComparableAllocations(t *testing.T) { - t.Skip("test broken in old golang version") + if !testComparableAllocations { + t.Skip("test broken in old golang version") + } seed := MakeSeed() x := heapStr(t) allocs := testing.AllocsPerRun(10, func() { diff --git a/mihomo/common/structure/structure.go b/mihomo/common/structure/structure.go index 5bafc178e0..bf79f7dd27 100644 --- a/mihomo/common/structure/structure.go +++ b/mihomo/common/structure/structure.go @@ -53,6 +53,12 @@ func (d *Decoder) Decode(src map[string]any, dst any) error { key, omitKey, found := strings.Cut(tag, ",") omitempty := found && omitKey == "omitempty" + // As a special case, if the field tag is "-", the field is always omitted. + // Note that a field with name "-" can still be generated using the tag "-,". + if key == "-" { + continue + } + value, ok := src[key] if !ok { if d.option.KeyReplacer != nil { diff --git a/mihomo/common/structure/structure_test.go b/mihomo/common/structure/structure_test.go index fcdd853a63..06dffd0f32 100644 --- a/mihomo/common/structure/structure_test.go +++ b/mihomo/common/structure/structure_test.go @@ -288,3 +288,23 @@ func TestStructure_Null(t *testing.T) { assert.Nil(t, err) assert.Equal(t, s.Opt.Bar, "") } + +func TestStructure_Ignore(t *testing.T) { + rawMap := map[string]any{ + "-": "newData", + } + + s := struct { + MustIgnore string `test:"-"` + }{MustIgnore: "oldData"} + + err := decoder.Decode(rawMap, &s) + assert.Nil(t, err) + assert.Equal(t, s.MustIgnore, "oldData") + + // test omitempty + delete(rawMap, "-") + err = decoder.Decode(rawMap, &s) + assert.Nil(t, err) + assert.Equal(t, s.MustIgnore, "oldData") +} diff --git a/mihomo/constant/adapters.go b/mihomo/constant/adapters.go index ab48c47d23..97e9235b5c 100644 --- a/mihomo/constant/adapters.go +++ b/mihomo/constant/adapters.go @@ -139,8 +139,11 @@ type ProxyAdapter interface { // SupportUOT return UDP over TCP support SupportUOT() bool + // SupportWithDialer only for deprecated relay group, the new protocol does not need to be implemented. SupportWithDialer() NetWork + // DialContextWithDialer only for deprecated relay group, the new protocol does not need to be implemented. DialContextWithDialer(ctx context.Context, dialer Dialer, metadata *Metadata) (Conn, error) + // ListenPacketWithDialer only for deprecated relay group, the new protocol does not need to be implemented. ListenPacketWithDialer(ctx context.Context, dialer Dialer, metadata *Metadata) (PacketConn, error) // IsL3Protocol return ProxyAdapter working in L3 (tell dns module not pass the domain to avoid loopback) @@ -178,12 +181,6 @@ type Proxy interface { ExtraDelayHistories() map[string]ProxyState LastDelayForTestUrl(url string) uint16 URLTest(ctx context.Context, url string, expectedStatus utils.IntRanges[uint16]) (uint16, error) - - // Deprecated: use DialContext instead. - Dial(metadata *Metadata) (Conn, error) - - // Deprecated: use DialPacketConn instead. - DialUDP(metadata *Metadata) (PacketConn, error) } // AdapterType is enum of adapter type diff --git a/mihomo/transport/vmess/http.go b/mihomo/transport/vmess/http.go index 3c66fe6b24..94f1fbd351 100644 --- a/mihomo/transport/vmess/http.go +++ b/mihomo/transport/vmess/http.go @@ -3,7 +3,6 @@ package vmess import ( "bufio" "bytes" - "errors" "fmt" "net" "net/http" @@ -55,11 +54,11 @@ func (hc *httpConn) Write(b []byte) (int, error) { return hc.Conn.Write(b) } - if len(hc.cfg.Path) == 0 { - return -1, errors.New("path is empty") + path := "/" + if len(hc.cfg.Path) > 0 { + path = hc.cfg.Path[randv2.IntN(len(hc.cfg.Path))] } - path := hc.cfg.Path[randv2.IntN(len(hc.cfg.Path))] host := hc.cfg.Host if header := hc.cfg.Headers["Host"]; len(header) != 0 { host = header[randv2.IntN(len(header))] diff --git a/openwrt-packages/openlist2/Makefile b/openwrt-packages/openlist2/Makefile index dc47afea99..765ca0ff26 100644 --- a/openwrt-packages/openlist2/Makefile +++ b/openwrt-packages/openlist2/Makefile @@ -7,13 +7,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openlist2 -PKG_VERSION:=4.1.5 -PKG_WEB_VERSION:=4.1.5 +PKG_VERSION:=4.1.6 +PKG_WEB_VERSION:=4.1.6 PKG_RELEASE:=1 PKG_SOURCE:=openlist-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/OpenListTeam/OpenList/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=5ddf3f0b7616248862a8b908cffad9437d19053092bc45e8299ad7c95a3626d2 +PKG_HASH:=9cb26d5a41a9df56a6c937bc37a572ff104e2d5a72c0ec8813273f2e67c0a092 PKG_BUILD_DIR:=$(BUILD_DIR)/OpenList-$(PKG_VERSION) @@ -24,7 +24,7 @@ PKG_MAINTAINER:=sbwml define Download/openlist-frontend FILE:=openlist-frontend-dist-lite-v$(PKG_WEB_VERSION).tar.gz URL:=https://github.com/OpenListTeam/OpenList-Frontend/releases/download/v$(PKG_WEB_VERSION)/ - HASH:=19a079a30fb6658a9122ecce4285abad6c276a9a41b79688b48a601d5fd18896 + HASH:=b57cfeabd160664478086a952d618f1b5ac022852909d38d7a31924b27067308 endef PKG_BUILD_DEPENDS:=golang/host diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/local/http/http_client.rs b/shadowsocks-rust/crates/shadowsocks-service/src/local/http/http_client.rs index 493c52f692..bad671921e 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/local/http/http_client.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/local/http/http_client.rs @@ -53,6 +53,7 @@ pub enum HttpClientError { InvalidHeaderValue(#[from] InvalidHeaderValue), } +#[allow(clippy::large_enum_variant)] #[derive(thiserror::Error, Debug)] enum SendRequestError { #[error("{0}")] diff --git a/shadowsocks-rust/snap/snapcraft.yaml b/shadowsocks-rust/snap/snapcraft.yaml index 489421c9d2..0608103040 100644 --- a/shadowsocks-rust/snap/snapcraft.yaml +++ b/shadowsocks-rust/snap/snapcraft.yaml @@ -39,6 +39,11 @@ apps: install-mode: disable plugs: [network, network-bind, home] + ssservice: + command: bin/ssservice + plugs: [network, network-bind, network-control, home] + aliases: [ssservice] + ssurl: command: bin/ssurl aliases: [ssurl] diff --git a/small/v2ray-geodata/Makefile b/small/v2ray-geodata/Makefile index 304b6522e4..b11a32339b 100644 --- a/small/v2ray-geodata/Makefile +++ b/small/v2ray-geodata/Makefile @@ -30,13 +30,13 @@ define Download/geosite HASH:=434469c8a61ec36d2f3e1ddd6ff65c594bf76ebcb4e472705695b6d4ab51ba47 endef -GEOSITE_IRAN_VER:=202510270042 +GEOSITE_IRAN_VER:=202511030041 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)/ URL_FILE:=iran.dat FILE:=$(GEOSITE_IRAN_FILE) - HASH:=73b5115badba3ec8da2a6ffef2fcd3720ca289453fdddb7ca20c067ce56a3d79 + HASH:=29891a3fe55ad1f42ecfb9448bff8b7e29358f2514185629ea99d7bd39a91a75 endef define Package/v2ray-geodata/template diff --git a/v2rayn/v2rayN/ServiceLib/Common/FileManager.cs b/v2rayn/v2rayN/ServiceLib/Common/FileUtils.cs similarity index 99% rename from v2rayn/v2rayN/ServiceLib/Common/FileManager.cs rename to v2rayn/v2rayN/ServiceLib/Common/FileUtils.cs index 44a9fe82ee..2f86b60a22 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/FileManager.cs +++ b/v2rayn/v2rayN/ServiceLib/Common/FileUtils.cs @@ -3,7 +3,7 @@ using System.IO.Compression; namespace ServiceLib.Common; -public static class FileManager +public static class FileUtils { private static readonly string _tag = "FileManager"; diff --git a/v2rayn/v2rayN/ServiceLib/Common/WindowsJob.cs b/v2rayn/v2rayN/ServiceLib/Common/WindowsJob.cs deleted file mode 100644 index dacf85865a..0000000000 --- a/v2rayn/v2rayN/ServiceLib/Common/WindowsJob.cs +++ /dev/null @@ -1,177 +0,0 @@ -namespace ServiceLib.Common; - /* - * See: - * http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net - */ - - public sealed class WindowsJob : IDisposable - { - private IntPtr handle = IntPtr.Zero; - - public WindowsJob() - { - handle = CreateJobObject(IntPtr.Zero, null); - var extendedInfoPtr = IntPtr.Zero; - var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION - { - LimitFlags = 0x2000 - }; - - var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION - { - BasicLimitInformation = info - }; - - try - { - var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); - extendedInfoPtr = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); - - if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, - (uint)length)) - { - throw new Exception(string.Format("Unable to set information. Error: {0}", - Marshal.GetLastWin32Error())); - } - } - finally - { - if (extendedInfoPtr != IntPtr.Zero) - { - Marshal.FreeHGlobal(extendedInfoPtr); - } - } - } - - public bool AddProcess(IntPtr processHandle) - { - var succ = AssignProcessToJobObject(handle, processHandle); - - if (!succ) - { - Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); - } - - return succ; - } - - public bool AddProcess(int processId) - { - return AddProcess(Process.GetProcessById(processId).Handle); - } - - #region IDisposable - - private bool disposed; - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool disposing) - { - if (disposed) - { - return; - } - disposed = true; - - if (disposing) - { - // no managed objects to free - } - - if (handle != IntPtr.Zero) - { - CloseHandle(handle); - handle = IntPtr.Zero; - } - } - - ~WindowsJob() - { - Dispose(false); - } - - #endregion IDisposable - - #region Interop - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern IntPtr CreateJobObject(IntPtr a, string? lpName); - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength); - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool CloseHandle(IntPtr hObject); - - #endregion Interop - } - - #region Helper classes - - [StructLayout(LayoutKind.Sequential)] - internal struct IO_COUNTERS - { - public ulong ReadOperationCount; - public ulong WriteOperationCount; - public ulong OtherOperationCount; - public ulong ReadTransferCount; - public ulong WriteTransferCount; - public ulong OtherTransferCount; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION - { - public long PerProcessUserTimeLimit; - public long PerJobUserTimeLimit; - public uint LimitFlags; - public UIntPtr MinimumWorkingSetSize; - public UIntPtr MaximumWorkingSetSize; - public uint ActiveProcessLimit; - public UIntPtr Affinity; - public uint PriorityClass; - public uint SchedulingClass; - } - - [StructLayout(LayoutKind.Sequential)] - public struct SECURITY_ATTRIBUTES - { - public uint nLength; - public IntPtr lpSecurityDescriptor; - public int bInheritHandle; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION - { - public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; - public IO_COUNTERS IoInfo; - public UIntPtr ProcessMemoryLimit; - public UIntPtr JobMemoryLimit; - public UIntPtr PeakProcessMemoryUsed; - public UIntPtr PeakJobMemoryUsed; - } - - public enum JobObjectInfoType - { - AssociateCompletionPortInformation = 7, - BasicLimitInformation = 2, - BasicUIRestrictions = 4, - EndOfJobTimeInformation = 6, - ExtendedLimitInformation = 9, - SecurityLimitInformation = 5, - GroupInformation = 11 - } - - #endregion Helper classes - diff --git a/v2rayn/v2rayN/ServiceLib/Handler/ConnectionHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/ConnectionHandler.cs index ae3268ea96..05825d934d 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/ConnectionHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/ConnectionHandler.cs @@ -6,7 +6,7 @@ public static class ConnectionHandler public static async Task RunAvailabilityCheck() { - var time = await GetRealPingTime(); + var time = await GetRealPingTimeInfo(); var ip = time > 0 ? await GetIPInfo() ?? Global.None : Global.None; return string.Format(ResUI.TestMeOutput, time, ip); @@ -39,7 +39,7 @@ public static class ConnectionHandler return $"({country ?? "unknown"}) {ip}"; } - private static async Task GetRealPingTime() + private static async Task GetRealPingTimeInfo() { var responseTime = -1; try @@ -50,7 +50,7 @@ public static class ConnectionHandler for (var i = 0; i < 2; i++) { - responseTime = await HttpClientHelper.Instance.GetRealPingTime(url, webProxy, 10); + responseTime = await GetRealPingTime(url, webProxy, 10); if (responseTime > 0) { break; @@ -65,4 +65,34 @@ public static class ConnectionHandler } return responseTime; } + + public static async Task GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout) + { + var responseTime = -1; + try + { + using var cts = new CancellationTokenSource(); + cts.CancelAfter(TimeSpan.FromSeconds(downloadTimeout)); + using var client = new HttpClient(new SocketsHttpHandler() + { + Proxy = webProxy, + UseProxy = webProxy != null + }); + + List oneTime = new(); + for (var i = 0; i < 2; i++) + { + var timer = Stopwatch.StartNew(); + await client.GetAsync(url, cts.Token).ConfigureAwait(false); + timer.Stop(); + oneTime.Add((int)timer.Elapsed.TotalMilliseconds); + await Task.Delay(100); + } + responseTime = oneTime.Where(x => x > 0).OrderBy(x => x).FirstOrDefault(); + } + catch + { + } + return responseTime; + } } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingLinux.cs b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingLinux.cs index 828c2102ff..9cac0018e0 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingLinux.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingLinux.cs @@ -18,7 +18,7 @@ public static class ProxySettingLinux private static async Task ExecCmd(List args) { - var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false); + var fileName = await FileUtils.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false); await Utils.GetCliWrapOutput(fileName, args); } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs index 85d9b821b8..88baa5a6f4 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs @@ -23,7 +23,7 @@ public static class ProxySettingOSX private static async Task ExecCmd(List args) { - var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false); + var fileName = await FileUtils.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false); await Utils.GetCliWrapOutput(fileName, args); } diff --git a/v2rayn/v2rayN/ServiceLib/Helper/HttpClientHelper.cs b/v2rayn/v2rayN/ServiceLib/Helper/HttpClientHelper.cs index cd971a898a..0c9bd47078 100644 --- a/v2rayn/v2rayN/ServiceLib/Helper/HttpClientHelper.cs +++ b/v2rayn/v2rayN/ServiceLib/Helper/HttpClientHelper.cs @@ -48,15 +48,7 @@ public class HttpClientHelper } return await httpClient.GetStringAsync(url); } - - public async Task GetAsync(HttpClient client, string url, CancellationToken token = default) - { - if (url.IsNullOrEmpty()) - { - return null; - } - return await client.GetStringAsync(url, token); - } + public async Task PutAsync(string url, Dictionary headers) { @@ -81,155 +73,5 @@ public class HttpClientHelper await httpClient.DeleteAsync(url); } - public static async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress? progress, CancellationToken token = default) - { - ArgumentNullException.ThrowIfNull(url); - ArgumentNullException.ThrowIfNull(fileName); - if (File.Exists(fileName)) - { - File.Delete(fileName); - } - - using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); - - if (!response.IsSuccessStatusCode) - { - throw new Exception(response.StatusCode.ToString()); - } - - var total = response.Content.Headers.ContentLength ?? -1L; - var canReportProgress = total != -1 && progress != null; - - await using var stream = await response.Content.ReadAsStreamAsync(token); - await using var file = File.Create(fileName); - var totalRead = 0L; - var buffer = new byte[1024 * 1024]; - var progressPercentage = 0; - - while (true) - { - token.ThrowIfCancellationRequested(); - - var read = await stream.ReadAsync(buffer, token); - totalRead += read; - - if (read == 0) - { - break; - } - await file.WriteAsync(buffer.AsMemory(0, read), token); - - if (canReportProgress) - { - var percent = (int)(100.0 * totalRead / total); - //if (progressPercentage != percent && percent % 10 == 0) - { - progressPercentage = percent; - progress?.Report(percent); - } - } - } - if (canReportProgress) - { - progress?.Report(101); - } - } - - public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token = default) - { - if (url.IsNullOrEmpty()) - { - throw new ArgumentNullException(nameof(url)); - } - - var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); - - if (!response.IsSuccessStatusCode) - { - throw new Exception(response.StatusCode.ToString()); - } - - //var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L; - //var canReportProgress = total != -1 && progress != null; - - await using var stream = await response.Content.ReadAsStreamAsync(token); - var totalRead = 0L; - var buffer = new byte[1024 * 64]; - var isMoreToRead = true; - var progressSpeed = string.Empty; - var totalDatetime = DateTime.Now; - var totalSecond = 0; - - do - { - if (token.IsCancellationRequested) - { - if (totalRead > 0) - { - return; - } - else - { - token.ThrowIfCancellationRequested(); - } - } - - var read = await stream.ReadAsync(buffer, token); - - if (read == 0) - { - isMoreToRead = false; - } - else - { - var data = new byte[read]; - buffer.ToList().CopyTo(0, data, 0, read); - - totalRead += read; - - var ts = DateTime.Now - totalDatetime; - if (progress != null && ts.Seconds > totalSecond) - { - totalSecond = ts.Seconds; - var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0"); - if (progressSpeed != speed) - { - progressSpeed = speed; - progress.Report(speed); - } - } - } - } while (isMoreToRead); - } - - public async Task GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout) - { - var responseTime = -1; - try - { - using var cts = new CancellationTokenSource(); - cts.CancelAfter(TimeSpan.FromSeconds(downloadTimeout)); - using var client = new HttpClient(new SocketsHttpHandler() - { - Proxy = webProxy, - UseProxy = webProxy != null - }); - - List oneTime = new(); - for (var i = 0; i < 2; i++) - { - var timer = Stopwatch.StartNew(); - await client.GetAsync(url, cts.Token).ConfigureAwait(false); - timer.Stop(); - oneTime.Add((int)timer.Elapsed.TotalMilliseconds); - await Task.Delay(100); - } - responseTime = oneTime.Where(x => x > 0).OrderBy(x => x).FirstOrDefault(); - } - catch //(Exception ex) - { - //Utile.SaveLog(ex.Message, ex); - } - return responseTime; - } + } diff --git a/v2rayn/v2rayN/ServiceLib/Manager/CoreAdminManager.cs b/v2rayn/v2rayN/ServiceLib/Manager/CoreAdminManager.cs index dbd19d38c7..6c54e1e1f3 100644 --- a/v2rayn/v2rayN/ServiceLib/Manager/CoreAdminManager.cs +++ b/v2rayn/v2rayN/ServiceLib/Manager/CoreAdminManager.cs @@ -35,7 +35,7 @@ public class CoreAdminManager sb.AppendLine("#!/bin/bash"); var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}"; sb.AppendLine($"exec sudo -S -- {cmdLine}"); - var shFilePath = await FileManager.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true); + var shFilePath = await FileUtils.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true); var procService = new ProcessService( fileName: shFilePath, @@ -68,7 +68,7 @@ public class CoreAdminManager try { var shellFileName = Utils.IsOSX() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName; - var shFilePath = await FileManager.CreateLinuxShellFile("kill_as_sudo.sh", EmbedUtils.GetEmbedText(shellFileName), true); + var shFilePath = await FileUtils.CreateLinuxShellFile("kill_as_sudo.sh", EmbedUtils.GetEmbedText(shellFileName), true); if (shFilePath.Contains(' ')) { shFilePath = shFilePath.AppendQuotes(); diff --git a/v2rayn/v2rayN/ServiceLib/Manager/CoreManager.cs b/v2rayn/v2rayN/ServiceLib/Manager/CoreManager.cs index bd01fe5b88..8dbff9e227 100644 --- a/v2rayn/v2rayN/ServiceLib/Manager/CoreManager.cs +++ b/v2rayn/v2rayN/ServiceLib/Manager/CoreManager.cs @@ -8,7 +8,7 @@ public class CoreManager private static readonly Lazy _instance = new(() => new()); public static CoreManager Instance => _instance.Value; private Config _config; - private WindowsJob? _processJob; + private WindowsJobService? _processJob; private ProcessService? _processService; private ProcessService? _processPreService; private bool _linuxSudo = false; @@ -27,7 +27,7 @@ public class CoreManager var toPath = Utils.GetBinPath(""); if (fromPath != toPath) { - FileManager.CopyDirectory(fromPath, toPath, true, false); + FileUtils.CopyDirectory(fromPath, toPath, true, false); } } diff --git a/v2rayn/v2rayN/ServiceLib/Manager/TaskManager.cs b/v2rayn/v2rayN/ServiceLib/Manager/TaskManager.cs index 862afe446f..d1c7315785 100644 --- a/v2rayn/v2rayN/ServiceLib/Manager/TaskManager.cs +++ b/v2rayn/v2rayN/ServiceLib/Manager/TaskManager.cs @@ -56,9 +56,9 @@ public class TaskManager { //Logging.SaveLog("Execute delete expired files"); - FileManager.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1)); - FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1)); - FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1)); + FileUtils.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1)); + FileUtils.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1)); + FileUtils.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1)); try { diff --git a/v2rayn/v2rayN/ServiceLib/Common/SemanticVersion.cs b/v2rayn/v2rayN/ServiceLib/Models/SemanticVersion.cs similarity index 99% rename from v2rayn/v2rayN/ServiceLib/Common/SemanticVersion.cs rename to v2rayn/v2rayN/ServiceLib/Models/SemanticVersion.cs index 64167084a4..78463434b6 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/SemanticVersion.cs +++ b/v2rayn/v2rayN/ServiceLib/Models/SemanticVersion.cs @@ -1,4 +1,4 @@ -namespace ServiceLib.Common; +namespace ServiceLib.Models; public class SemanticVersion { diff --git a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs index 9cffb352e2..4db9d7cbf0 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs @@ -268,10 +268,13 @@ public partial class CoreConfigSingboxService .Select(s => s + "\n-----END CERTIFICATE-----") .Select(s => s.Replace("\r\n", "\n")) .ToList() ?? new(); - tls.certificate = certs.Count > 0 ? certs : null; - tls.insecure = false; + if (certs.Count > 0) + { + tls.certificate = certs; + tls.insecure = false; + } } - else + else if (node.StreamSecurity == Global.StreamSecurityReality) { tls.reality = new Reality4Sbox() { diff --git a/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs b/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs index d41229648f..fe0da3d6e6 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs @@ -71,7 +71,7 @@ public class DownloadService AllowAutoRedirect = false, Proxy = await GetWebProxy(blProxy) }; - HttpClient client = new(webRequestHandler); + var client = new HttpClient(webRequestHandler); var response = await client.GetAsync(url); if (response.StatusCode == HttpStatusCode.Redirect && response.Headers.Location is not null) @@ -156,7 +156,7 @@ public class DownloadService } using var cts = new CancellationTokenSource(); - var result = await HttpClientHelper.Instance.GetAsync(client, url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); + var result = await client.GetStringAsync(url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); return result; } catch (Exception ex) diff --git a/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs b/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs index 3cb5c2b6bf..600ba4d1d7 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs @@ -272,7 +272,7 @@ public class SpeedtestService(Config config, Func updateF private async Task DoRealPing(ServerTestItem it) { var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}"); - var responseTime = await HttpClientHelper.Instance.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10); + var responseTime = await ConnectionHandler.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10); ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime); await UpdateFunc(it.IndexId, responseTime.ToString()); diff --git a/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs index f14f0a706a..b5129fc7f3 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs @@ -1,18 +1,12 @@ namespace ServiceLib.Services; -public class UpdateService +public class UpdateService(Config config, Func updateFunc) { - private readonly Config? _config; - private readonly Func? _updateFunc; + private readonly Config? _config = config; + private readonly Func? _updateFunc = updateFunc; private readonly int _timeout = 30; private static readonly string _tag = "UpdateService"; - public UpdateService(Config config, Func updateFunc) - { - _config = config; - _updateFunc = updateFunc; - } - public async Task CheckUpdateGuiN(bool preRelease) { var url = string.Empty; diff --git a/v2rayn/v2rayN/ServiceLib/Services/WindowsJobService.cs b/v2rayn/v2rayN/ServiceLib/Services/WindowsJobService.cs new file mode 100644 index 0000000000..ffd4a36a82 --- /dev/null +++ b/v2rayn/v2rayN/ServiceLib/Services/WindowsJobService.cs @@ -0,0 +1,171 @@ +namespace ServiceLib.Services; + +/// +/// http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net +/// +public sealed class WindowsJobService : IDisposable +{ + private nint handle = nint.Zero; + + public WindowsJobService() + { + handle = CreateJobObject(nint.Zero, null); + var extendedInfoPtr = nint.Zero; + var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION + { + LimitFlags = 0x2000 + }; + + var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION + { + BasicLimitInformation = info + }; + + try + { + var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); + extendedInfoPtr = Marshal.AllocHGlobal(length); + Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); + + if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, + (uint)length)) + { + throw new Exception(string.Format("Unable to set information. Error: {0}", + Marshal.GetLastWin32Error())); + } + } + finally + { + if (extendedInfoPtr != nint.Zero) + { + Marshal.FreeHGlobal(extendedInfoPtr); + } + } + } + + public bool AddProcess(nint processHandle) + { + var succ = AssignProcessToJobObject(handle, processHandle); + + if (!succ) + { + Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); + } + + return succ; + } + + public bool AddProcess(int processId) + { + return AddProcess(Process.GetProcessById(processId).Handle); + } + + #region IDisposable + + private bool disposed; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposed) + { + return; + } + disposed = true; + + if (disposing) + { + // no managed objects to free + } + + if (handle != nint.Zero) + { + CloseHandle(handle); + handle = nint.Zero; + } + } + + ~WindowsJobService() + { + Dispose(false); + } + + #endregion IDisposable + + #region Interop + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + private static extern nint CreateJobObject(nint a, string? lpName); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool SetInformationJobObject(nint hJob, JobObjectInfoType infoType, nint lpJobObjectInfo, uint cbJobObjectInfoLength); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool AssignProcessToJobObject(nint job, nint process); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool CloseHandle(nint hObject); + + #endregion Interop +} + +[StructLayout(LayoutKind.Sequential)] +internal struct IO_COUNTERS +{ + public ulong ReadOperationCount; + public ulong WriteOperationCount; + public ulong OtherOperationCount; + public ulong ReadTransferCount; + public ulong WriteTransferCount; + public ulong OtherTransferCount; +} + +[StructLayout(LayoutKind.Sequential)] +internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION +{ + public long PerProcessUserTimeLimit; + public long PerJobUserTimeLimit; + public uint LimitFlags; + public nuint MinimumWorkingSetSize; + public nuint MaximumWorkingSetSize; + public uint ActiveProcessLimit; + public nuint Affinity; + public uint PriorityClass; + public uint SchedulingClass; +} + +[StructLayout(LayoutKind.Sequential)] +public struct SECURITY_ATTRIBUTES +{ + public uint nLength; + public nint lpSecurityDescriptor; + public int bInheritHandle; +} + +[StructLayout(LayoutKind.Sequential)] +internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION +{ + public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; + public IO_COUNTERS IoInfo; + public nuint ProcessMemoryLimit; + public nuint JobMemoryLimit; + public nuint PeakProcessMemoryUsed; + public nuint PeakJobMemoryUsed; +} + +public enum JobObjectInfoType +{ + AssociateCompletionPortInformation = 7, + BasicLimitInformation = 2, + BasicUIRestrictions = 4, + EndOfJobTimeInformation = 6, + ExtendedLimitInformation = 9, + SecurityLimitInformation = 5, + GroupInformation = 11 +} diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs index c0eae75f0d..dbe3b24db6 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs @@ -119,7 +119,7 @@ public class BackupAndRestoreViewModel : MyReactiveObject return; } //check - var lstFiles = FileManager.GetFilesFromZip(fileName); + var lstFiles = FileUtils.GetFilesFromZip(fileName); if (lstFiles is null || !lstFiles.Any(t => t.Contains(_guiConfigs))) { DisplayOperationMsg(ResUI.LocalRestoreInvalidZipTips); @@ -135,7 +135,7 @@ public class BackupAndRestoreViewModel : MyReactiveObject await SQLiteHelper.Instance.DisposeDbConnectionAsync(); var toPath = Utils.GetConfigPath(); - FileManager.ZipExtractToFile(fileName, toPath, ""); + FileUtils.ZipExtractToFile(fileName, toPath, ""); if (Utils.IsWindows()) { @@ -167,8 +167,8 @@ public class BackupAndRestoreViewModel : MyReactiveObject var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}"); var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs); - FileManager.CopyDirectory(configDir, configDirTemp, false, true, ""); - var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName); + FileUtils.CopyDirectory(configDir, configDirTemp, false, true, ""); + var ret = FileUtils.CreateFromDirectory(configDirZipTemp, fileName); Directory.Delete(configDirZipTemp, true); return await Task.FromResult(ret); } diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs index d5a1b0c6d7..7bcb36ea1d 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs @@ -271,24 +271,24 @@ public class CheckUpdateViewModel : MyReactiveObject if (fileName.Contains(".tar.gz")) { - FileManager.DecompressTarFile(fileName, toPath); + FileUtils.DecompressTarFile(fileName, toPath); var dir = new DirectoryInfo(toPath); if (dir.Exists) { foreach (var subDir in dir.GetDirectories()) { - FileManager.CopyDirectory(subDir.FullName, toPath, false, true); + FileUtils.CopyDirectory(subDir.FullName, toPath, false, true); subDir.Delete(true); } } } else if (fileName.Contains(".gz")) { - FileManager.DecompressFile(fileName, toPath, item.CoreType); + FileUtils.DecompressFile(fileName, toPath, item.CoreType); } else { - FileManager.ZipExtractToFile(fileName, toPath, "geo"); + FileUtils.ZipExtractToFile(fileName, toPath, "geo"); } if (Utils.IsNonWindows()) diff --git a/yt-dlp/yt_dlp/extractor/_extractors.py b/yt-dlp/yt_dlp/extractor/_extractors.py index 2646ed9ac9..8c247908de 100644 --- a/yt-dlp/yt_dlp/extractor/_extractors.py +++ b/yt-dlp/yt_dlp/extractor/_extractors.py @@ -1218,6 +1218,7 @@ from .n1 import ( N1InfoAssetIE, N1InfoIIE, ) +from .nascar import NascarClassicsIE from .nate import ( NateIE, NateProgramIE, diff --git a/yt-dlp/yt_dlp/extractor/nascar.py b/yt-dlp/yt_dlp/extractor/nascar.py new file mode 100644 index 0000000000..b14a3b0aa1 --- /dev/null +++ b/yt-dlp/yt_dlp/extractor/nascar.py @@ -0,0 +1,60 @@ +from .common import InfoExtractor +from ..utils import ( + float_or_none, + parse_iso8601, + url_or_none, +) +from ..utils.traversal import traverse_obj + + +class NascarClassicsIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?classics\.nascar\.com/video/(?P[\w~-]+)' + _TESTS = [{ + 'url': 'https://classics.nascar.com/video/Ka5qGuxzZ~SIvJii7uAC~wszPshklHN', + 'md5': '81d712eccffa7169c328281b8cc28f77', + 'info_dict': { + 'id': 'Ka5qGuxzZ~SIvJii7uAC~wszPshklHN', + 'ext': 'mp4', + 'title': 'Cook Out 400 2023', + 'thumbnail': 'https://va.aws.nascar.com/IMAGES/CUP_2023_22_RICHMOND_THUMB_NCD.jpg', + 'timestamp': 1690732800, + 'upload_date': '20230730', + 'tags': ['2023', 'race #22', 'richmond', 'chris buescher', 'cup'], + 'chapters': 'count:18', + }, + }, { + 'url': 'https://classics.nascar.com/video/UASvPDOwEha~SIvJii7uAC~wszPshklHN', + 'md5': 'a5e8d6ec6005da3857d25ba2df5e7133', + 'info_dict': { + 'id': 'UASvPDOwEha~SIvJii7uAC~wszPshklHN', + 'ext': 'mp4', + 'title': 'I Love New York 355 at the Glen 2017', + 'thumbnail': 'https://va.aws.nascar.com/IMAGES/CUP_2017_22_WATKINSGLEN_THUMB_NCD.jpg', + 'timestamp': 1501995600, + 'upload_date': '20170806', + 'tags': ['watkins glen', 'race #22', '2017', 'martin truex jr.', 'cup'], + 'chapters': 'count:13', + }, + }] + + def _real_extract(self, url): + video_id = self._match_id(url) + webpage = self._download_webpage(url, video_id) + content_data = self._search_nextjs_data( + webpage, video_id)['props']['pageProps']['contentData'] + + return { + 'id': video_id, + 'formats': self._extract_m3u8_formats(content_data['input']['src'], video_id, 'mp4'), + **traverse_obj(content_data, { + 'title': ('input', 'name', {str}), + 'description': ('input', 'description', {str}, filter), + 'thumbnail': ('input', 'thumbnail', {url_or_none}), + 'tags': ('input', 'settings', 'tags', ..., {str}), + 'timestamp': ('input', 'start_time', {parse_iso8601}), + 'chapters': ('overlay', 'data', 'timelines', 0, 'events', lambda _, v: float(v['timestamp']) is not None, { + 'start_time': ('timestamp', {float_or_none}), + 'title': ('name', {str}), + }), + }), + }