diff --git a/.github/update.log b/.github/update.log index 1ab0e59f04..7462871c80 100644 --- a/.github/update.log +++ b/.github/update.log @@ -929,3 +929,4 @@ Update On Wed Feb 26 19:35:34 CET 2025 Update On Thu Feb 27 19:34:57 CET 2025 Update On Fri Feb 28 19:34:20 CET 2025 Update On Sat Mar 1 19:31:26 CET 2025 +Update On Sun Mar 2 19:33:02 CET 2025 diff --git a/clash-meta/transport/anytls/session/client.go b/clash-meta/transport/anytls/session/client.go index b0c9982bac..5e99f13562 100644 --- a/clash-meta/transport/anytls/session/client.go +++ b/clash-meta/transport/anytls/session/client.go @@ -21,10 +21,14 @@ type Client struct { dialOut util.DialOutFunc - sessionCounter atomic.Uint64 + sessionCounter atomic.Uint64 + idleSession *skiplist.SkipList[uint64, *Session] idleSessionLock sync.Mutex + sessions map[uint64]*Session + sessionsLock sync.Mutex + padding *atomic.TypedValue[*padding.PaddingFactory] idleSessionTimeout time.Duration @@ -33,6 +37,7 @@ type Client struct { func NewClient(ctx context.Context, dialOut util.DialOutFunc, _padding *atomic.TypedValue[*padding.PaddingFactory], idleSessionCheckInterval, idleSessionTimeout time.Duration, minIdleSession int) *Client { c := &Client{ + sessions: make(map[uint64]*Session), dialOut: dialOut, padding: _padding, idleSessionTimeout: idleSessionTimeout, @@ -130,15 +135,35 @@ func (c *Client) createSession(ctx context.Context) (*Session, error) { c.idleSessionLock.Lock() c.idleSession.Remove(math.MaxUint64 - session.seq) c.idleSessionLock.Unlock() + + c.sessionsLock.Lock() + delete(c.sessions, session.seq) + c.sessionsLock.Unlock() } + + c.sessionsLock.Lock() + c.sessions[session.seq] = session + c.sessionsLock.Unlock() + session.Run() return session, nil } func (c *Client) Close() error { c.dieCancel() - c.minIdleSession = 0 - go c.idleCleanupExpTime(time.Time{}) + + c.sessionsLock.Lock() + sessionToClose := make([]*Session, 0, len(c.sessions)) + for seq, session := range c.sessions { + sessionToClose = append(sessionToClose, session) + delete(c.sessions, seq) + } + c.sessionsLock.Unlock() + + for _, session := range sessionToClose { + session.Close() + } + return nil } diff --git a/clash-nyanpasu/.github/workflows/ci.yml b/clash-nyanpasu/.github/workflows/ci.yml index ddd70072a9..03785a774b 100644 --- a/clash-nyanpasu/.github/workflows/ci.yml +++ b/clash-nyanpasu/.github/workflows/ci.yml @@ -46,20 +46,27 @@ jobs: libxdo-dev webkit2gtk-driver xvfb - - uses: Swatinem/rust-cache@v2 - with: - workspaces: './backend/' - prefix-key: 'rust-stable' - shared-key: 'ci' - save-if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' }} + - uses: maxim-lobanov/setup-xcode@v1 if: startsWith(matrix.targets.os, 'macos-') with: - xcode-version: '15.0' + xcode-version: 'latest-stable' + - name: Install Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 + + - uses: actions/cache@v4 + name: Cache Rust dependencies + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - uses: pnpm/action-setup@v4 name: Install pnpm @@ -97,6 +104,81 @@ jobs: env: NODE_OPTIONS: '--max_old_space_size=4096' + # TODO: support test cross-platform + build: + name: Build Tauri + strategy: + matrix: + targets: + - os: ubuntu-latest + - os: macos-latest + - os: windows-latest + fail-fast: false + runs-on: ${{ matrix.targets.os }} + needs: lint + steps: + - uses: actions/checkout@v4 + - name: Tauri dependencies + if: startsWith(matrix.targets.os, 'ubuntu-') + run: >- + sudo apt-get update && + sudo apt-get install -y + libgtk-3-dev + libayatana-appindicator3-dev + libwebkit2gtk-4.1-dev + librsvg2-dev + libxdo-dev + webkit2gtk-driver + xvfb + - uses: maxim-lobanov/setup-xcode@v1 + if: startsWith(matrix.targets.os, 'macos-') + with: + xcode-version: 'latest-stable' + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - uses: actions/cache@v4 + name: Cache Rust dependencies + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - uses: pnpm/action-setup@v4 + name: Install pnpm + with: + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - uses: actions/cache@v4 + name: Setup pnpm cache + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install --no-frozen-lockfile + + - name: Prepare sidecar and resources + run: pnpm check + + - name: Build Tauri + run: pnpm tauri build + env: + NODE_OPTIONS: '--max_old_space_size=4096' # 以后完善了新的测试套件后再添加 # test_unit: # name: Unit Test diff --git a/clash-nyanpasu/.github/workflows/deps-build-linux.yaml b/clash-nyanpasu/.github/workflows/deps-build-linux.yaml index 52c8dbcfe2..23ec381b1f 100644 --- a/clash-nyanpasu/.github/workflows/deps-build-linux.yaml +++ b/clash-nyanpasu/.github/workflows/deps-build-linux.yaml @@ -84,12 +84,6 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libwebkit2gtk-4.1-dev libxdo-dev libappindicator3-dev librsvg2-dev patchelf openssl - - uses: Swatinem/rust-cache@v2 - with: - workspaces: './backend/' - prefix-key: 'rust-stable' - key: ubuntu-latest - shared-key: 'release' - name: Install Node latest uses: actions/setup-node@v4 diff --git a/clash-nyanpasu/.github/workflows/deps-build-macos.yaml b/clash-nyanpasu/.github/workflows/deps-build-macos.yaml index 5c458ead9a..fa8c500f93 100644 --- a/clash-nyanpasu/.github/workflows/deps-build-macos.yaml +++ b/clash-nyanpasu/.github/workflows/deps-build-macos.yaml @@ -56,13 +56,6 @@ jobs: rustup install stable --profile minimal --no-self-update rustup default stable - - uses: Swatinem/rust-cache@v2 - with: - workspaces: './backend/' - prefix-key: 'rust-stable' - key: 'macos-latest' - shared-key: 'release' - - name: Install Rust intel target if: ${{ inputs.aarch64 == false }} run: | @@ -127,6 +120,9 @@ jobs: echo "Uploading $file to release" gh release upload ${{ inputs.tag }} "$file" --clobber done + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload to Github Artifact uses: actions/upload-artifact@v4 diff --git a/clash-nyanpasu/.github/workflows/deps-build-windows-nsis.yaml b/clash-nyanpasu/.github/workflows/deps-build-windows-nsis.yaml index 07141c6ad8..bc4905bc28 100644 --- a/clash-nyanpasu/.github/workflows/deps-build-windows-nsis.yaml +++ b/clash-nyanpasu/.github/workflows/deps-build-windows-nsis.yaml @@ -85,13 +85,6 @@ jobs: run: | rustup target add ${{ inputs.arch }}-pc-windows-msvc - - uses: Swatinem/rust-cache@v2 - with: - workspaces: './backend/' - prefix-key: 'rust-stable' - key: windows-latest - shared-key: 'release' - - name: Install Node latest uses: actions/setup-node@v4 with: diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index 29f904d828..9a8ccc2eba 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -1387,13 +1387,17 @@ dependencies = [ "boa_engine", "boa_gc", "boa_parser", + "futures-concurrency", "futures-util", "indoc", "isahc", + "log", "rustc-hash 2.1.1", "smol", + "test-log", "textwrap", "tracing", + "url", ] [[package]] @@ -2143,6 +2147,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "cordyceps" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec10f0a762d93c4498d2e97a333805cb6250d60bead623f71d8034f9a4152ba3" +dependencies = [ + "loom", + "tracing", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -2608,6 +2622,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" +[[package]] +name = "diatomic-waker" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" + [[package]] name = "diff" version = "0.1.13" @@ -3366,6 +3386,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.1.0" @@ -3535,6 +3561,19 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-buffered" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe940397c8b744b9c2c974791c2c08bca2c3242ce0290393249e98f215a00472" +dependencies = [ + "cordyceps", + "diatomic-waker", + "futures-core", + "pin-project-lite", + "spin", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -3545,6 +3584,21 @@ dependencies = [ "futures-sink", ] +[[package]] +name = "futures-concurrency" +version = "7.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eb68017df91f2e477ed4bea586c59eaecaa47ed885a770d0444e21e62572cd2" +dependencies = [ + "fixedbitset 0.5.7", + "futures-buffered", + "futures-core", + "futures-lite 2.6.0", + "pin-project", + "slab", + "smallvec", +] + [[package]] name = "futures-core" version = "0.3.31" @@ -3760,6 +3814,19 @@ dependencies = [ "x11", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows 0.48.0", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -5504,6 +5571,19 @@ version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "loop9" version = "0.1.5" @@ -7390,7 +7470,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ - "fixedbitset", + "fixedbitset 0.4.2", "indexmap 2.7.1", ] @@ -12410,6 +12490,15 @@ dependencies = [ "windows-version", ] +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows" version = "0.52.0" diff --git a/clash-nyanpasu/backend/boa_utils/Cargo.toml b/clash-nyanpasu/backend/boa_utils/Cargo.toml index da4adb39fb..7daf138fd8 100644 --- a/clash-nyanpasu/backend/boa_utils/Cargo.toml +++ b/clash-nyanpasu/backend/boa_utils/Cargo.toml @@ -13,9 +13,13 @@ boa_gc = { version = "0.20" } boa_parser = { version = "0.20" } isahc = "1.7" futures-util = "0.3" +futures-concurrency = "7" smol = "2" tracing = "0.1" +url = "2" +log = "0.4" [dev-dependencies] indoc = "2" textwrap = "0.16" +test-log = "0.2" diff --git a/clash-nyanpasu/backend/boa_utils/src/module/combine.rs b/clash-nyanpasu/backend/boa_utils/src/module/combine.rs new file mode 100644 index 0000000000..2c7cbfac4b --- /dev/null +++ b/clash-nyanpasu/backend/boa_utils/src/module/combine.rs @@ -0,0 +1,73 @@ +use std::rc::Rc; + +use boa_engine::module::ModuleLoader; +use url::Url; + +pub struct CombineModuleLoader { + simple: Rc, + http: Rc, +} + +impl CombineModuleLoader { + pub fn new( + simple: boa_engine::module::SimpleModuleLoader, + http: super::http::HttpModuleLoader, + ) -> Self { + Self { + simple: Rc::new(simple), + http: Rc::new(http), + } + } + + pub fn clone_simple(&self) -> Rc { + self.simple.clone() + } + + pub fn clone_http(&self) -> Rc { + self.http.clone() + } +} + +impl ModuleLoader for CombineModuleLoader { + fn load_imported_module( + &self, + referrer: boa_engine::module::Referrer, + specifier: boa_engine::JsString, + finish_load: Box< + dyn FnOnce(boa_engine::JsResult, &mut boa_engine::Context), + >, + context: &mut boa_engine::Context, + ) { + let specifier_str = specifier.to_std_string_escaped(); + match Url::parse(&specifier_str) { + Ok(url) if url.scheme() == "http" || url.scheme() == "https" => { + self.http + .load_imported_module(referrer, specifier, finish_load, context); + } + _ => { + self.simple + .load_imported_module(referrer, specifier, finish_load, context); + } + } + } + + fn get_module(&self, _specifier: boa_engine::JsString) -> Option { + let specifier_str = _specifier.to_std_string_escaped(); + match Url::parse(&specifier_str) { + Ok(url) if url.scheme() == "http" || url.scheme() == "https" => { + self.http.get_module(_specifier) + } + _ => self.simple.get_module(_specifier), + } + } + + fn register_module(&self, _specifier: boa_engine::JsString, _module: boa_engine::Module) { + let specifier_str = _specifier.to_std_string_escaped(); + match Url::parse(&specifier_str) { + Ok(url) if url.scheme() == "http" || url.scheme() == "https" => { + self.http.register_module(_specifier, _module); + } + _ => self.simple.register_module(_specifier, _module), + } + } +} diff --git a/clash-nyanpasu/backend/boa_utils/src/module/http.rs b/clash-nyanpasu/backend/boa_utils/src/module/http.rs index 02f910d7f3..3dd662819f 100644 --- a/clash-nyanpasu/backend/boa_utils/src/module/http.rs +++ b/clash-nyanpasu/backend/boa_utils/src/module/http.rs @@ -1,4 +1,3 @@ -// Most code is taken from https://github.com/boa-dev/boa/blob/main/examples/src/bin/module_fetch.rs use std::{ cell::{Cell, RefCell}, collections::VecDeque, @@ -40,7 +39,7 @@ impl ModuleLoader for HttpModuleLoader { // Adding some prints to show the non-deterministic nature of the async fetches. // Try to run the example several times to see how sometimes the fetches start in order // but finish in disorder. - tracing::debug!("Fetching `{url}`..."); + log::debug!("fetching `{url}`..."); // This could also retry fetching in case there's an error while requesting the module. let body: Result<_, isahc::Error> = async { let mut response = Request::get(&url) @@ -52,7 +51,7 @@ impl ModuleLoader for HttpModuleLoader { Ok(response.text().await?) } .await; - tracing::debug!("Finished fetching `{url}`"); + log::debug!("finished fetching `{url}`"); // Since the async context cannot take the `context` by ref, we have to continue // parsing inside a new `NativeJob` that will be enqueued into the promise job queue. @@ -93,8 +92,8 @@ impl ModuleLoader for HttpModuleLoader { } } -#[allow(dead_code)] -fn main() -> JsResult<()> { +#[test] +fn test_http_module_loader() -> JsResult<()> { // A simple snippet that imports modules from the web instead of the file system. const SRC: &str = r#" import YAML from 'https://esm.run/yaml@2.3.4'; @@ -184,6 +183,12 @@ pub struct Queue<'a> { jobs: RefCell>, } +impl Default for Queue<'_> { + fn default() -> Self { + Self::new(LocalExecutor::new()) + } +} + impl<'a> Queue<'a> { fn new(executor: LocalExecutor<'a>) -> Self { Self { @@ -194,12 +199,6 @@ impl<'a> Queue<'a> { } } -impl Default for Queue<'_> { - fn default() -> Self { - Self::new(LocalExecutor::new()) - } -} - impl JobQueue for Queue<'_> { fn enqueue_promise_job(&self, job: NativeJob, _context: &mut Context) { self.jobs.borrow_mut().push_back(job); diff --git a/clash-nyanpasu/backend/boa_utils/src/module/mod.rs b/clash-nyanpasu/backend/boa_utils/src/module/mod.rs index 9177d163cb..23917cfdda 100644 --- a/clash-nyanpasu/backend/boa_utils/src/module/mod.rs +++ b/clash-nyanpasu/backend/boa_utils/src/module/mod.rs @@ -1,7 +1,9 @@ +#![allow(dead_code)] use std::{cell::RefCell, collections::HashMap, rc::Rc}; use boa_engine::module::ModuleLoader as BoaModuleLoader; use std::sync::Mutex; +pub mod combine; pub mod http; pub struct ModuleLoader(Vec>, Mutex>); diff --git a/clash-nyanpasu/backend/tauri/src/core/clash/ws.rs b/clash-nyanpasu/backend/tauri/src/core/clash/ws.rs index f1634a03c8..fc595a5dfc 100644 --- a/clash-nyanpasu/backend/tauri/src/core/clash/ws.rs +++ b/clash-nyanpasu/backend/tauri/src/core/clash/ws.rs @@ -274,15 +274,3 @@ impl Drop for ClashConnectionsConnectorInner { } } } - -#[cfg(test)] -mod tests { - use super::*; - - #[tokio::test] - async fn test_connect_clash_server() { - "ws://127.0.0.1:12649:10808/connections" - .into_client_request() - .unwrap(); - } -} diff --git a/clash-nyanpasu/backend/tauri/src/enhance/script/js.rs b/clash-nyanpasu/backend/tauri/src/enhance/script/js.rs index 5e126b8d36..ab91ce1309 100644 --- a/clash-nyanpasu/backend/tauri/src/enhance/script/js.rs +++ b/clash-nyanpasu/backend/tauri/src/enhance/script/js.rs @@ -12,7 +12,7 @@ use boa_engine::{ use boa_utils::{ Console, module::{ - ModuleLoader, + combine::CombineModuleLoader, http::{HttpModuleLoader, Queue}, }, }; @@ -77,12 +77,11 @@ pub struct BoaRunner { impl BoaRunner { pub fn try_new() -> Result { - let simple_loader = Rc::new(SimpleModuleLoader::new(CUSTOM_SCRIPTS_DIR.as_path())?); - let http_loader: Rc = Rc::new(HttpModuleLoader); - let loader = Rc::new(ModuleLoader::from(vec![ - simple_loader.clone() as Rc, - http_loader, - ])); + let loader = Rc::new(CombineModuleLoader::new( + SimpleModuleLoader::new(CUSTOM_SCRIPTS_DIR.as_path())?, + HttpModuleLoader::default(), + )); + let simple_loader = loader.clone_simple(); let queue = Rc::new(Queue::default()); let context = Context::builder() .job_queue(queue) @@ -333,6 +332,7 @@ mod utils { } } +#[cfg(test)] mod test { #[test] fn test_wrap_script_if_not_esm() { @@ -463,7 +463,7 @@ const foreignNameservers = [ }); } - #[test] + #[test_log::test] fn test_process_honey_with_fetch() { use super::{super::runner::Runner, JSRunner}; let runner = JSRunner::try_new().unwrap(); diff --git a/clash-nyanpasu/backend/tauri/src/logging/indexer.rs b/clash-nyanpasu/backend/tauri/src/logging/indexer.rs index a44cd58b28..52c069787a 100644 --- a/clash-nyanpasu/backend/tauri/src/logging/indexer.rs +++ b/clash-nyanpasu/backend/tauri/src/logging/indexer.rs @@ -207,6 +207,7 @@ impl Indexer { .unwrap() .replace(".", "_") .replace(" ", "_") + .replace("-", "__") )) .await .context("failed to create index")?; diff --git a/clash-nyanpasu/backend/tauri/src/utils/candy.rs b/clash-nyanpasu/backend/tauri/src/utils/candy.rs index b56b0695fe..46e9db0fc8 100644 --- a/clash-nyanpasu/backend/tauri/src/utils/candy.rs +++ b/clash-nyanpasu/backend/tauri/src/utils/candy.rs @@ -139,6 +139,5 @@ mod test { .await .unwrap(); println!("{:?}", results); - assert_eq!(results.len(), 5); } } diff --git a/clash-nyanpasu/frontend/interface/package.json b/clash-nyanpasu/frontend/interface/package.json index 91b6a6a538..287081f366 100644 --- a/clash-nyanpasu/frontend/interface/package.json +++ b/clash-nyanpasu/frontend/interface/package.json @@ -11,7 +11,7 @@ "build": "tsc" }, "dependencies": { - "@tanstack/react-query": "5.66.9", + "@tanstack/react-query": "5.66.11", "@tauri-apps/api": "2.2.0", "ahooks": "3.8.4", "dayjs": "1.11.13", diff --git a/clash-nyanpasu/frontend/interface/src/ipc/use-clash-connections.ts b/clash-nyanpasu/frontend/interface/src/ipc/use-clash-connections.ts index 0cfec71fa2..412aea22d4 100644 --- a/clash-nyanpasu/frontend/interface/src/ipc/use-clash-connections.ts +++ b/clash-nyanpasu/frontend/interface/src/ipc/use-clash-connections.ts @@ -50,6 +50,13 @@ export const useClashConnections = () => { const query = useQuery({ queryKey: [CLASH_CONNECTIONS_QUERY_KEY], + queryFn: () => { + return ( + queryClient.getQueryData([ + CLASH_CONNECTIONS_QUERY_KEY, + ]) || [] + ) + }, }) const deleteConnections = useMutation({ diff --git a/clash-nyanpasu/frontend/interface/src/ipc/use-clash-logs.ts b/clash-nyanpasu/frontend/interface/src/ipc/use-clash-logs.ts index ad3d394fb2..7e8f18fa76 100644 --- a/clash-nyanpasu/frontend/interface/src/ipc/use-clash-logs.ts +++ b/clash-nyanpasu/frontend/interface/src/ipc/use-clash-logs.ts @@ -16,6 +16,9 @@ export const useClashLogs = () => { const query = useQuery({ queryKey: [CLASH_LOGS_QUERY_KEY], + queryFn: () => { + return queryClient.getQueryData([CLASH_LOGS_QUERY_KEY]) || [] + }, }) const clean = useMutation({ diff --git a/clash-nyanpasu/frontend/interface/src/ipc/use-clash-memory.ts b/clash-nyanpasu/frontend/interface/src/ipc/use-clash-memory.ts index 140ecf7d0c..06cbffded5 100644 --- a/clash-nyanpasu/frontend/interface/src/ipc/use-clash-memory.ts +++ b/clash-nyanpasu/frontend/interface/src/ipc/use-clash-memory.ts @@ -1,4 +1,4 @@ -import { useQuery } from '@tanstack/react-query' +import { useQuery, useQueryClient } from '@tanstack/react-query' import { CLASH_MEMORY_QUERY_KEY } from './consts' export type ClashMemory = { @@ -7,8 +7,15 @@ export type ClashMemory = { } export const useClashMemory = () => { + const queryClient = useQueryClient() + const query = useQuery({ queryKey: [CLASH_MEMORY_QUERY_KEY], + queryFn: () => { + return ( + queryClient.getQueryData([CLASH_MEMORY_QUERY_KEY]) || [] + ) + }, }) return query diff --git a/clash-nyanpasu/frontend/interface/src/ipc/use-clash-traffic.ts b/clash-nyanpasu/frontend/interface/src/ipc/use-clash-traffic.ts index 372a9f5c65..18c66e092e 100644 --- a/clash-nyanpasu/frontend/interface/src/ipc/use-clash-traffic.ts +++ b/clash-nyanpasu/frontend/interface/src/ipc/use-clash-traffic.ts @@ -1,4 +1,4 @@ -import { useQuery } from '@tanstack/react-query' +import { useQuery, useQueryClient } from '@tanstack/react-query' import { CLASH_TRAAFFIC_QUERY_KEY } from './consts' export type ClashTraffic = { @@ -7,8 +7,16 @@ export type ClashTraffic = { } export const useClashTraffic = () => { + const queryClient = useQueryClient() + const query = useQuery({ queryKey: [CLASH_TRAAFFIC_QUERY_KEY], + queryFn: () => { + return ( + queryClient.getQueryData([CLASH_TRAAFFIC_QUERY_KEY]) || + [] + ) + }, }) return query diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 1b7c720fec..da0db5b512 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -33,7 +33,7 @@ "i18next": "24.2.2", "jotai": "2.12.1", "json-schema": "0.4.0", - "material-react-table": "3.2.0", + "material-react-table": "3.2.1", "monaco-editor": "0.52.2", "mui-color-input": "5.0.1", "react": "19.0.0", @@ -55,7 +55,7 @@ "@emotion/react": "11.14.0", "@iconify/json": "2.2.311", "@monaco-editor/react": "4.7.0", - "@tanstack/react-query": "5.66.9", + "@tanstack/react-query": "5.66.11", "@tanstack/react-router": "1.112.0", "@tanstack/router-devtools": "1.112.0", "@tanstack/router-plugin": "1.112.0", diff --git a/clash-nyanpasu/frontend/nyanpasu/src/components/updater/updater-dialog.tsx b/clash-nyanpasu/frontend/nyanpasu/src/components/updater/updater-dialog.tsx index 55683dddca..b6f247295b 100644 --- a/clash-nyanpasu/frontend/nyanpasu/src/components/updater/updater-dialog.tsx +++ b/clash-nyanpasu/frontend/nyanpasu/src/components/updater/updater-dialog.tsx @@ -3,6 +3,7 @@ import dayjs from 'dayjs' import { useSetAtom } from 'jotai' import { lazy, Suspense, useCallback, useState, useTransition } from 'react' import { useTranslation } from 'react-i18next' +import { IS_NIGHTLY } from '@/consts' import { UpdaterIgnoredAtom } from '@/store/updater' import { formatError } from '@/utils' import { message } from '@/utils/notification' @@ -71,6 +72,10 @@ export default function UpdaterDialog({ }) }) + const releasesPageUrl = IS_NIGHTLY + ? `https://github.com/libnyanpasu/clash-nyanpasu/releases/tag/pre-releases` + : `https://github.com/libnyanpasu/clash-nyanpasu/releases/tag/v${update.version}` + return ( { - openThat( - `https://github.com/libnyanpasu/clash-nyanpasu/releases/tag/v${update.version}`, - ) + openThat(releasesPageUrl) }} > {t('updater.go')} diff --git a/clash-nyanpasu/frontend/nyanpasu/src/consts.ts b/clash-nyanpasu/frontend/nyanpasu/src/consts.ts index 2e07473b0b..70fc80d456 100644 --- a/clash-nyanpasu/frontend/nyanpasu/src/consts.ts +++ b/clash-nyanpasu/frontend/nyanpasu/src/consts.ts @@ -1,3 +1,8 @@ +/* eslint-disable */ +// @ts-nocheck + import { getSystem } from '@nyanpasu/ui' export const OS = getSystem() + +export const IS_NIGHTLY = window.__IS_NIGHTLY__ === true diff --git a/clash-nyanpasu/frontend/nyanpasu/vite.config.ts b/clash-nyanpasu/frontend/nyanpasu/vite.config.ts index 460d534ec1..79e9937fcd 100644 --- a/clash-nyanpasu/frontend/nyanpasu/vite.config.ts +++ b/clash-nyanpasu/frontend/nyanpasu/vite.config.ts @@ -14,6 +14,8 @@ import { TanStackRouterVite } from '@tanstack/router-plugin/vite' import legacy from '@vitejs/plugin-legacy' import react from '@vitejs/plugin-react-swc' +const IS_NIGHTLY = process.env.NIGHTLY?.toLowerCase() === 'true' + const devtools = () => { return { name: 'react-devtools', @@ -26,7 +28,17 @@ const devtools = () => { } } -const IS_NIGHTLY = process.env.NIGHTLY?.toLowerCase() === 'true' +const builtinVars = () => { + return { + name: 'built-in-vars', + transformIndexHtml(html: string) { + return html.replace( + /<\/head>/, + ``, + ) + }, + } +} // https://vitejs.dev/config/ export default defineConfig(({ command, mode }) => { @@ -80,6 +92,7 @@ export default defineConfig(({ command, mode }) => { }, }, }), + builtinVars(), TanStackRouterVite(), svgr(), react({ diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index f144c91967..f126cecafd 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -65,7 +65,7 @@ "@tauri-apps/cli": "2.2.7", "@types/fs-extra": "11.0.4", "@types/lodash-es": "4.17.12", - "@types/node": "22.13.5", + "@types/node": "22.13.8", "@typescript-eslint/eslint-plugin": "8.25.0", "@typescript-eslint/parser": "8.25.0", "autoprefixer": "10.4.20", @@ -106,7 +106,7 @@ "stylelint-scss": "6.11.1", "tailwindcss": "4.0.9", "tsx": "4.19.3", - "typescript": "5.7.3", + "typescript": "5.8.2", "typescript-eslint": "8.25.0" }, "packageManager": "pnpm@10.5.2", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index f853694c84..147a991a2c 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -20,7 +20,7 @@ importers: devDependencies: '@commitlint/cli': specifier: 19.7.1 - version: 19.7.1(@types/node@22.13.5)(typescript@5.7.3) + version: 19.7.1(@types/node@22.13.8)(typescript@5.8.2) '@commitlint/config-conventional': specifier: 19.7.1 version: 19.7.1 @@ -43,14 +43,14 @@ importers: specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: 22.13.5 - version: 22.13.5 + specifier: 22.13.8 + version: 22.13.8 '@typescript-eslint/eslint-plugin': specifier: 8.25.0 - version: 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + version: 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) '@typescript-eslint/parser': specifier: 8.25.0 - version: 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + version: 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) autoprefixer: specifier: 10.4.20 version: 10.4.20(postcss@8.5.3) @@ -71,16 +71,16 @@ importers: version: 10.0.2(eslint@9.21.0(jiti@2.4.2)) eslint-config-standard: specifier: 17.1.0 - version: 17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)))(eslint-plugin-n@17.15.1(eslint@9.21.0(jiti@2.4.2)))(eslint-plugin-promise@7.2.1(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)) + version: 17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)))(eslint-plugin-n@17.15.1(eslint@9.21.0(jiti@2.4.2)))(eslint-plugin-promise@7.2.1(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)) eslint-import-resolver-alias: specifier: 1.1.2 - version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))) + version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))) eslint-plugin-html: specifier: 8.1.2 version: 8.1.2 eslint-plugin-import: specifier: 2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)) + version: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-n: specifier: 17.15.1 version: 17.15.1(eslint@9.21.0(jiti@2.4.2)) @@ -104,13 +104,13 @@ importers: version: 16.0.0 knip: specifier: 5.45.0 - version: 5.45.0(@types/node@22.13.5)(typescript@5.7.3) + version: 5.45.0(@types/node@22.13.8)(typescript@5.8.2) lint-staged: specifier: 15.4.3 version: 15.4.3 neostandard: specifier: 0.12.1 - version: 0.12.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + version: 0.12.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) npm-run-all2: specifier: 7.0.2 version: 7.0.2 @@ -140,25 +140,25 @@ importers: version: 6.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) stylelint: specifier: 16.14.1 - version: 16.14.1(typescript@5.7.3) + version: 16.14.1(typescript@5.8.2) stylelint-config-html: specifier: 1.1.0 - version: 1.1.0(postcss-html@1.8.0)(stylelint@16.14.1(typescript@5.7.3)) + version: 1.1.0(postcss-html@1.8.0)(stylelint@16.14.1(typescript@5.8.2)) stylelint-config-recess-order: specifier: 6.0.0 - version: 6.0.0(stylelint@16.14.1(typescript@5.7.3)) + version: 6.0.0(stylelint@16.14.1(typescript@5.8.2)) stylelint-config-standard: specifier: 37.0.0 - version: 37.0.0(stylelint@16.14.1(typescript@5.7.3)) + version: 37.0.0(stylelint@16.14.1(typescript@5.8.2)) stylelint-declaration-block-no-ignored-properties: specifier: 2.8.0 - version: 2.8.0(stylelint@16.14.1(typescript@5.7.3)) + version: 2.8.0(stylelint@16.14.1(typescript@5.8.2)) stylelint-order: specifier: 6.0.4 - version: 6.0.4(stylelint@16.14.1(typescript@5.7.3)) + version: 6.0.4(stylelint@16.14.1(typescript@5.8.2)) stylelint-scss: specifier: 6.11.1 - version: 6.11.1(stylelint@16.14.1(typescript@5.7.3)) + version: 6.11.1(stylelint@16.14.1(typescript@5.8.2)) tailwindcss: specifier: 4.0.9 version: 4.0.9 @@ -166,17 +166,17 @@ importers: specifier: 4.19.3 version: 4.19.3 typescript: - specifier: 5.7.3 - version: 5.7.3 + specifier: 5.8.2 + version: 5.8.2 typescript-eslint: specifier: 8.25.0 - version: 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + version: 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) frontend/interface: dependencies: '@tanstack/react-query': - specifier: 5.66.9 - version: 5.66.9(react@19.0.0) + specifier: 5.66.11 + version: 5.66.11(react@19.0.0) '@tauri-apps/api': specifier: 2.2.0 version: 2.2.0 @@ -270,7 +270,7 @@ importers: version: 12.4.7(@emotion/is-prop-valid@1.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) i18next: specifier: 24.2.2 - version: 24.2.2(typescript@5.7.3) + version: 24.2.2(typescript@5.8.2) jotai: specifier: 2.12.1 version: 2.12.1(@types/react@19.0.10)(react@19.0.0) @@ -278,8 +278,8 @@ importers: specifier: 0.4.0 version: 0.4.0 material-react-table: - specifier: 3.2.0 - version: 3.2.0(854b71f7a9a071703e7a40c20c22e82e) + specifier: 3.2.1 + version: 3.2.1(854b71f7a9a071703e7a40c20c22e82e) monaco-editor: specifier: 0.52.2 version: 0.52.2 @@ -303,7 +303,7 @@ importers: version: 7.5.0(aa8b041558720f84deefb917c6d05709) react-i18next: specifier: 15.4.1 - version: 15.4.1(i18next@24.2.2(typescript@5.7.3))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 15.4.1(i18next@24.2.2(typescript@5.8.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react-markdown: specifier: 10.0.0 version: 10.0.0(@types/react@19.0.10)(react@19.0.0) @@ -339,8 +339,8 @@ importers: specifier: 4.7.0 version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@tanstack/react-query': - specifier: 5.66.9 - version: 5.66.9(react@19.0.0) + specifier: 5.66.11 + version: 5.66.11(react@19.0.0) '@tanstack/react-router': specifier: 1.112.0 version: 1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -349,7 +349,7 @@ importers: version: 1.112.0(@tanstack/react-router@1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@tanstack/router-plugin': specifier: 1.112.0 - version: 1.112.0(@tanstack/react-router@1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 1.112.0(@tanstack/react-router@1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) '@tauri-apps/plugin-clipboard-manager': specifier: 2.2.1 version: 2.2.1 @@ -385,13 +385,13 @@ importers: version: 13.12.2 '@vitejs/plugin-legacy': specifier: 6.0.2 - version: 6.0.2(terser@5.36.0)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 6.0.2(terser@5.36.0)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) '@vitejs/plugin-react': specifier: 4.3.4 - version: 4.3.4(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 4.3.4(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) '@vitejs/plugin-react-swc': specifier: 3.8.0 - version: 3.8.0(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 3.8.0(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) change-case: specifier: 5.4.4 version: 5.4.4 @@ -424,25 +424,25 @@ importers: version: 19.1.1 unplugin-icons: specifier: 22.1.0 - version: 22.1.0(@svgr/core@8.1.0(typescript@5.7.3)) + version: 22.1.0(@svgr/core@8.1.0(typescript@5.8.2)) validator: specifier: 13.12.0 version: 13.12.0 vite: specifier: 6.2.0 - version: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + version: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) vite-plugin-html: specifier: 3.2.2 - version: 3.2.2(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 3.2.2(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) vite-plugin-sass-dts: specifier: 1.3.30 - version: 1.3.30(postcss@8.5.3)(prettier@3.5.2)(sass-embedded@1.85.1)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 1.3.30(postcss@8.5.3)(prettier@3.5.2)(sass-embedded@1.85.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) vite-plugin-svgr: specifier: 4.3.0 - version: 4.3.0(rollup@4.34.3)(typescript@5.7.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 4.3.0(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.7.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 5.1.4(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) zod: specifier: 3.24.2 version: 3.24.2 @@ -478,7 +478,7 @@ importers: version: 19.0.10 '@vitejs/plugin-react': specifier: 4.3.4 - version: 4.3.4(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 4.3.4(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) ahooks: specifier: 3.8.4 version: 3.8.4(react@19.0.0) @@ -499,7 +499,7 @@ importers: version: 5.0.0(react@19.0.0) react-i18next: specifier: 15.4.1 - version: 15.4.1(i18next@24.2.2(typescript@5.7.3))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 15.4.1(i18next@24.2.2(typescript@5.8.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react-use: specifier: 17.6.0 version: 17.6.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -508,10 +508,10 @@ importers: version: 4.0.9 vite: specifier: 6.2.0 - version: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + version: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.7.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 5.1.4(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) devDependencies: '@emotion/react': specifier: 11.14.0 @@ -533,10 +533,10 @@ importers: version: 3.0.2 typescript-plugin-css-modules: specifier: 5.1.0 - version: 5.1.0(typescript@5.7.3) + version: 5.1.0(typescript@5.8.2) vite-plugin-dts: specifier: 4.5.1 - version: 4.5.1(@types/node@22.13.5)(rollup@4.34.3)(typescript@5.7.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) + version: 4.5.1(@types/node@22.13.8)(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)) scripts: dependencies: @@ -2730,11 +2730,11 @@ packages: resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} - '@tanstack/query-core@5.66.4': - resolution: {integrity: sha512-skM/gzNX4shPkqmdTCSoHtJAPMTtmIJNS0hE+xwTTUVYwezArCT34NMermABmBVUg5Ls5aiUXEDXfqwR1oVkcA==} + '@tanstack/query-core@5.66.11': + resolution: {integrity: sha512-ZEYxgHUcohj3sHkbRaw0gYwFxjY5O6M3IXOYXEun7E1rqNhsP8fOtqjJTKPZpVHcdIdrmX4lzZctT4+pts0OgA==} - '@tanstack/react-query@5.66.9': - resolution: {integrity: sha512-NRI02PHJsP5y2gAuWKP+awamTIBFBSKMnO6UVzi03GTclmHHHInH5UzVgzi5tpu4+FmGfsdT7Umqegobtsp23A==} + '@tanstack/react-query@5.66.11': + resolution: {integrity: sha512-uPDiQbZScWkAeihmZ9gAm3wOBA1TmLB1KCB1fJ1hIiEKq3dTT+ja/aYM7wGUD+XiEsY4sDSE7p8VIz/21L2Dow==} peerDependencies: react: ^18 || ^19 @@ -3122,8 +3122,8 @@ packages: '@types/node@22.10.1': resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} - '@types/node@22.13.5': - resolution: {integrity: sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==} + '@types/node@22.13.8': + resolution: {integrity: sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -5803,8 +5803,8 @@ packages: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} - material-react-table@3.2.0: - resolution: {integrity: sha512-q2xWG1CQ30ji+aCLKX1XrIg3zrfHT/zZ4aR49Vk/oP4+ospCgjlIVcWLapjrPoqAIDNgB9/fRRG7d1se1Z3nUg==} + material-react-table@3.2.1: + resolution: {integrity: sha512-sQtTf7bETpkPN2Hm5BVtz89wrfXCVQguz6XlwMChSnfKFO5QCKAJJC5aSIKnUc3S0AvTz/k/ILi00FnnY1Gixw==} engines: {node: '>=16'} peerDependencies: '@emotion/react': '>=11.13' @@ -7650,6 +7650,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.8.2: + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + engines: {node: '>=14.17'} + hasBin: true + ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} @@ -9000,11 +9005,11 @@ snapshots: '@bufbuild/protobuf@2.2.3': {} - '@commitlint/cli@19.7.1(@types/node@22.13.5)(typescript@5.7.3)': + '@commitlint/cli@19.7.1(@types/node@22.13.8)(typescript@5.8.2)': dependencies: '@commitlint/format': 19.5.0 '@commitlint/lint': 19.7.1 - '@commitlint/load': 19.6.1(@types/node@22.13.5)(typescript@5.7.3) + '@commitlint/load': 19.6.1(@types/node@22.13.8)(typescript@5.8.2) '@commitlint/read': 19.5.0 '@commitlint/types': 19.5.0 tinyexec: 0.3.1 @@ -9051,15 +9056,15 @@ snapshots: '@commitlint/rules': 19.6.0 '@commitlint/types': 19.5.0 - '@commitlint/load@19.6.1(@types/node@22.13.5)(typescript@5.7.3)': + '@commitlint/load@19.6.1(@types/node@22.13.8)(typescript@5.8.2)': dependencies: '@commitlint/config-validator': 19.5.0 '@commitlint/execute-rule': 19.5.0 '@commitlint/resolve-extends': 19.5.0 '@commitlint/types': 19.5.0 chalk: 5.4.1 - cosmiconfig: 9.0.0(typescript@5.7.3) - cosmiconfig-typescript-loader: 6.1.0(@types/node@22.13.5)(cosmiconfig@9.0.0(typescript@5.7.3))(typescript@5.7.3) + cosmiconfig: 9.0.0(typescript@5.8.2) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.13.8)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -9484,23 +9489,23 @@ snapshots: '@material/material-color-utilities@0.3.0': {} - '@microsoft/api-extractor-model@7.30.3(@types/node@22.13.5)': + '@microsoft/api-extractor-model@7.30.3(@types/node@22.13.8)': dependencies: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@22.13.5) + '@rushstack/node-core-library': 5.11.0(@types/node@22.13.8) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.51.0(@types/node@22.13.5)': + '@microsoft/api-extractor@7.51.0(@types/node@22.13.8)': dependencies: - '@microsoft/api-extractor-model': 7.30.3(@types/node@22.13.5) + '@microsoft/api-extractor-model': 7.30.3(@types/node@22.13.8) '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@22.13.5) + '@rushstack/node-core-library': 5.11.0(@types/node@22.13.8) '@rushstack/rig-package': 0.5.3 - '@rushstack/terminal': 0.15.0(@types/node@22.13.5) - '@rushstack/ts-command-line': 4.23.5(@types/node@22.13.5) + '@rushstack/terminal': 0.15.0(@types/node@22.13.8) + '@rushstack/ts-command-line': 4.23.5(@types/node@22.13.8) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.8 @@ -10170,7 +10175,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/node-core-library@5.11.0(@types/node@22.13.5)': + '@rushstack/node-core-library@5.11.0(@types/node@22.13.8)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -10181,23 +10186,23 @@ snapshots: resolve: 1.22.8 semver: 7.5.4 optionalDependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.8 '@rushstack/rig-package@0.5.3': dependencies: resolve: 1.22.8 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.15.0(@types/node@22.13.5)': + '@rushstack/terminal@0.15.0(@types/node@22.13.8)': dependencies: - '@rushstack/node-core-library': 5.11.0(@types/node@22.13.5) + '@rushstack/node-core-library': 5.11.0(@types/node@22.13.8) supports-color: 8.1.1 optionalDependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.8 - '@rushstack/ts-command-line@4.23.5(@types/node@22.13.5)': + '@rushstack/ts-command-line@4.23.5(@types/node@22.13.8)': dependencies: - '@rushstack/terminal': 0.15.0(@types/node@22.13.5) + '@rushstack/terminal': 0.15.0(@types/node@22.13.8) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 @@ -10247,9 +10252,9 @@ snapshots: ignore: 5.3.2 p-map: 4.0.0 - '@stylistic/eslint-plugin@2.11.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@stylistic/eslint-plugin@2.11.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)': dependencies: - '@typescript-eslint/utils': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) eslint: 9.21.0(jiti@2.4.2) eslint-visitor-keys: 4.2.0 espree: 10.3.0 @@ -10303,12 +10308,12 @@ snapshots: '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.26.9) '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.26.9) - '@svgr/core@8.1.0(typescript@5.7.3)': + '@svgr/core@8.1.0(typescript@5.8.2)': dependencies: '@babel/core': 7.26.9 '@svgr/babel-preset': 8.1.0(@babel/core@7.26.9) camelcase: 6.3.0 - cosmiconfig: 8.3.6(typescript@5.7.3) + cosmiconfig: 8.3.6(typescript@5.8.2) snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -10319,11 +10324,11 @@ snapshots: '@babel/types': 7.26.9 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.7.3))': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.8.2))': dependencies: '@babel/core': 7.26.9 '@svgr/babel-preset': 8.1.0(@babel/core@7.26.9) - '@svgr/core': 8.1.0(typescript@5.7.3) + '@svgr/core': 8.1.0(typescript@5.8.2) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: @@ -10453,11 +10458,11 @@ snapshots: dependencies: remove-accents: 0.5.0 - '@tanstack/query-core@5.66.4': {} + '@tanstack/query-core@5.66.11': {} - '@tanstack/react-query@5.66.9(react@19.0.0)': + '@tanstack/react-query@5.66.11(react@19.0.0)': dependencies: - '@tanstack/query-core': 5.66.4 + '@tanstack/query-core': 5.66.11 react: 19.0.0 '@tanstack/react-router@1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': @@ -10514,7 +10519,7 @@ snapshots: optionalDependencies: '@tanstack/react-router': 1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@tanstack/router-plugin@1.112.0(@tanstack/react-router@1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))': + '@tanstack/router-plugin@1.112.0(@tanstack/react-router@1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))': dependencies: '@babel/core': 7.26.9 '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.9) @@ -10535,7 +10540,7 @@ snapshots: zod: 3.24.2 optionalDependencies: '@tanstack/react-router': 1.112.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - supports-color @@ -10688,12 +10693,12 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 22.13.5 + '@types/node': 22.13.8 '@types/responselike': 1.0.3 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.8 '@types/d3-array@3.2.1': {} @@ -10829,7 +10834,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 22.13.5 + '@types/node': 22.13.8 '@types/geojson@7946.0.14': {} @@ -10847,11 +10852,11 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.8 '@types/keyv@3.1.4': dependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.8 '@types/lodash-es@4.17.12': dependencies: @@ -10871,7 +10876,7 @@ snapshots: dependencies: undici-types: 6.20.0 - '@types/node@22.13.5': + '@types/node@22.13.8': dependencies: undici-types: 6.20.0 @@ -10901,7 +10906,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.8 '@types/retry@0.12.2': {} @@ -10921,35 +10926,35 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.8 optional: true - '@typescript-eslint/eslint-plugin@8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/eslint-plugin@8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) '@typescript-eslint/scope-manager': 8.25.0 - '@typescript-eslint/type-utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/type-utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) + '@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) '@typescript-eslint/visitor-keys': 8.25.0 eslint: 9.21.0(jiti@2.4.2) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)': dependencies: '@typescript-eslint/scope-manager': 8.25.0 '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.8.2) '@typescript-eslint/visitor-keys': 8.25.0 debug: 4.4.0 eslint: 9.21.0(jiti@2.4.2) - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - supports-color @@ -10963,14 +10968,14 @@ snapshots: '@typescript-eslint/types': 8.25.0 '@typescript-eslint/visitor-keys': 8.25.0 - '@typescript-eslint/type-utils@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/type-utils@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.8.2) + '@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) debug: 4.4.0 eslint: 9.21.0(jiti@2.4.2) - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color @@ -10978,7 +10983,7 @@ snapshots: '@typescript-eslint/types@8.25.0': {} - '@typescript-eslint/typescript-estree@8.24.1(typescript@5.7.3)': + '@typescript-eslint/typescript-estree@8.24.1(typescript@5.8.2)': dependencies: '@typescript-eslint/types': 8.24.1 '@typescript-eslint/visitor-keys': 8.24.1 @@ -10987,12 +10992,12 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.1 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.25.0(typescript@5.7.3)': + '@typescript-eslint/typescript-estree@8.25.0(typescript@5.8.2)': dependencies: '@typescript-eslint/types': 8.25.0 '@typescript-eslint/visitor-keys': 8.25.0 @@ -11001,30 +11006,30 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.1 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/utils@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0(jiti@2.4.2)) '@typescript-eslint/scope-manager': 8.24.1 '@typescript-eslint/types': 8.24.1 - '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.8.2) eslint: 9.21.0(jiti@2.4.2) - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/utils@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0(jiti@2.4.2)) '@typescript-eslint/scope-manager': 8.25.0 '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.8.2) eslint: 9.21.0(jiti@2.4.2) - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - supports-color @@ -11040,7 +11045,7 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-legacy@6.0.2(terser@5.36.0)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))': + '@vitejs/plugin-legacy@6.0.2(terser@5.36.0)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))': dependencies: '@babel/core': 7.26.9 '@babel/preset-env': 7.26.9(@babel/core@7.26.9) @@ -11051,25 +11056,25 @@ snapshots: regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.36.0 - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react-swc@3.8.0(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))': + '@vitejs/plugin-react-swc@3.8.0(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))': dependencies: '@swc/core': 1.10.15 - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@4.3.4(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))': + '@vitejs/plugin-react@4.3.4(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - supports-color @@ -11103,7 +11108,7 @@ snapshots: de-indent: 1.0.2 he: 1.2.0 - '@vue/language-core@2.2.4(typescript@5.7.3)': + '@vue/language-core@2.2.4(typescript@5.8.2)': dependencies: '@volar/language-core': 2.4.11 '@vue/compiler-dom': 3.5.13 @@ -11114,7 +11119,7 @@ snapshots: muggle-string: 0.4.1 path-browserify: 1.0.1 optionalDependencies: - typescript: 5.7.3 + typescript: 5.8.2 '@vue/shared@3.5.13': {} @@ -11712,12 +11717,12 @@ snapshots: core-js@3.40.0: {} - cosmiconfig-typescript-loader@6.1.0(@types/node@22.13.5)(cosmiconfig@9.0.0(typescript@5.7.3))(typescript@5.7.3): + cosmiconfig-typescript-loader@6.1.0(@types/node@22.13.8)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2): dependencies: - '@types/node': 22.13.5 - cosmiconfig: 9.0.0(typescript@5.7.3) + '@types/node': 22.13.8 + cosmiconfig: 9.0.0(typescript@5.8.2) jiti: 2.4.2 - typescript: 5.7.3 + typescript: 5.8.2 cosmiconfig@7.1.0: dependencies: @@ -11727,23 +11732,23 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.7.3): + cosmiconfig@8.3.6(typescript@5.8.2): dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.7.3 + typescript: 5.8.2 - cosmiconfig@9.0.0(typescript@5.7.3): + cosmiconfig@9.0.0(typescript@5.8.2): dependencies: env-paths: 2.2.1 import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.7.3 + typescript: 5.8.2 country-code-emoji@2.3.0: {} @@ -12447,16 +12452,16 @@ snapshots: dependencies: eslint: 9.21.0(jiti@2.4.2) - eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)))(eslint-plugin-n@17.15.1(eslint@9.21.0(jiti@2.4.2)))(eslint-plugin-promise@7.2.1(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)): + eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)))(eslint-plugin-n@17.15.1(eslint@9.21.0(jiti@2.4.2)))(eslint-plugin-promise@7.2.1(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)): dependencies: eslint: 9.21.0(jiti@2.4.2) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-n: 17.15.1(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-promise: 7.2.1(eslint@9.21.0(jiti@2.4.2)) - eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))): + eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))): dependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)) eslint-import-resolver-node@0.3.9: dependencies: @@ -12466,7 +12471,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.7.0(eslint-plugin-import-x@4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)): + eslint-import-resolver-typescript@3.7.0(eslint-plugin-import-x@4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 @@ -12478,16 +12483,16 @@ snapshots: is-glob: 4.0.3 stable-hash: 0.0.4 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)) - eslint-plugin-import-x: 4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)) + eslint-plugin-import-x: 4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0(jiti@2.4.2)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0(jiti@2.4.2)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) eslint: 9.21.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: @@ -12504,10 +12509,10 @@ snapshots: dependencies: htmlparser2: 9.1.0 - eslint-plugin-import-x@4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3): + eslint-plugin-import-x@4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2): dependencies: '@typescript-eslint/scope-manager': 8.24.1 - '@typescript-eslint/utils': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) debug: 4.4.0 doctrine: 3.0.0 eslint: 9.21.0(jiti@2.4.2) @@ -12522,7 +12527,7 @@ snapshots: - supports-color - typescript - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -12533,7 +12538,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.21.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0(jiti@2.4.2)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0(jiti@2.4.2)) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -12545,7 +12550,7 @@ snapshots: string.prototype.trimend: 1.0.8 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -13248,11 +13253,11 @@ snapshots: hyphenate-style-name@1.1.0: {} - i18next@24.2.2(typescript@5.7.3): + i18next@24.2.2(typescript@5.8.2): dependencies: '@babel/runtime': 7.26.0 optionalDependencies: - typescript: 5.7.3 + typescript: 5.8.2 iconv-lite@0.6.3: dependencies: @@ -13694,11 +13699,11 @@ snapshots: kind-of@6.0.3: {} - knip@5.45.0(@types/node@22.13.5)(typescript@5.7.3): + knip@5.45.0(@types/node@22.13.8)(typescript@5.8.2): dependencies: '@nodelib/fs.walk': 3.0.1 '@snyk/github-codeowners': 1.1.0 - '@types/node': 22.13.5 + '@types/node': 22.13.8 easy-table: 1.2.0 enhanced-resolve: 5.18.1 fast-glob: 3.3.3 @@ -13711,7 +13716,7 @@ snapshots: smol-toml: 1.3.1 strip-json-comments: 5.0.1 summary: 2.1.0 - typescript: 5.7.3 + typescript: 5.8.2 zod: 3.24.2 zod-validation-error: 3.3.1(zod@3.24.2) @@ -13916,7 +13921,7 @@ snapshots: escape-string-regexp: 4.0.0 optional: true - material-react-table@3.2.0(854b71f7a9a071703e7a40c20c22e82e): + material-react-table@3.2.1(854b71f7a9a071703e7a40c20c22e82e): dependencies: '@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0) '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) @@ -14309,20 +14314,20 @@ snapshots: sax: 1.3.0 optional: true - neostandard@0.12.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3): + neostandard@0.12.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2): dependencies: '@humanwhocodes/gitignore-to-minimatch': 1.0.2 - '@stylistic/eslint-plugin': 2.11.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@stylistic/eslint-plugin': 2.11.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) eslint: 9.21.0(jiti@2.4.2) - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import-x@4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)) - eslint-plugin-import-x: 4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import-x@4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)) + eslint-plugin-import-x: 4.5.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) eslint-plugin-n: 17.15.1(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-promise: 7.2.1(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-react: 7.37.4(eslint@9.21.0(jiti@2.4.2)) find-up: 5.0.0 globals: 15.15.0 peowly: 1.3.2 - typescript-eslint: 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + typescript-eslint: 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) transitivePeerDependencies: - eslint-plugin-import - supports-color @@ -14858,11 +14863,11 @@ snapshots: dependencies: react: 19.0.0 - react-i18next@15.4.1(i18next@24.2.2(typescript@5.7.3))(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + react-i18next@15.4.1(i18next@24.2.2(typescript@5.8.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@babel/runtime': 7.26.0 html-parse-stringify: 3.0.1 - i18next: 24.2.2(typescript@5.7.3) + i18next: 24.2.2(typescript@5.8.2) react: 19.0.0 optionalDependencies: react-dom: 19.0.0(react@19.0.0) @@ -15589,36 +15594,36 @@ snapshots: dependencies: inline-style-parser: 0.2.3 - stylelint-config-html@1.1.0(postcss-html@1.8.0)(stylelint@16.14.1(typescript@5.7.3)): + stylelint-config-html@1.1.0(postcss-html@1.8.0)(stylelint@16.14.1(typescript@5.8.2)): dependencies: postcss-html: 1.8.0 - stylelint: 16.14.1(typescript@5.7.3) + stylelint: 16.14.1(typescript@5.8.2) - stylelint-config-recess-order@6.0.0(stylelint@16.14.1(typescript@5.7.3)): + stylelint-config-recess-order@6.0.0(stylelint@16.14.1(typescript@5.8.2)): dependencies: - stylelint: 16.14.1(typescript@5.7.3) - stylelint-order: 6.0.4(stylelint@16.14.1(typescript@5.7.3)) + stylelint: 16.14.1(typescript@5.8.2) + stylelint-order: 6.0.4(stylelint@16.14.1(typescript@5.8.2)) - stylelint-config-recommended@15.0.0(stylelint@16.14.1(typescript@5.7.3)): + stylelint-config-recommended@15.0.0(stylelint@16.14.1(typescript@5.8.2)): dependencies: - stylelint: 16.14.1(typescript@5.7.3) + stylelint: 16.14.1(typescript@5.8.2) - stylelint-config-standard@37.0.0(stylelint@16.14.1(typescript@5.7.3)): + stylelint-config-standard@37.0.0(stylelint@16.14.1(typescript@5.8.2)): dependencies: - stylelint: 16.14.1(typescript@5.7.3) - stylelint-config-recommended: 15.0.0(stylelint@16.14.1(typescript@5.7.3)) + stylelint: 16.14.1(typescript@5.8.2) + stylelint-config-recommended: 15.0.0(stylelint@16.14.1(typescript@5.8.2)) - stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.14.1(typescript@5.7.3)): + stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.14.1(typescript@5.8.2)): dependencies: - stylelint: 16.14.1(typescript@5.7.3) + stylelint: 16.14.1(typescript@5.8.2) - stylelint-order@6.0.4(stylelint@16.14.1(typescript@5.7.3)): + stylelint-order@6.0.4(stylelint@16.14.1(typescript@5.8.2)): dependencies: postcss: 8.5.3 postcss-sorting: 8.0.2(postcss@8.5.3) - stylelint: 16.14.1(typescript@5.7.3) + stylelint: 16.14.1(typescript@5.8.2) - stylelint-scss@6.11.1(stylelint@16.14.1(typescript@5.7.3)): + stylelint-scss@6.11.1(stylelint@16.14.1(typescript@5.8.2)): dependencies: css-tree: 3.1.0 is-plain-object: 5.0.0 @@ -15628,9 +15633,9 @@ snapshots: postcss-resolve-nested-selector: 0.1.6 postcss-selector-parser: 7.1.0 postcss-value-parser: 4.2.0 - stylelint: 16.14.1(typescript@5.7.3) + stylelint: 16.14.1(typescript@5.8.2) - stylelint@16.14.1(typescript@5.7.3): + stylelint@16.14.1(typescript@5.8.2): dependencies: '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) '@csstools/css-tokenizer': 3.0.3 @@ -15639,7 +15644,7 @@ snapshots: '@dual-bundle/import-meta-resolve': 4.1.0 balanced-match: 2.0.0 colord: 2.9.3 - cosmiconfig: 9.0.0(typescript@5.7.3) + cosmiconfig: 9.0.0(typescript@5.8.2) css-functions-list: 3.2.3 css-tree: 3.1.0 debug: 4.4.0 @@ -15832,17 +15837,17 @@ snapshots: trough@2.2.0: {} - ts-api-utils@2.0.1(typescript@5.7.3): + ts-api-utils@2.0.1(typescript@5.8.2): dependencies: - typescript: 5.7.3 + typescript: 5.8.2 ts-custom-error@3.3.1: {} ts-easing@0.2.0: {} - tsconfck@3.0.3(typescript@5.7.3): + tsconfck@3.0.3(typescript@5.8.2): optionalDependencies: - typescript: 5.7.3 + typescript: 5.8.2 tsconfig-paths@3.15.0: dependencies: @@ -15946,17 +15951,17 @@ snapshots: dependencies: is-typedarray: 1.0.0 - typescript-eslint@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3): + typescript-eslint@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/eslint-plugin': 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) + '@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) + '@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2) eslint: 9.21.0(jiti@2.4.2) - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - supports-color - typescript-plugin-css-modules@5.1.0(typescript@5.7.3): + typescript-plugin-css-modules@5.1.0(typescript@5.8.2): dependencies: '@types/postcss-modules-local-by-default': 4.0.2 '@types/postcss-modules-scope': 3.0.4 @@ -15974,13 +15979,15 @@ snapshots: source-map-js: 1.2.1 stylus: 0.62.0 tsconfig-paths: 4.2.0 - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - supports-color - ts-node typescript@5.7.3: {} + typescript@5.8.2: {} + ufo@1.5.4: {} unbox-primitive@1.0.2: @@ -16096,7 +16103,7 @@ snapshots: unplugin: 2.2.0 unplugin-utils: 0.2.4 - unplugin-icons@22.1.0(@svgr/core@8.1.0(typescript@5.7.3)): + unplugin-icons@22.1.0(@svgr/core@8.1.0(typescript@5.8.2)): dependencies: '@antfu/install-pkg': 1.0.0 '@iconify/utils': 2.3.0 @@ -16104,7 +16111,7 @@ snapshots: local-pkg: 1.0.0 unplugin: 2.2.0 optionalDependencies: - '@svgr/core': 8.1.0(typescript@5.7.3) + '@svgr/core': 8.1.0(typescript@5.8.2) transitivePeerDependencies: - supports-color @@ -16199,26 +16206,26 @@ snapshots: - rollup - supports-color - vite-plugin-dts@4.5.1(@types/node@22.13.5)(rollup@4.34.3)(typescript@5.7.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): + vite-plugin-dts@4.5.1(@types/node@22.13.8)(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): dependencies: - '@microsoft/api-extractor': 7.51.0(@types/node@22.13.5) + '@microsoft/api-extractor': 7.51.0(@types/node@22.13.8) '@rollup/pluginutils': 5.1.4(rollup@4.34.3) '@volar/typescript': 2.4.11 - '@vue/language-core': 2.2.4(typescript@5.7.3) + '@vue/language-core': 2.2.4(typescript@5.8.2) compare-versions: 6.1.1 debug: 4.4.0 kolorist: 1.8.0 local-pkg: 1.0.0 magic-string: 0.30.17 - typescript: 5.7.3 + typescript: 5.8.2 optionalDependencies: - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite-plugin-html@3.2.2(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): + vite-plugin-html@3.2.2(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): dependencies: '@rollup/pluginutils': 4.2.1 colorette: 2.0.20 @@ -16232,45 +16239,45 @@ snapshots: html-minifier-terser: 6.1.0 node-html-parser: 5.4.2 pathe: 0.2.0 - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) - vite-plugin-sass-dts@1.3.30(postcss@8.5.3)(prettier@3.5.2)(sass-embedded@1.85.1)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): + vite-plugin-sass-dts@1.3.30(postcss@8.5.3)(prettier@3.5.2)(sass-embedded@1.85.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): dependencies: postcss: 8.5.3 postcss-js: 4.0.1(postcss@8.5.3) prettier: 3.5.2 sass-embedded: 1.85.1 - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) - vite-plugin-svgr@4.3.0(rollup@4.34.3)(typescript@5.7.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): + vite-plugin-svgr@4.3.0(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): dependencies: '@rollup/pluginutils': 5.1.3(rollup@4.34.3) - '@svgr/core': 8.1.0(typescript@5.7.3) - '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.7.3)) - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + '@svgr/core': 8.1.0(typescript@5.8.2) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.8.2)) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): + vite-tsconfig-paths@5.1.4(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)): dependencies: debug: 4.3.7 globrex: 0.1.2 - tsconfck: 3.0.3(typescript@5.7.3) + tsconfck: 3.0.3(typescript@5.8.2) optionalDependencies: - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - supports-color - typescript - vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0): + vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0): dependencies: esbuild: 0.25.0 postcss: 8.5.3 rollup: 4.34.3 optionalDependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.8 fsevents: 2.3.3 jiti: 2.4.2 less: 4.2.0 diff --git a/clash-nyanpasu/rust-toolchain.toml b/clash-nyanpasu/rust-toolchain.toml index 5d56faf9ae..d9d3e798da 100644 --- a/clash-nyanpasu/rust-toolchain.toml +++ b/clash-nyanpasu/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "nightly" +channel = "nightly-2025-02-25" diff --git a/clash-verge-rev/.github/workflows/alpha.yml b/clash-verge-rev/.github/workflows/alpha.yml index d2add9cf07..c52fe0f558 100644 --- a/clash-verge-rev/.github/workflows/alpha.yml +++ b/clash-verge-rev/.github/workflows/alpha.yml @@ -92,12 +92,6 @@ jobs: tauriScript: pnpm args: --target ${{ matrix.target }} - - name: Portable Bundle - if: matrix.os == 'windows-latest' - run: pnpm portable ${{ matrix.target }} --alpha - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - alpha-for-linux-arm: strategy: fail-fast: false @@ -347,7 +341,7 @@ jobs: - Linux arm64 architecture: arm64.deb/aarch64.rpm - Linux armv7架构: armhf.deb/armhfp.rpm - ### Windows (Win7 用户请查看下面FAQ中的解决方案) + ### Windows (不再支持Win7) #### 正常版本(推荐) - 64位: x64-setup.exe - arm64架构: arm64-setup.exe diff --git a/clash-verge-rev/.github/workflows/label_issue.yml b/clash-verge-rev/.github/workflows/label_issue.yml new file mode 100644 index 0000000000..b6ce0c6a46 --- /dev/null +++ b/clash-verge-rev/.github/workflows/label_issue.yml @@ -0,0 +1,60 @@ +name: Label Issue + +on: + workflow_dispatch: + issues: + types: [opened, edited] + +jobs: + label-issue: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Label issue if it contains "windows" + uses: actions/github-script@v7 + with: + script: | + const { data: issue } = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const labelsToAdd = []; + const existingLabels = issue.labels.map(label => label.name); + const bodyContent = issue.body.toLowerCase(); + + // Check for keywords and add corresponding labels + if (bodyContent.includes('windows')) { + labelsToAdd.push('windows'); + } + if (bodyContent.includes('linux')) { + labelsToAdd.push('linux'); + } + if (bodyContent.includes('macos')) { + labelsToAdd.push('macos'); + } + + if (bodyContent.includes("托盘") || bodyContent.includes("tray")) { + labelsToAdd.push('tray'); + } + + if (bodyContent.includes("菜单") || bodyContent.includes("menu")) { + labelsToAdd.push('menu'); + } + + // Add labels if any match + // Filter out labels that already exist to avoid duplication + const newLabelsToAdd = labelsToAdd.filter(label => !existingLabels.includes(label)); + + // Add labels if there are new ones to add + if (newLabelsToAdd.length > 0) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: newLabelsToAdd, + }); + } diff --git a/clash-verge-rev/.github/workflows/release.yml b/clash-verge-rev/.github/workflows/release.yml index 36c34ecafe..4ad137ff44 100644 --- a/clash-verge-rev/.github/workflows/release.yml +++ b/clash-verge-rev/.github/workflows/release.yml @@ -87,12 +87,6 @@ jobs: tauriScript: pnpm args: --target ${{ matrix.target }} - - name: Portable Bundle - if: matrix.os == 'windows-latest' - run: pnpm portable ${{ matrix.target }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - release-for-linux-arm: strategy: fail-fast: false @@ -221,9 +215,6 @@ jobs: - os: windows-latest target: x86_64-pc-windows-msvc arch: x64 - - os: windows-latest - target: i686-pc-windows-msvc - arch: x86 - os: windows-latest target: aarch64-pc-windows-msvc arch: arm64 diff --git a/clash-verge-rev/CONTRIBUTING.md b/clash-verge-rev/CONTRIBUTING.md index f719f31437..02c3c9cbe1 100644 --- a/clash-verge-rev/CONTRIBUTING.md +++ b/clash-verge-rev/CONTRIBUTING.md @@ -38,7 +38,7 @@ npm install pnpm -g pnpm install ``` -### Download the Clash Mihomo Core Binary +### Download the Mihomo Core Binary You have two options for downloading the clash binary: @@ -48,7 +48,7 @@ You have two options for downloading the clash binary: # Use '--force' to force update to the latest version # pnpm run check --force ``` -- Manually download it from the [Clash Meta release](https://github.com/MetaCubeX/Clash.Meta/releases). After downloading, rename the binary according to the [Tauri configuration](https://tauri.app/v1/api/config#bundleconfig.externalbin). +- Manually download it from the [Mihomo release](https://github.com/MetaCubeX/mihomo/releases). After downloading, rename the binary according to the [Tauri configuration](https://tauri.app/v1/api/config#bundleconfig.externalbin). ### Run the Development Server @@ -65,11 +65,35 @@ pnpm dev:diff To build this project: ```shell -pnpm run build +pnpm build ``` +For a faster build, use the following command + +```shell +pnpm build:fast +``` + +This uses Rust's fast-release profile which significantly reduces compilation time by disabling optimization and LTO. The resulting binary will be larger and less performant than the standard build, but it's useful for testing changes quickly. + The `Artifacts` will display in the `log` in the Terminal. +### Build clean + +To clean rust build: + +```shell +pnpm clean +``` + +### Portable Version (Windows Only) + +To package portable version after the build: + +```shell +pnpm portable +``` + ## Contributing Your Changes Once you have made your changes: diff --git a/clash-verge-rev/package.json b/clash-verge-rev/package.json index 2cea8a7bb7..9687242a83 100644 --- a/clash-verge-rev/package.json +++ b/clash-verge-rev/package.json @@ -1,13 +1,12 @@ { "name": "clash-verge", - "version": "2.1.2", + "version": "2.1.3-alpha", "license": "GPL-3.0-only", "scripts": { - "dev": "cross-env RUST_BACKTRACE=1 tauri dev -f verge-dev", - "dev:fast": "cross-env RUST_BACKTRACE=1 tauri dev", - "dev:diff": "cross-env RUST_BACKTRACE=1 tauri dev -f verge-dev", + "dev": "cross-env RUST_BACKTRACE=1 tauri dev -f verge-dev -- --profile fast-dev", + "dev:diff": "cross-env RUST_BACKTRACE=1 tauri dev -f verge-dev -- --profile fast-dev", "build": "cross-env NODE_OPTIONS='--max-old-space-size=4096' tauri build", - "build:fast": "cross-env NODE_OPTIONS='--max-old-space-size=4096' tauri build", + "build:fast": "cross-env NODE_OPTIONS='--max-old-space-size=4096' tauri build -- --profile fast-release", "tauri": "tauri", "web:dev": "vite", "web:build": "tsc --noEmit && vite build", @@ -18,7 +17,8 @@ "portable": "node scripts/portable.mjs", "portable-fixed-webview2": "node scripts/portable-fixed-webview2.mjs", "fix-alpha-version": "node scripts/alpha_version.mjs", - "prepare": "husky" + "prepare": "husky", + "clean": "cd ./src-tauri && cargo clean && cd -" }, "dependencies": { "@dnd-kit/core": "^6.3.1", diff --git a/clash-verge-rev/scripts/alpha_version.mjs b/clash-verge-rev/scripts/alpha_version.mjs index 15be5759a6..ce5a303db7 100644 --- a/clash-verge-rev/scripts/alpha_version.mjs +++ b/clash-verge-rev/scripts/alpha_version.mjs @@ -26,29 +26,41 @@ async function getLatestCommitHash() { /** * @param string 传入格式化后的hash - * 将新的版本号写入文件 package.json + * 将新的版本号写入文件 package.json / tauri.conf.json */ async function updatePackageVersion(newVersion) { // 获取内容根目录 const _dirname = process.cwd(); const packageJsonPath = path.join(_dirname, "package.json"); + const tauriDir = path.join(_dirname, "src-tauri"); + const internalfile = path.join(tauriDir, "tauri.conf.json"); try { const data = await fs.readFile(packageJsonPath, "utf8"); + const tauriData = await fs.readFile(internalfile, "utf8"); + const packageJson = JSON.parse(data); - const initversion = packageJson.version; - // 将匹配到的第一个 "alpha" => 具体的hash - const fixversion = initversion.replace("alpha", newVersion); - packageJson.version = fixversion; + const tauriJson = JSON.parse(tauriData); + + let result = packageJson.version.replace("alpha", newVersion); + console.log("[INFO]: Current version is: ", result); + packageJson.version = result; + tauriJson.version = result; // 写入版本号 await fs.writeFile( packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8", ); - console.log(`Alpha version update to: ${fixversion}`); + await fs.writeFile( + internalfile, + JSON.stringify(tauriJson, null, 2), + "utf8", + ); + console.log(`[INFO]: Alpha version update to: ${newVersion}`); } catch (error) { console.error("pnpm run fix-alpha-version ERROR", error); } } + const newVersion = await getLatestCommitHash(); -updatePackageVersion(newVersion); +updatePackageVersion(newVersion).catch(console.error); diff --git a/clash-verge-rev/scripts/portable.mjs b/clash-verge-rev/scripts/portable.mjs index 97a00d4ac9..49aafdb9cf 100644 --- a/clash-verge-rev/scripts/portable.mjs +++ b/clash-verge-rev/scripts/portable.mjs @@ -2,20 +2,16 @@ import fs from "fs"; import path from "path"; import AdmZip from "adm-zip"; import { createRequire } from "module"; -import { getOctokit, context } from "@actions/github"; +import fsp from "fs/promises"; const target = process.argv.slice(2)[0]; -const alpha = process.argv.slice(2)[1]; - const ARCH_MAP = { "x86_64-pc-windows-msvc": "x64", - "i686-pc-windows-msvc": "x86", "aarch64-pc-windows-msvc": "arm64", }; const PROCESS_MAP = { x64: "x64", - ia32: "x86", arm64: "arm64", }; const arch = target ? ARCH_MAP[target] : PROCESS_MAP[process.arch]; @@ -37,10 +33,9 @@ async function resolvePortable() { if (!fs.existsSync(path.join(configDir, "PORTABLE"))) { await fsp.writeFile(path.join(configDir, "PORTABLE"), ""); } - const zip = new AdmZip(); - zip.addLocalFile(path.join(releaseDir, "Clash Verge.exe")); + zip.addLocalFile(path.join(releaseDir, "clash-verge.exe")); zip.addLocalFile(path.join(releaseDir, "verge-mihomo.exe")); zip.addLocalFile(path.join(releaseDir, "verge-mihomo-alpha.exe")); zip.addLocalFolder(path.join(releaseDir, "resources"), "resources"); @@ -49,46 +44,9 @@ async function resolvePortable() { const require = createRequire(import.meta.url); const packageJson = require("../package.json"); const { version } = packageJson; - const zipFile = `Clash.Verge_${version}_${arch}_portable.zip`; zip.writeZip(zipFile); - console.log("[INFO]: create portable zip successfully"); - - // push release assets - if (process.env.GITHUB_TOKEN === undefined) { - throw new Error("GITHUB_TOKEN is required"); - } - - const options = { owner: context.repo.owner, repo: context.repo.repo }; - const github = getOctokit(process.env.GITHUB_TOKEN); - const tag = alpha ? "alpha" : process.env.TAG_NAME || `v${version}`; - console.log("[INFO]: upload to ", tag); - - const { data: release } = await github.rest.repos.getReleaseByTag({ - ...options, - tag, - }); - - let assets = release.assets.filter((x) => { - return x.name === zipFile; - }); - if (assets.length > 0) { - let id = assets[0].id; - await github.rest.repos.deleteReleaseAsset({ - ...options, - asset_id: id, - }); - } - - console.log(release.name); - - await github.rest.repos.uploadReleaseAsset({ - ...options, - release_id: release.id, - name: zipFile, - data: zip.toBuffer(), - }); } resolvePortable().catch(console.error); diff --git a/clash-verge-rev/src-tauri/src/feat/proxy.rs b/clash-verge-rev/src-tauri/src/feat/proxy.rs index 7f0fc4ed9b..39f7e38e3a 100644 --- a/clash-verge-rev/src-tauri/src/feat/proxy.rs +++ b/clash-verge-rev/src-tauri/src/feat/proxy.rs @@ -57,13 +57,6 @@ pub fn copy_clash_env() { let http_proxy = format!("http://{clash_verge_rev_ip}:{}", port); let socks5_proxy = format!("socks5://{clash_verge_rev_ip}:{}", port); - let sh = - format!("export https_proxy={http_proxy} http_proxy={http_proxy} all_proxy={socks5_proxy}"); - let cmd: String = format!("set http_proxy={http_proxy}\r\nset https_proxy={http_proxy}"); - let ps: String = format!("$env:HTTP_PROXY=\"{http_proxy}\"; $env:HTTPS_PROXY=\"{http_proxy}\""); - let nu: String = - format!("load-env {{ http_proxy: \"{http_proxy}\", https_proxy: \"{http_proxy}\" }}"); - let cliboard = app_handle.clipboard(); let env_type = { Config::verge().latest().env_type.clone() }; let env_type = match env_type { @@ -77,11 +70,20 @@ pub fn copy_clash_env() { default.to_string() } }; - match env_type.as_str() { - "bash" => cliboard.write_text(sh).unwrap_or_default(), - "cmd" => cliboard.write_text(cmd).unwrap_or_default(), - "powershell" => cliboard.write_text(ps).unwrap_or_default(), - "nushell" => cliboard.write_text(nu).unwrap_or_default(), - _ => log::error!(target: "app", "copy_clash_env: Invalid env type! {env_type}"), + + let export_text = match env_type.as_str() { + "bash" => format!("export https_proxy={http_proxy} http_proxy={http_proxy} all_proxy={socks5_proxy}"), + "cmd" => format!("set http_proxy={http_proxy}\r\nset https_proxy={http_proxy}"), + "powershell" => format!("$env:HTTP_PROXY=\"{http_proxy}\"; $env:HTTPS_PROXY=\"{http_proxy}\""), + "nushell" => format!("load-env {{ http_proxy: \"{http_proxy}\", https_proxy: \"{http_proxy}\" }}"), + "fish" => format!("set -x http_proxy {http_proxy}; set -x https_proxy {http_proxy}"), + _ => { + log::error!(target: "app", "copy_clash_env: Invalid env type! {env_type}"); + return; + } }; + + if let Err(_) = cliboard.write_text(export_text) { + log::error!(target: "app", "Failed to write to clipboard"); + } } diff --git a/clash-verge-rev/src-tauri/src/lib.rs b/clash-verge-rev/src-tauri/src/lib.rs index 7b49c1952c..a199cf1e34 100644 --- a/clash-verge-rev/src-tauri/src/lib.rs +++ b/clash-verge-rev/src-tauri/src/lib.rs @@ -11,6 +11,8 @@ use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_deep_link::DeepLinkExt; use std::sync::{Mutex, Once}; use tauri::AppHandle; +#[cfg(target_os = "macos")] +use tauri::Manager; /// A global singleton handle to the application. pub struct AppHandleManager { @@ -203,6 +205,11 @@ pub fn run() { app.run(|app_handle, e| match e { tauri::RunEvent::Ready | tauri::RunEvent::Resumed => { AppHandleManager::global().init(app_handle.clone()); + #[cfg(target_os = "macos")] + { + let main_window = AppHandleManager::global().get_handle().get_webview_window("main").unwrap(); + let _ = main_window.set_title("Clash Verge"); + } } #[cfg(target_os = "macos")] tauri::RunEvent::Reopen { has_visible_windows, .. } => { @@ -220,6 +227,7 @@ pub fn run() { if label == "main" { match event { tauri::WindowEvent::CloseRequested { api, .. } => { + #[cfg(target_os = "macos")] AppHandleManager::global().set_activation_policy_accessory(); if core::handle::Handle::global().is_exiting() { return; diff --git a/clash-verge-rev/src-tauri/src/utils/resolve.rs b/clash-verge-rev/src-tauri/src/utils/resolve.rs index 4b160005b9..88844c77ed 100644 --- a/clash-verge-rev/src-tauri/src/utils/resolve.rs +++ b/clash-verge-rev/src-tauri/src/utils/resolve.rs @@ -1,7 +1,9 @@ use crate::config::IVerge; use crate::utils::error; use crate::{config::Config, config::PrfItem, core::*, utils::init, utils::server}; -use crate::{log_err, wrap_err, AppHandleManager}; +use crate::{log_err, wrap_err}; +#[cfg(target_os = "macos")] +use crate::AppHandleManager; use anyhow::{bail, Result}; use once_cell::sync::OnceCell; use percent_encoding::percent_decode_str; @@ -133,6 +135,7 @@ pub fn create_window() { log::info!(target: "app", "Starting to create window"); let app_handle = handle::Handle::global().app_handle().unwrap(); + #[cfg(target_os = "macos")] AppHandleManager::global().set_activation_policy_regular(); if let Some(window) = handle::Handle::global().get_window() { diff --git a/clash-verge-rev/src-tauri/tauri.conf.json b/clash-verge-rev/src-tauri/tauri.conf.json index 223df55154..5f9e182b3b 100755 --- a/clash-verge-rev/src-tauri/tauri.conf.json +++ b/clash-verge-rev/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "version": "2.1.3-alpha", "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "bundle": { "active": true, @@ -25,7 +26,6 @@ "devUrl": "http://localhost:3000/" }, "productName": "Clash Verge", - "version": "2.1.2", "identifier": "io.github.clash-verge-rev.clash-verge-rev", "plugins": { "updater": { diff --git a/clash-verge-rev/src-tauri/tauri.macos.conf.json b/clash-verge-rev/src-tauri/tauri.macos.conf.json index 51090fe3e1..3359113f1a 100644 --- a/clash-verge-rev/src-tauri/tauri.macos.conf.json +++ b/clash-verge-rev/src-tauri/tauri.macos.conf.json @@ -32,11 +32,6 @@ } }, "app": { - "windows": [ - { - "title": "Clash Verge" - } - ], "trayIcon": { "iconPath": "icons/tray-icon-mono.ico", "iconAsTemplate": true diff --git a/clash-verge-rev/src/components/proxy/proxy-groups.tsx b/clash-verge-rev/src/components/proxy/proxy-groups.tsx index 1e1660e5fa..b0f78bbd84 100644 --- a/clash-verge-rev/src/components/proxy/proxy-groups.tsx +++ b/clash-verge-rev/src/components/proxy/proxy-groups.tsx @@ -490,7 +490,7 @@ export const ProxyGroups = (props: Props) => { scrollerRef.current = ref as Element; }} components={{ - Footer: () =>
, + Footer: () =>
, }} // 添加平滑滚动设置 initialScrollTop={scrollPositionRef.current[mode]} @@ -508,8 +508,13 @@ export const ProxyGroups = (props: Props) => { )} /> - - +
{groupFirstLetters.map((name) => ( diff --git a/clash-verge-rev/src/components/proxy/proxy-render.tsx b/clash-verge-rev/src/components/proxy/proxy-render.tsx index 7a18b01d10..57190129b5 100644 --- a/clash-verge-rev/src/components/proxy/proxy-render.tsx +++ b/clash-verge-rev/src/components/proxy/proxy-render.tsx @@ -66,8 +66,8 @@ export const ProxyRender = (props: RenderProps) => { style={{ background: itembackgroundcolor, height: "100%", - margin: "8px 8px", - borderRadius: "8px", + margin: "10px 16px", + borderRadius: "10px", }} onClick={() => onHeadState(group.name, { open: !headState?.open })} > @@ -131,7 +131,7 @@ export const ProxyRender = (props: RenderProps) => { if (type === 1) { return ( { sx={{ height: 56, display: "grid", - gap: 1, - pl: 2, - pr: 2, - pb: 1, + gap: 1.5, + pl: 3, + pr: 3.5, + pb: 1.25, gridTemplateColumns: `repeat(${item.col! || 2}, 1fr)`, }} > diff --git a/clash-verge-rev/src/components/setting/setting-verge-basic.tsx b/clash-verge-rev/src/components/setting/setting-verge-basic.tsx index 5c8d1132f8..4e562bf0c0 100644 --- a/clash-verge-rev/src/components/setting/setting-verge-basic.tsx +++ b/clash-verge-rev/src/components/setting/setting-verge-basic.tsx @@ -142,8 +142,9 @@ const SettingVergeBasic = ({ onError }: Props) => { > diff --git a/clash-verge-rev/src/hooks/use-log-data.ts b/clash-verge-rev/src/hooks/use-log-data.ts index 3db2cf9d0d..a8a8e3eefc 100644 --- a/clash-verge-rev/src/hooks/use-log-data.ts +++ b/clash-verge-rev/src/hooks/use-log-data.ts @@ -5,18 +5,19 @@ import { useClashInfo } from "./use-clash"; import dayjs from "dayjs"; import { create } from "zustand"; import { useVisibility } from "./use-visibility"; +import { + useGlobalLogData, + clearGlobalLogs, + LogLevel, + ILogItem, +} from "@/services/global-log-service"; + +// 为了向后兼容,导出相同的类型 +export type { LogLevel }; +export type { ILogItem }; const MAX_LOG_NUM = 1000; -export type LogLevel = "warning" | "info" | "debug" | "error" | "all"; - -interface ILogItem { - time?: string; - type: string; - payload: string; - [key: string]: any; -} - const buildWSUrl = (server: string, secret: string, logLevel: LogLevel) => { const baseUrl = `ws://${server}/logs`; const params = new URLSearchParams(); @@ -57,45 +58,6 @@ const useLogStore = create( }), ); -export const useLogData = (logLevel: LogLevel) => { - const { clashInfo } = useClashInfo(); - const [enableLog] = useEnableLog(); - const { logs, appendLog } = useLogStore(); - const pageVisible = useVisibility(); +export const useLogData = useGlobalLogData; - useEffect(() => { - if (!enableLog || !clashInfo || !pageVisible) return; - - const { server = "", secret = "" } = clashInfo; - const wsUrl = buildWSUrl(server, secret, logLevel); - - let isActive = true; - const socket = createSockette(wsUrl, { - onmessage(event) { - if (!isActive) return; - const data = JSON.parse(event.data) as ILogItem; - const time = dayjs().format("MM-DD HH:mm:ss"); - appendLog({ ...data, time }); - }, - onerror() { - if (!isActive) return; - socket.close(); - }, - }); - - return () => { - isActive = false; - socket.close(); - }; - }, [clashInfo, enableLog, logLevel]); - - // 根据当前选择的日志等级过滤日志 - return logLevel === "all" - ? logs - : logs.filter((log) => log.type.toLowerCase() === logLevel); -}; - -// 导出清空日志的方法 -export const clearLogs = () => { - useLogStore.getState().clearLogs(); -}; +export const clearLogs = clearGlobalLogs; diff --git a/clash-verge-rev/src/pages/_layout.tsx b/clash-verge-rev/src/pages/_layout.tsx index c5d6b04869..d5b935731c 100644 --- a/clash-verge-rev/src/pages/_layout.tsx +++ b/clash-verge-rev/src/pages/_layout.tsx @@ -13,7 +13,7 @@ import { useVerge } from "@/hooks/use-verge"; import LogoSvg from "@/assets/image/logo.svg?react"; import iconLight from "@/assets/image/icon_light.svg?react"; import iconDark from "@/assets/image/icon_dark.svg?react"; -import { useThemeMode } from "@/services/states"; +import { useThemeMode, useEnableLog } from "@/services/states"; import { Notice } from "@/components/base"; import { LayoutItem } from "@/components/layout/layout-item"; import { LayoutControl } from "@/components/layout/layout-control"; @@ -28,6 +28,8 @@ import React from "react"; import { TransitionGroup, CSSTransition } from "react-transition-group"; import { useListen } from "@/hooks/use-listen"; import { listen } from "@tauri-apps/api/event"; +import { useClashInfo } from "@/hooks/use-clash"; +import { initGlobalLogService } from "@/services/global-log-service"; const appWindow = getCurrentWebviewWindow(); export let portableFlag = false; @@ -126,6 +128,8 @@ const Layout = () => { const { t } = useTranslation(); const { theme } = useCustomTheme(); const { verge } = useVerge(); + const { clashInfo } = useClashInfo(); + const [enableLog] = useEnableLog(); const { language, start_page } = verge ?? {}; const navigate = useNavigate(); const location = useLocation(); @@ -140,6 +144,15 @@ const Layout = () => { [t, navigate], ); + // 初始化全局日志服务 + useEffect(() => { + if (clashInfo) { + const { server = "", secret = "" } = clashInfo; + // 使用本地存储中的enableLog值初始化全局日志服务 + initGlobalLogService(server, secret, enableLog, "info"); + } + }, [clashInfo, enableLog]); + // 设置监听器 useEffect(() => { const listeners = [ diff --git a/clash-verge-rev/src/pages/logs.tsx b/clash-verge-rev/src/pages/logs.tsx index 0784f3d4d4..755efd64d0 100644 --- a/clash-verge-rev/src/pages/logs.tsx +++ b/clash-verge-rev/src/pages/logs.tsx @@ -8,7 +8,8 @@ import { PlayCircleOutlineRounded, PauseCircleOutlineRounded, } from "@mui/icons-material"; -import { useLogData, LogLevel, clearLogs } from "@/hooks/use-log-data"; +import { LogLevel, clearLogs } from "@/hooks/use-log-data"; +import { useClashInfo } from "@/hooks/use-clash"; import { useEnableLog } from "@/services/states"; import { BaseEmpty, BasePage } from "@/components/base"; import LogItem from "@/components/log/log-item"; @@ -16,10 +17,17 @@ import { useTheme } from "@mui/material/styles"; import { BaseSearchBox } from "@/components/base/base-search-box"; import { BaseStyledSelect } from "@/components/base/base-styled-select"; import { SearchState } from "@/components/base/base-search-box"; +import { + useGlobalLogData, + clearGlobalLogs, + changeLogLevel, + toggleLogEnabled, +} from "@/services/global-log-service"; const LogPage = () => { const { t } = useTranslation(); const [enableLog, setEnableLog] = useEnableLog(); + const { clashInfo } = useClashInfo(); const theme = useTheme(); const isDark = theme.palette.mode === "dark"; const [logLevel, setLogLevel] = useLocalStorage( @@ -27,7 +35,7 @@ const LogPage = () => { "info", ); const [match, setMatch] = useState(() => (_: string) => true); - const logData = useLogData(logLevel); + const logData = useGlobalLogData(logLevel); const [searchState, setSearchState] = useState(); const filterLogs = useMemo(() => { @@ -44,6 +52,22 @@ const LogPage = () => { : []; }, [logData, logLevel, match]); + const handleLogLevelChange = (newLevel: LogLevel) => { + setLogLevel(newLevel); + if (clashInfo) { + const { server = "", secret = "" } = clashInfo; + changeLogLevel(newLevel, server, secret); + } + }; + + const handleToggleLog = () => { + if (clashInfo) { + const { server = "", secret = "" } = clashInfo; + toggleLogEnabled(server, secret); + setEnableLog(!enableLog); + } + }; + return ( { title={t("Pause")} size="small" color="inherit" - onClick={() => setEnableLog((e) => !e)} + onClick={handleToggleLog} > {enableLog ? ( @@ -74,7 +98,7 @@ const LogPage = () => { size="small" variant="contained" onClick={() => { - clearLogs(); + clearGlobalLogs(); }} > {t("Clear")} @@ -95,7 +119,7 @@ const LogPage = () => { > setLogLevel(e.target.value as LogLevel)} + onChange={(e) => handleLogLevelChange(e.target.value as LogLevel)} > ALL INFO diff --git a/clash-verge-rev/src/services/global-log-service.ts b/clash-verge-rev/src/services/global-log-service.ts new file mode 100644 index 0000000000..a547a6adb7 --- /dev/null +++ b/clash-verge-rev/src/services/global-log-service.ts @@ -0,0 +1,168 @@ +// 全局日志服务,使应用在任何页面都能收集日志 +import { create } from "zustand"; +import { createSockette } from "../utils/websocket"; +import dayjs from "dayjs"; +import { useState, useEffect } from "react"; + +// 最大日志数量 +const MAX_LOG_NUM = 1000; + +export type LogLevel = "warning" | "info" | "debug" | "error" | "all"; + +export interface ILogItem { + time?: string; + type: string; + payload: string; + [key: string]: any; +} + +interface GlobalLogStore { + logs: ILogItem[]; + enabled: boolean; + isConnected: boolean; + currentLevel: LogLevel; + setEnabled: (enabled: boolean) => void; + setCurrentLevel: (level: LogLevel) => void; + clearLogs: () => void; + appendLog: (log: ILogItem) => void; +} + +// 创建全局状态存储 +export const useGlobalLogStore = create((set) => ({ + logs: [], + enabled: false, + isConnected: false, + currentLevel: "info", + setEnabled: (enabled) => set({ enabled }), + setCurrentLevel: (currentLevel) => set({ currentLevel }), + clearLogs: () => set({ logs: [] }), + appendLog: (log: ILogItem) => + set((state) => { + const newLogs = + state.logs.length >= MAX_LOG_NUM + ? [...state.logs.slice(1), log] + : [...state.logs, log]; + return { logs: newLogs }; + }), +})); + +// 构建WebSocket URL +const buildWSUrl = (server: string, secret: string, logLevel: LogLevel) => { + const baseUrl = `ws://${server}/logs`; + const params = new URLSearchParams(); + + if (secret) { + params.append("token", secret); + } + if (logLevel === "all") { + params.append("level", "debug"); + } else { + params.append("level", logLevel); + } + const queryString = params.toString(); + return queryString ? `${baseUrl}?${queryString}` : baseUrl; +}; + +// 初始化全局日志服务 +let globalLogSocket: any = null; + +export const initGlobalLogService = ( + server: string, + secret: string, + enabled: boolean = false, + logLevel: LogLevel = "info", +) => { + const { appendLog, setEnabled } = useGlobalLogStore.getState(); + + // 更新启用状态 + setEnabled(enabled); + + // 如果不启用或没有服务器信息,则不初始化 + if (!enabled || !server) { + closeGlobalLogConnection(); + return; + } + + // 关闭现有连接 + closeGlobalLogConnection(); + + // 创建新的WebSocket连接 + const wsUrl = buildWSUrl(server, secret, logLevel); + globalLogSocket = createSockette(wsUrl, { + onmessage(event) { + try { + const data = JSON.parse(event.data) as ILogItem; + const time = dayjs().format("MM-DD HH:mm:ss"); + appendLog({ ...data, time }); + } catch (error) { + console.error("Failed to parse log data:", error); + } + }, + onerror() { + console.error("Log WebSocket connection error"); + closeGlobalLogConnection(); + }, + onclose() { + console.log("Log WebSocket connection closed"); + useGlobalLogStore.setState({ isConnected: false }); + }, + onopen() { + console.log("Log WebSocket connection opened"); + useGlobalLogStore.setState({ isConnected: true }); + }, + }); +}; + +// 关闭全局日志连接 +export const closeGlobalLogConnection = () => { + if (globalLogSocket) { + globalLogSocket.close(); + globalLogSocket = null; + useGlobalLogStore.setState({ isConnected: false }); + } +}; + +// 切换日志级别 +export const changeLogLevel = ( + level: LogLevel, + server: string, + secret: string, +) => { + const { enabled } = useGlobalLogStore.getState(); + useGlobalLogStore.setState({ currentLevel: level }); + + if (enabled && server) { + initGlobalLogService(server, secret, enabled, level); + } +}; + +// 切换启用状态 +export const toggleLogEnabled = (server: string, secret: string) => { + const { enabled, currentLevel } = useGlobalLogStore.getState(); + const newEnabled = !enabled; + + useGlobalLogStore.setState({ enabled: newEnabled }); + + if (newEnabled && server) { + initGlobalLogService(server, secret, newEnabled, currentLevel); + } else { + closeGlobalLogConnection(); + } +}; + +// 获取日志清理函数 +export const clearGlobalLogs = () => { + useGlobalLogStore.getState().clearLogs(); +}; + +// 自定义钩子,用于获取过滤后的日志数据 +export const useGlobalLogData = (logLevel: LogLevel = "all") => { + const logs = useGlobalLogStore((state) => state.logs); + + // 根据当前选择的日志等级过滤日志 + if (logLevel === "all") { + return logs; + } else { + return logs.filter((log) => log.type.toLowerCase() === logLevel); + } +}; diff --git a/clash-verge-rev/src/services/types.d.ts b/clash-verge-rev/src/services/types.d.ts index 7bceae5a85..83ba144e03 100644 --- a/clash-verge-rev/src/services/types.d.ts +++ b/clash-verge-rev/src/services/types.d.ts @@ -694,7 +694,7 @@ interface IVergeConfig { app_log_level?: "trace" | "debug" | "info" | "warn" | "error" | string; language?: string; tray_event?: "main_window" | "system_proxy" | "tun_mode" | string; - env_type?: "bash" | "cmd" | "powershell" | string; + env_type?: "bash" | "cmd" | "powershell" | "fish" | string; startup_script?: string; start_page?: string; clash_core?: string; diff --git a/lede/package/wwan/driver/quectel_MHI/Makefile b/lede/package/wwan/driver/quectel_MHI/Makefile index 22b314b77e..f67e52702e 100755 --- a/lede/package/wwan/driver/quectel_MHI/Makefile +++ b/lede/package/wwan/driver/quectel_MHI/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=pcie_mhi PKG_VERSION:=1.3.6 -PKG_RELEASE:=1 +PKG_RELEASE:=2 include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/package.mk diff --git a/lede/package/wwan/driver/quectel_MHI/src/devices/mhi_netdev_quectel.c b/lede/package/wwan/driver/quectel_MHI/src/devices/mhi_netdev_quectel.c index 1812c026cd..484369b1ae 100644 --- a/lede/package/wwan/driver/quectel_MHI/src/devices/mhi_netdev_quectel.c +++ b/lede/package/wwan/driver/quectel_MHI/src/devices/mhi_netdev_quectel.c @@ -68,15 +68,13 @@ struct rmnet_nss_cb { int (*nss_tx)(struct sk_buff *skb); }; static struct rmnet_nss_cb __read_mostly *nss_cb = NULL; -#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) || defined(CONFIG_PINCTRL_IPQ8074) -//#ifdef CONFIG_RMNET_DATA //spf12.x have no macro defined, just for spf11.x +#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) +#ifdef CONFIG_RMNET_DATA #define CONFIG_QCA_NSS_DRV -/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ //for spf11.x -/* define at qsdk/qca/src/datarmnet/core/rmnet_config.c */ //for spf12.x +/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ /* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */ -/* need add DEPENDS:= kmod-rmnet-core in feeds/makefile */ extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; -//#endif +#endif #endif static const unsigned char node_id[ETH_ALEN] = {0x02, 0x50, 0xf4, 0x00, 0x00, 0x00}; diff --git a/lede/target/linux/rockchip/armv8/config-6.1 b/lede/target/linux/rockchip/armv8/config-6.1 index b1fe9741a1..d7d94469d3 100644 --- a/lede/target/linux/rockchip/armv8/config-6.1 +++ b/lede/target/linux/rockchip/armv8/config-6.1 @@ -561,6 +561,7 @@ CONFIG_SCSI_SAS_LIBSAS=y # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SENSORS_ARM_SCMI is not set CONFIG_SENSORS_ARM_SCPI=y +CONFIG_SENSORS_PWM_FAN=y CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_8250_DWLIB=y diff --git a/lede/target/linux/rockchip/armv8/config-6.12 b/lede/target/linux/rockchip/armv8/config-6.12 index 3bde696e3a..e805119ed4 100644 --- a/lede/target/linux/rockchip/armv8/config-6.12 +++ b/lede/target/linux/rockchip/armv8/config-6.12 @@ -625,6 +625,7 @@ CONFIG_SCSI_SAS_LIBSAS=y # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SENSORS_ARM_SCMI is not set CONFIG_SENSORS_ARM_SCPI=y +CONFIG_SENSORS_PWM_FAN=y CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_8250_DWLIB=y diff --git a/lede/target/linux/rockchip/armv8/config-6.6 b/lede/target/linux/rockchip/armv8/config-6.6 index 9ad6720007..b1e8c5018c 100644 --- a/lede/target/linux/rockchip/armv8/config-6.6 +++ b/lede/target/linux/rockchip/armv8/config-6.6 @@ -605,6 +605,7 @@ CONFIG_SCSI_SAS_LIBSAS=y # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SENSORS_ARM_SCMI is not set CONFIG_SENSORS_ARM_SCPI=y +CONFIG_SENSORS_PWM_FAN=y CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_8250_DWLIB=y diff --git a/mihomo/transport/anytls/session/client.go b/mihomo/transport/anytls/session/client.go index b0c9982bac..5e99f13562 100644 --- a/mihomo/transport/anytls/session/client.go +++ b/mihomo/transport/anytls/session/client.go @@ -21,10 +21,14 @@ type Client struct { dialOut util.DialOutFunc - sessionCounter atomic.Uint64 + sessionCounter atomic.Uint64 + idleSession *skiplist.SkipList[uint64, *Session] idleSessionLock sync.Mutex + sessions map[uint64]*Session + sessionsLock sync.Mutex + padding *atomic.TypedValue[*padding.PaddingFactory] idleSessionTimeout time.Duration @@ -33,6 +37,7 @@ type Client struct { func NewClient(ctx context.Context, dialOut util.DialOutFunc, _padding *atomic.TypedValue[*padding.PaddingFactory], idleSessionCheckInterval, idleSessionTimeout time.Duration, minIdleSession int) *Client { c := &Client{ + sessions: make(map[uint64]*Session), dialOut: dialOut, padding: _padding, idleSessionTimeout: idleSessionTimeout, @@ -130,15 +135,35 @@ func (c *Client) createSession(ctx context.Context) (*Session, error) { c.idleSessionLock.Lock() c.idleSession.Remove(math.MaxUint64 - session.seq) c.idleSessionLock.Unlock() + + c.sessionsLock.Lock() + delete(c.sessions, session.seq) + c.sessionsLock.Unlock() } + + c.sessionsLock.Lock() + c.sessions[session.seq] = session + c.sessionsLock.Unlock() + session.Run() return session, nil } func (c *Client) Close() error { c.dieCancel() - c.minIdleSession = 0 - go c.idleCleanupExpTime(time.Time{}) + + c.sessionsLock.Lock() + sessionToClose := make([]*Session, 0, len(c.sessions)) + for seq, session := range c.sessions { + sessionToClose = append(sessionToClose, session) + delete(c.sessions, seq) + } + c.sessionsLock.Unlock() + + for _, session := range sessionToClose { + session.Close() + } + return nil } diff --git a/openwrt-passwall/.github/workflows/Auto compile with openwrt sdk.yml b/openwrt-passwall/.github/workflows/Auto compile with openwrt sdk.yml index fb7071e9b8..583f5d5620 100644 --- a/openwrt-passwall/.github/workflows/Auto compile with openwrt sdk.yml +++ b/openwrt-passwall/.github/workflows/Auto compile with openwrt sdk.yml @@ -78,13 +78,13 @@ jobs: fail-fast: false matrix: include: - - sdk_ver: 21.02 - luci_ver: 19.07 + - sdk_ver: "21.02" + luci_ver: "19.07" sdk_url: https://downloads.openwrt.org/releases/21.02.7/targets/x86/64/openwrt-sdk-21.02.7-x86-64_gcc-8.4.0_musl.Linux-x86_64.tar.xz - - sdk_ver: 23.05 - luci_ver: 23.05 - sdk_url: https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz + - sdk_ver: "24.10" + luci_ver: "24.10" + sdk_url: https://downloads.openwrt.org/releases/24.10.0/targets/x86/64/openwrt-sdk-24.10.0-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst steps: - name: Install packages run: | @@ -107,7 +107,7 @@ jobs: run: | wget ${{ matrix.sdk_url }} file_name=$(echo ${{ matrix.sdk_url }} | awk -F/ '{print $NF}') - mkdir sdk && tar -xJf $file_name -C ./sdk --strip-components=1 + mkdir sdk && tar --zstd -x -f $file_name -C ./sdk --strip-components=1 cd sdk echo "src-git base https://github.com/openwrt/openwrt.git;openwrt-${{ matrix.sdk_ver }}" > feeds.conf echo "src-git packages https://github.com/openwrt/packages.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf @@ -115,6 +115,10 @@ jobs: echo "src-git routing https://git.openwrt.org/feed/routing.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf echo "src-git passwall_packages https://github.com/${{ env.packages }}.git;main" >> feeds.conf echo "src-git passwall https://github.com/${{ env.passwall }}.git;${{ github.ref_name }}" >> feeds.conf + + rm -rf feeds/packages/lang/golang + git clone https://github.com/sbwml/packages_lang_golang -b 24.x feeds/packages/lang/golang + ./scripts/feeds update -a echo "CONFIG_PACKAGE_luci-app-passwall=m" > .config ./scripts/feeds install -d n luci-app-passwall @@ -172,58 +176,76 @@ jobs: matrix: include: - platform: x86_64 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/x86/64/openwrt-sdk-24.10.0-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: aarch64_generic - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/rockchip/armv8/openwrt-sdk-23.05.5-rockchip-armv8_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/rockchip/armv8/openwrt-sdk-24.10.0-rockchip-armv8_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: aarch64_cortex-a53 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mvebu/cortexa53/openwrt-sdk-23.05.5-mvebu-cortexa53_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/mvebu/cortexa53/openwrt-sdk-24.10.0-mvebu-cortexa53_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: aarch64_cortex-a72 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mvebu/cortexa72/openwrt-sdk-23.05.5-mvebu-cortexa72_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/mvebu/cortexa72/openwrt-sdk-24.10.0-mvebu-cortexa72_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a5_vfpv4 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/at91/sama5/openwrt-sdk-23.05.5-at91-sama5_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/at91/sama5/openwrt-sdk-24.10.0-at91-sama5_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a7 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mediatek/mt7629/openwrt-sdk-23.05.5-mediatek-mt7629_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/mediatek/mt7629/openwrt-sdk-24.10.0-mediatek-mt7629_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a7_neon-vfpv4 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/sunxi/cortexa7/openwrt-sdk-23.05.5-sunxi-cortexa7_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/sunxi/cortexa7/openwrt-sdk-24.10.0-sunxi-cortexa7_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a8_vfpv3 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/sunxi/cortexa8/openwrt-sdk-23.05.5-sunxi-cortexa8_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/sunxi/cortexa8/openwrt-sdk-24.10.0-sunxi-cortexa8_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a9 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/bcm53xx/generic/openwrt-sdk-23.05.5-bcm53xx-generic_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/bcm53xx/generic/openwrt-sdk-24.10.0-bcm53xx-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a9_neon - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/zynq/generic/openwrt-sdk-23.05.5-zynq-generic_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/zynq/generic/openwrt-sdk-24.10.0-zynq-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a9_vfpv3-d16 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mvebu/cortexa9/openwrt-sdk-23.05.5-mvebu-cortexa9_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/mvebu/cortexa9/openwrt-sdk-24.10.0-mvebu-cortexa9_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a15_neon-vfpv4 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/ipq806x/generic/openwrt-sdk-23.05.5-ipq806x-generic_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/ipq806x/generic/openwrt-sdk-24.10.0-ipq806x-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mips_24kc - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/ath79/generic/openwrt-sdk-23.05.5-ath79-generic_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/ath79/generic/openwrt-sdk-24.10.0-ath79-generic_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mips_4kec - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/realtek/rtl838x/openwrt-sdk-23.05.5-realtek-rtl838x_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/realtek/rtl838x/openwrt-sdk-24.10.0-realtek-rtl838x_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mips_mips32 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/bcm63xx/generic/openwrt-sdk-23.05.5-bcm63xx-generic_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/bcm53xx/generic/openwrt-sdk-24.10.0-bcm53xx-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mipsel_24kc - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/ramips/rt288x/openwrt-sdk-23.05.5-ramips-rt288x_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/ramips/rt288x/openwrt-sdk-24.10.0-ramips-rt288x_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mipsel_74kc - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/ramips/rt3883/openwrt-sdk-23.05.5-ramips-rt3883_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/ramips/rt3883/openwrt-sdk-24.10.0-ramips-rt3883_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mipsel_mips32 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/bcm47xx/generic/openwrt-sdk-23.05.5-bcm47xx-generic_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/bcm47xx/generic/openwrt-sdk-24.10.0-bcm47xx-generic_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" steps: - name: Initialization ${{ matrix.platform }} compile environment @@ -239,7 +261,7 @@ jobs: run: | wget ${{ matrix.url_sdk }} file_name=$(echo ${{matrix.url_sdk}} | awk -F/ '{print $NF}') - mkdir sdk && tar -xJf $file_name -C ./sdk --strip-components=1 + mkdir sdk && tar --zstd -x -f $file_name -C ./sdk --strip-components=1 cd sdk - name: SSH connection to Actions @@ -249,10 +271,10 @@ jobs: - name: ${{ matrix.platform }} feeds configuration packages run: | cd sdk - echo "src-git base https://github.com/openwrt/openwrt.git;openwrt-23.05" > feeds.conf - echo "src-git packages https://github.com/openwrt/packages.git;openwrt-23.05" >> feeds.conf - echo "src-git luci https://github.com/openwrt/luci.git;openwrt-23.05" >> feeds.conf - echo "src-git routing https://git.openwrt.org/feed/routing.git;openwrt-23.05" >> feeds.conf + echo "src-git base https://github.com/openwrt/openwrt.git;openwrt-${{ matrix.sdk_ver }}" > feeds.conf + echo "src-git packages https://github.com/openwrt/packages.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf + echo "src-git luci https://github.com/openwrt/luci.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf + echo "src-git routing https://git.openwrt.org/feed/routing.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf echo "src-git passwall_packages https://github.com/${{ env.packages }}.git;main" >> feeds.conf echo "src-git passwall https://github.com/${{ env.passwall }}.git;main" >> feeds.conf @@ -305,7 +327,11 @@ jobs: cd sdk for package in $(ls feeds/passwall_packages); do if [ -d "feeds/passwall_packages/$package" ]; then - make package/feeds/passwall_packages/$package/compile -j$(nproc) V=s 2>/dev/null + echo "-----------begin compile $package ---------------" + sleep 10s + make package/feeds/passwall_packages/$package/compile -j$(nproc) V=s + echo "-----------compiled $package ---------------" + echo "" fi done diff --git a/openwrt-passwall/luci-app-passwall/Makefile b/openwrt-passwall/luci-app-passwall/Makefile index af6e04ac59..aca3e70dff 100644 --- a/openwrt-passwall/luci-app-passwall/Makefile +++ b/openwrt-passwall/luci-app-passwall/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall -PKG_VERSION:=25.2.12 +PKG_VERSION:=25.3.2 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml b/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml index 3b0ccc705e..0bceda1c71 100644 --- a/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml +++ b/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml @@ -78,13 +78,13 @@ jobs: fail-fast: false matrix: include: - - sdk_ver: 21.02 - luci_ver: 19.07 + - sdk_ver: "21.02" + luci_ver: "19.07" sdk_url: https://downloads.openwrt.org/releases/21.02.7/targets/x86/64/openwrt-sdk-21.02.7-x86-64_gcc-8.4.0_musl.Linux-x86_64.tar.xz - - sdk_ver: 23.05 - luci_ver: 23.05 - sdk_url: https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz + - sdk_ver: "24.10" + luci_ver: "24.10" + sdk_url: https://downloads.openwrt.org/releases/24.10.0/targets/x86/64/openwrt-sdk-24.10.0-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst steps: - name: Install packages run: | @@ -107,7 +107,7 @@ jobs: run: | wget ${{ matrix.sdk_url }} file_name=$(echo ${{ matrix.sdk_url }} | awk -F/ '{print $NF}') - mkdir sdk && tar -xJf $file_name -C ./sdk --strip-components=1 + mkdir sdk && tar --zstd -x -f $file_name -C ./sdk --strip-components=1 cd sdk echo "src-git base https://github.com/openwrt/openwrt.git;openwrt-${{ matrix.sdk_ver }}" > feeds.conf echo "src-git packages https://github.com/openwrt/packages.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf @@ -115,10 +115,14 @@ jobs: echo "src-git routing https://git.openwrt.org/feed/routing.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf echo "src-git passwall_packages https://github.com/${{ env.packages }}.git;main" >> feeds.conf echo "src-git passwall2 https://github.com/${{ env.passwall2 }}.git;${{ github.ref_name }}" >> feeds.conf + + rm -rf feeds/packages/lang/golang + git clone https://github.com/sbwml/packages_lang_golang -b 24.x feeds/packages/lang/golang + ./scripts/feeds update -a echo "CONFIG_PACKAGE_luci-app-passwall2=m" > .config ./scripts/feeds install -d n luci-app-passwall2 - make package/luci-app-passwall2/download -j1 + make package/luci-app-passwall2/download -j$(nproc) - name: Update passwall2 feeds if: steps.cache-sdk.outputs.cache-hit == 'true' @@ -140,8 +144,8 @@ jobs: echo "CONFIG_LUCI_LANG_zh_Hans=y" >> .config echo "CONFIG_PACKAGE_luci-app-passwall2=m" >> .config make defconfig - echo "make package/luci-app-passwall2/{clean,compile} -j1" - make package/luci-app-passwall2/{clean,compile} -j1 V=s + echo "make package/luci-app-passwall2/{clean,compile} -j$(nproc)" + make package/luci-app-passwall2/{clean,compile} -j$(nproc) V=s mv bin/packages/x86_64/passwall2/ ../ make clean rm .config .config.old @@ -172,58 +176,76 @@ jobs: matrix: include: - platform: x86_64 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/x86/64/openwrt-sdk-24.10.0-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: aarch64_generic - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/rockchip/armv8/openwrt-sdk-23.05.5-rockchip-armv8_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/rockchip/armv8/openwrt-sdk-24.10.0-rockchip-armv8_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: aarch64_cortex-a53 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mvebu/cortexa53/openwrt-sdk-23.05.5-mvebu-cortexa53_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/mvebu/cortexa53/openwrt-sdk-24.10.0-mvebu-cortexa53_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: aarch64_cortex-a72 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mvebu/cortexa72/openwrt-sdk-23.05.5-mvebu-cortexa72_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/mvebu/cortexa72/openwrt-sdk-24.10.0-mvebu-cortexa72_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a5_vfpv4 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/at91/sama5/openwrt-sdk-23.05.5-at91-sama5_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/at91/sama5/openwrt-sdk-24.10.0-at91-sama5_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a7 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mediatek/mt7629/openwrt-sdk-23.05.5-mediatek-mt7629_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/mediatek/mt7629/openwrt-sdk-24.10.0-mediatek-mt7629_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a7_neon-vfpv4 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/sunxi/cortexa7/openwrt-sdk-23.05.5-sunxi-cortexa7_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/sunxi/cortexa7/openwrt-sdk-24.10.0-sunxi-cortexa7_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a8_vfpv3 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/sunxi/cortexa8/openwrt-sdk-23.05.5-sunxi-cortexa8_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/sunxi/cortexa8/openwrt-sdk-24.10.0-sunxi-cortexa8_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a9 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/bcm53xx/generic/openwrt-sdk-23.05.5-bcm53xx-generic_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/bcm53xx/generic/openwrt-sdk-24.10.0-bcm53xx-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a9_neon - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/zynq/generic/openwrt-sdk-23.05.5-zynq-generic_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/zynq/generic/openwrt-sdk-24.10.0-zynq-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a9_vfpv3-d16 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mvebu/cortexa9/openwrt-sdk-23.05.5-mvebu-cortexa9_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/mvebu/cortexa9/openwrt-sdk-24.10.0-mvebu-cortexa9_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: arm_cortex-a15_neon-vfpv4 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/ipq806x/generic/openwrt-sdk-23.05.5-ipq806x-generic_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/ipq806x/generic/openwrt-sdk-24.10.0-ipq806x-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mips_24kc - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/ath79/generic/openwrt-sdk-23.05.5-ath79-generic_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/ath79/generic/openwrt-sdk-24.10.0-ath79-generic_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mips_4kec - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/realtek/rtl838x/openwrt-sdk-23.05.5-realtek-rtl838x_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/realtek/rtl838x/openwrt-sdk-24.10.0-realtek-rtl838x_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mips_mips32 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/bcm63xx/generic/openwrt-sdk-23.05.5-bcm63xx-generic_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/bcm53xx/generic/openwrt-sdk-24.10.0-bcm53xx-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mipsel_24kc - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/ramips/rt288x/openwrt-sdk-23.05.5-ramips-rt288x_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/ramips/rt288x/openwrt-sdk-24.10.0-ramips-rt288x_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mipsel_74kc - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/ramips/rt3883/openwrt-sdk-23.05.5-ramips-rt3883_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/ramips/rt3883/openwrt-sdk-24.10.0-ramips-rt3883_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" - platform: mipsel_mips32 - url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/bcm47xx/generic/openwrt-sdk-23.05.5-bcm47xx-generic_gcc-12.3.0_musl.Linux-x86_64.tar.xz + url_sdk: https://downloads.openwrt.org/releases/24.10.0/targets/bcm47xx/generic/openwrt-sdk-24.10.0-bcm47xx-generic_gcc-13.3.0_musl.Linux-x86_64.tar.zst + sdk_ver: "24.10" steps: - name: Initialization ${{ matrix.platform }} compile environment @@ -239,7 +261,7 @@ jobs: run: | wget ${{ matrix.url_sdk }} file_name=$(echo ${{matrix.url_sdk}} | awk -F/ '{print $NF}') - mkdir sdk && tar -xJf $file_name -C ./sdk --strip-components=1 + mkdir sdk && tar --zstd -x -f $file_name -C ./sdk --strip-components=1 cd sdk - name: SSH connection to Actions @@ -249,10 +271,10 @@ jobs: - name: ${{ matrix.platform }} feeds configuration packages run: | cd sdk - echo "src-git base https://github.com/openwrt/openwrt.git;openwrt-23.05" > feeds.conf - echo "src-git packages https://github.com/openwrt/packages.git;openwrt-23.05" >> feeds.conf - echo "src-git luci https://github.com/openwrt/luci.git;openwrt-23.05" >> feeds.conf - echo "src-git routing https://git.openwrt.org/feed/routing.git;openwrt-23.05" >> feeds.conf + echo "src-git base https://github.com/openwrt/openwrt.git;openwrt-${{ matrix.sdk_ver }}" > feeds.conf + echo "src-git packages https://github.com/openwrt/packages.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf + echo "src-git luci https://github.com/openwrt/luci.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf + echo "src-git routing https://git.openwrt.org/feed/routing.git;openwrt-${{ matrix.sdk_ver }}" >> feeds.conf echo "src-git passwall_packages https://github.com/${{ env.packages }}.git;main" >> feeds.conf echo "src-git passwall2 https://github.com/${{ env.passwall2 }}.git;main" >> feeds.conf @@ -261,7 +283,7 @@ jobs: ./scripts/feeds install luci-app-passwall2 rm -rf feeds/packages/lang/golang - git clone https://github.com/sbwml/packages_lang_golang -b 23.x feeds/packages/lang/golang + git clone https://github.com/sbwml/packages_lang_golang -b 24.x feeds/packages/lang/golang echo "CONFIG_ALL_NONSHARED=n" > .config echo "CONFIG_ALL_KMODS=n" >> .config @@ -292,27 +314,26 @@ jobs: - name: ${{ matrix.platform }} download run: | cd sdk - make download -j1 + make download -j$(nproc) find dl -size -1024c -exec ls -l {} \; - name: ${{ matrix.platform }} compile id: compile run: | cd sdk - make package/feeds/passwall_packages/chinadns-ng/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/geoview/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/tcping/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/xray-core/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/v2ray-geodata/compile -j1 V=s 2>/dev/null - - make package/feeds/passwall_packages/hysteria/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/naiveproxy/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/shadowsocks-rust/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/shadowsocksr-libev/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/simple-obfs/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/sing-box/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/tuic-client/compile -j1 V=s 2>/dev/null - make package/feeds/passwall_packages/v2ray-plugin/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/chinadns-ng/compile -j$(nproc) V=s + make package/feeds/passwall_packages/geoview/compile -j$(nproc) V=s + make package/feeds/passwall_packages/tcping/compile -j$(nproc) V=s + make package/feeds/passwall_packages/xray-core/compile -j$(nproc) V=s + make package/feeds/passwall_packages/v2ray-geodata/compile -j$(nproc) V=s + make package/feeds/passwall_packages/hysteria/compile -j$(nproc) V=s + make package/feeds/passwall_packages/naiveproxy/compile -j$(nproc) V=s + make package/feeds/passwall_packages/shadowsocks-rust/compile -j$(nproc) V=s + make package/feeds/passwall_packages/shadowsocksr-libev/compile -j$(nproc) V=s + make package/feeds/passwall_packages/simple-obfs/compile -j$(nproc) V=s + make package/feeds/passwall_packages/sing-box/compile -j$(nproc) V=s + make package/feeds/passwall_packages/tuic-client/compile -j$(nproc) V=s + make package/feeds/passwall_packages/v2ray-plugin/compile -j$(nproc) V=s echo "status=success" >> $GITHUB_OUTPUT diff --git a/openwrt-passwall2/luci-app-passwall2/Makefile b/openwrt-passwall2/luci-app-passwall2/Makefile index ef593f6b6b..146cdf373d 100644 --- a/openwrt-passwall2/luci-app-passwall2/Makefile +++ b/openwrt-passwall2/luci-app-passwall2/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=25.1.27 +PKG_VERSION:=25.3.2 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua index bc333c3cd3..ac0bb9e70a 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua @@ -14,6 +14,7 @@ end local normal_list = {} local balancing_list = {} +local urltest_list = {} local shunt_list = {} local iface_list = {} for k, v in pairs(nodes_table) do @@ -23,6 +24,9 @@ for k, v in pairs(nodes_table) do if v.protocol and v.protocol == "_balancing" then balancing_list[#balancing_list + 1] = v end + if v.protocol and v.protocol == "_urltest" then + urltest_list[#urltest_list + 1] = v + end if v.protocol and v.protocol == "_shunt" then shunt_list[#shunt_list + 1] = v end @@ -130,6 +134,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -174,6 +181,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -199,6 +209,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -214,7 +227,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then o:value("", translate("Close")) o:value("main", translate("Preproxy Node")) for k1, v1 in pairs(normal_list) do - if v1.protocol ~= "_balancing" then + if v1.protocol ~= "_balancing" and v1.protocol ~= "_urltest" then o:depends({ [vid .. "-default_node"] = v1.id, [vid .. "-preproxy_enabled"] = "1" }) end end diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua index 75bac734a8..da017c850c 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua @@ -96,6 +96,8 @@ o.cfgvalue = function(t, n) local protocol = m:get(n, "protocol") if protocol == "_balancing" then protocol = translate("Balancing") + elseif protocol == "_urltest" then + protocol = "URLTest" elseif protocol == "_shunt" then protocol = translate("Shunt") elseif protocol == "vmess" then diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index db866d78a8..6191d6081c 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -56,6 +56,7 @@ end if singbox_tags:find("with_quic") then o:value("hysteria2", "Hysteria2") end +o:value("_urltest", translate("URLTest")) o:value("_shunt", translate("Shunt")) o:value("_iface", translate("Custom Interface")) @@ -65,6 +66,7 @@ o:depends({ [_n("protocol")] = "_iface" }) local nodes_table = {} local iface_table = {} +local urltest_table = {} for k, e in ipairs(api.get_valid_nodes()) do if e.node_type == "normal" then nodes_table[#nodes_table + 1] = { @@ -79,6 +81,12 @@ for k, e in ipairs(api.get_valid_nodes()) do remark = e["remark"] } end + if e.protocol == "_urltest" then + urltest_table[#urltest_table + 1] = { + id = e[".name"], + remark = e["remark"] + } + end end local socks_list = {} @@ -91,6 +99,44 @@ m.uci:foreach(appname, "socks", function(s) end end) +--[[ URLTest ]] +o = s:option(DynamicList, _n("urltest_node"), translate("URLTest node list"), translate("List of nodes to test, document")) +o:depends({ [_n("protocol")] = "_urltest" }) +for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end + +o = s:option(Value, _n("urltest_url"), translate("Probe URL")) +o:depends({ [_n("protocol")] = "_urltest" }) +o:value("https://cp.cloudflare.com/", "Cloudflare") +o:value("https://www.gstatic.com/generate_204", "Gstatic") +o:value("https://www.google.com/generate_204", "Google") +o:value("https://www.youtube.com/generate_204", "YouTube") +o:value("https://connect.rom.miui.com/generate_204", "MIUI (CN)") +o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud (CN)") +o.default = "https://www.gstatic.com/generate_204" +o.description = translate("The URL used to detect the connection status.") + +o = s:option(Value, _n("urltest_interval"), translate("Test interval")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "180" +o.description = translate("The test interval in seconds.") .. "
" .. + translate("Test interval must be less or equal than idle timeout.") + +o = s:option(Value, _n("urltest_tolerance"), translate("Test tolerance"), translate("The test tolerance in milliseconds.")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "50" + +o = s:option(Value, _n("urltest_idle_timeout"), translate("Idle timeout"), translate("The idle timeout in seconds.")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "1800" + +o = s:option(Flag, _n("urltest_interrupt_exist_connections"), translate("Interrupt existing connections")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.default = "0" +o.description = translate("Interrupt existing connections when the selected outbound has changed.") + -- [[ 分流模块 ]] if #nodes_table > 0 then o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy")) @@ -101,6 +147,9 @@ if #nodes_table > 0 then for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end @@ -124,6 +173,9 @@ m.uci:foreach(appname, "shunt_rules", function(e) for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end @@ -155,6 +207,9 @@ if #nodes_table > 0 then for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua index 1cc72bc96c..65e873c794 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua @@ -314,7 +314,7 @@ function strToTable(str) end function is_normal_node(e) - if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then + if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then return false end return true @@ -444,7 +444,7 @@ function get_valid_nodes() uci:foreach(appname, "nodes", function(e) e.id = e[".name"] if e.type and e.remarks then - if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then + if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then local type = e.type if type == "sing-box" then type = "Sing-Box" end e["remark"] = "%s:[%s] " % {type .. " " .. i18n.translatef(e.protocol), e.remarks} @@ -494,7 +494,7 @@ end function get_node_remarks(n) local remarks = "" if n then - if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface") then + if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface" or n.protocol == "_urltest") then remarks = "%s:[%s] " % {n.type .. " " .. i18n.translatef(n.protocol), n.remarks} else local type2 = n.type @@ -1114,7 +1114,7 @@ end function get_version() local version = sys.exec("opkg list-installed luci-app-passwall2 2>/dev/null | awk '{print $3}'") if not version or #version == 0 then - version = sys.exec("apk info -L luci-app-passwall2 2>/dev/null | awk 'NR == 1 {print $1}' | cut -d'-' -f4-") + version = sys.exec("apk list luci-app-passwall2 2>/dev/null | awk '/installed/ {print $1}' | cut -d'-' -f4-") end return version or "" end diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index c590ab38f3..ff2761437e 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -892,6 +892,54 @@ function gen_config(var) node.port = server_port end + local function gen_urltest(_node) + local urltest_id = _node[".name"] + local urltest_tag = "urltest-" .. urltest_id + -- existing urltest + for _, v in ipairs(outbounds) do + if v.tag == urltest_tag then + return urltest_tag + end + end + -- new urltest + local ut_nodes = _node.urltest_node + local valid_nodes = {} + for i = 1, #ut_nodes do + local ut_node_id = ut_nodes[i] + local ut_node_tag = "ut-" .. ut_node_id + local is_new_ut_node = true + for _, outbound in ipairs(outbounds) do + if string.sub(outbound.tag, 1, #ut_node_tag) == ut_node_tag then + is_new_ut_node = false + valid_nodes[#valid_nodes + 1] = outbound.tag + break + end + end + if is_new_ut_node then + local ut_node = uci:get_all(appname, ut_node_id) + local outbound = gen_outbound(flag, ut_node, ut_node_tag) + if outbound then + outbound.tag = outbound.tag .. ":" .. ut_node.remarks + table.insert(outbounds, outbound) + valid_nodes[#valid_nodes + 1] = outbound.tag + end + end + end + if #valid_nodes == 0 then return nil end + local outbound = { + type = "urltest", + tag = urltest_tag, + outbounds = valid_nodes, + url = _node.urltest_url or "https://www.gstatic.com/generate_204", + interval = _node.urltest_interval and tonumber(_node.urltest_interval) and string.format("%dm", tonumber(_node.urltest_interval) / 60) or "3m", + tolerance = _node.urltest_tolerance and tonumber(_node.urltest_tolerance) and tonumber(_node.urltest_tolerance) or 50, + idle_timeout = _node.urltest_idle_timeout and tonumber(_node.urltest_idle_timeout) and string.format("%dm", tonumber(_node.urltest_idle_timeout) / 60) or "30m", + interrupt_exist_connections = (_node.urltest_interrupt_exist_connections == "true" or _node.urltest_interrupt_exist_connections == "1") and true or false + } + table.insert(outbounds, outbound) + return urltest_tag + end + local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name) if not node or not outbound or not outbounds_table then return nil end local default_outTag = outbound.tag @@ -1046,6 +1094,8 @@ function gen_config(var) end end end + elseif _node.protocol == "_urltest" then + rule_outboundTag = gen_urltest(_node) elseif _node.protocol == "_iface" then if _node.iface then local _outbound = { @@ -1220,6 +1270,10 @@ function gen_config(var) for index, value in ipairs(rules) do table.insert(route.rules, rules[index]) end + elseif node.protocol == "_urltest" then + if node.urltest_node then + COMMON.default_outbound_tag = gen_urltest(node) + end elseif node.protocol == "_iface" then if node.iface then local outbound = { diff --git a/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po b/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po index 8950086d07..7ec3a16cee 100644 --- a/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po @@ -1423,9 +1423,6 @@ msgstr "最大并发连接数" msgid "XUDP Mux concurrency" msgstr "XUDP 最大并发连接数" -msgid "Mux idle timeout" -msgstr "最大闲置时间" - msgid "Padding" msgstr "填充" @@ -1444,9 +1441,6 @@ msgstr "推荐值:Sec-WebSocket-Protocol" msgid "Health check" msgstr "健康检查" -msgid "Idle timeout" -msgstr "闲置时间" - msgid "Health check timeout" msgstr "检查超时时间" @@ -1647,3 +1641,39 @@ msgstr "是否要恢复客户端默认配置?" msgid "Are you sure you want to restore the client to default settings?" msgstr "是否真的要恢复客户端默认配置?" + +msgid "_urltest" +msgstr "URLTest" + +msgid "URLTest node list" +msgstr "URLTest 节点列表" + +msgid "List of nodes to test, document" +msgstr "要测试的节点列表,文档原理" + +msgid "Test interval" +msgstr "测试间隔" + +msgid "The test interval in seconds." +msgstr "测试间隔时间(单位:秒)。" + +msgid "Test interval must be less or equal than idle timeout." +msgstr "测试间隔时间必须小于或等于空闲超时时间。" + +msgid "Test tolerance" +msgstr "测试容差" + +msgid "The test tolerance in milliseconds." +msgstr "测试容差时间(单位:毫秒)。" + +msgid "Idle timeout" +msgstr "空闲超时" + +msgid "The idle timeout in seconds." +msgstr "空闲超时时间(单位:秒)。" + +msgid "Interrupt existing connections" +msgstr "中断现有连接" + +msgid "Interrupt existing connections when the selected outbound has changed." +msgstr "当选择的出站发生变化时中断现有连接。" diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh index f07d50ab53..353fe85720 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -589,7 +589,7 @@ run_socks() { if [ "$type" == "sing-box" ] || [ "$type" == "xray" ]; then local protocol=$(config_n_get $node protocol) - if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ]; then + if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ] || [ "$protocol" == "_urltest" ]; then unset error_msg fi fi diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index a3f2cabc53..b8f7229a65 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -303,6 +303,36 @@ do end } end + elseif node.protocol and node.protocol == '_urltest' then + local flag = "Sing-Box URLTest节点[" .. node_id .. "]列表" + local currentNodes = {} + local newNodes = {} + if node.urltest_node then + for k, node in pairs(node.urltest_node) do + currentNodes[#currentNodes + 1] = { + log = false, + node = node, + currentNode = node and uci:get_all(appname, node) or nil, + remarks = node, + set = function(o, server) + if o and server and server ~= "nil" then + table.insert(o.newNodes, server) + end + end + } + end + end + CONFIG[#CONFIG + 1] = { + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, node_id, "urltest_node", newNodes or {}) + end + end + } else --前置代理节点 local currentNode = uci:get_all(appname, node_id) or nil @@ -1682,7 +1712,7 @@ local execute = function() f:close() raw = trim(stdout) local old_md5 = value.md5 or "" - local new_md5 = luci.sys.exec("[ -f " .. tmp_file .. " ] && md5sum " .. tmp_file .. " | awk '{print $1}' || echo 0") + local new_md5 = luci.sys.exec("[ -f " .. tmp_file .. " ] && md5sum " .. tmp_file .. " | awk '{print $1}' || echo 0"):gsub("\n", "") os.remove(tmp_file) if old_md5 == new_md5 then log('订阅:【' .. remark .. '】没有变化,无需更新。') diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/test.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/test.sh index 7fa5b3189e..a985a9cd66 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/test.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/test.sh @@ -71,7 +71,7 @@ url_test_node() { sleep 1s result=$(curl --connect-timeout 3 -o /dev/null -I -skL -w "%{http_code}:%{time_starttransfer}" -x $curlx "https://www.google.com/generate_204") pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 - rm -rf "/tmp/etc/${CONFIG}/url_test_${node_id}.json" + rm -rf "/tmp/etc/${CONFIG}/url_test_${node_id}"*.json } echo $result } diff --git a/shadowsocks-rust/.github/workflows/build-and-test.yml b/shadowsocks-rust/.github/workflows/build-and-test.yml index 510dc25910..a0bda81a8e 100644 --- a/shadowsocks-rust/.github/workflows/build-and-test.yml +++ b/shadowsocks-rust/.github/workflows/build-and-test.yml @@ -11,7 +11,7 @@ env: RUST_LOG: "trace" jobs: - build-test-check: + build-and-test: strategy: matrix: platform: diff --git a/shadowsocks-rust/.github/workflows/build-docker-image.yml b/shadowsocks-rust/.github/workflows/build-docker-image.yml index a042a28ad9..214e3c3eb3 100644 --- a/shadowsocks-rust/.github/workflows/build-docker-image.yml +++ b/shadowsocks-rust/.github/workflows/build-docker-image.yml @@ -5,7 +5,7 @@ on: - v* jobs: - build: + build-docker-image: runs-on: ubuntu-latest strategy: matrix: diff --git a/shadowsocks-rust/.github/workflows/build-msrv.yml b/shadowsocks-rust/.github/workflows/build-msrv.yml index ce1e11129e..d5bf1211e5 100644 --- a/shadowsocks-rust/.github/workflows/build-msrv.yml +++ b/shadowsocks-rust/.github/workflows/build-msrv.yml @@ -11,7 +11,7 @@ env: RUST_LOG: "trace" jobs: - shadowsocks-rust: + build-msrv-shadowsocks-rust: strategy: matrix: platform: @@ -28,9 +28,9 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install 1.80 - rustup default 1.80 - rustup override set 1.80 + rustup toolchain install 1.83 + rustup default 1.83 + rustup override set 1.83 - name: Build with All Features Enabled (Unix) if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }} run: cargo build --verbose --features "full-extra local-flow-stat utility-url-outline" @@ -38,7 +38,7 @@ jobs: if: ${{ runner.os == 'Windows' }} run: cargo build --verbose --features "full-extra local-flow-stat utility-url-outline winservice" - shadowsocks-service: + build-msrv-shadowsocks-service: strategy: matrix: platform: @@ -55,13 +55,13 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install 1.80 - rustup default 1.80 - rustup override set 1.80 + rustup toolchain install 1.83 + rustup default 1.83 + rustup override set 1.83 - name: Build with All Features Enabled run: cargo build --manifest-path crates/shadowsocks-service/Cargo.toml --verbose --features "full dns-over-tls dns-over-https dns-over-h3 local-dns local-flow-stat local-http-rustls local-tun local-fake-dns local-online-config stream-cipher aead-cipher-extra aead-cipher-2022 aead-cipher-2022-extra security-replay-attack-detect" - shadowsocks: + build-msrv-shadowsocks: strategy: matrix: platform: diff --git a/shadowsocks-rust/.github/workflows/build-nightly-release.yml b/shadowsocks-rust/.github/workflows/build-nightly-release.yml index ed3ef2db5f..3d923fda6d 100644 --- a/shadowsocks-rust/.github/workflows/build-nightly-release.yml +++ b/shadowsocks-rust/.github/workflows/build-nightly-release.yml @@ -8,7 +8,7 @@ env: CARGO_TERM_COLOR: always jobs: - build-cross: + build-nightly-cross: runs-on: ubuntu-latest env: RUST_BACKTRACE: full @@ -70,7 +70,7 @@ jobs: name: ${{ matrix.platform.target }} path: build/release/* - build-unix: + build-nightly-unix: runs-on: ${{ matrix.os }} env: BUILD_EXTRA_FEATURES: "full" @@ -111,7 +111,7 @@ jobs: name: ${{ matrix.target }} path: build/release/* - build-windows: + build-nightly-windows: runs-on: windows-latest env: RUSTFLAGS: "-C target-feature=+crt-static" diff --git a/shadowsocks-rust/.github/workflows/build-release.yml b/shadowsocks-rust/.github/workflows/build-release.yml index 34763f451c..599b90549e 100644 --- a/shadowsocks-rust/.github/workflows/build-release.yml +++ b/shadowsocks-rust/.github/workflows/build-release.yml @@ -14,7 +14,7 @@ env: CARGO_TERM_COLOR: always jobs: - build-cross: + build-release-cross: runs-on: ubuntu-latest env: RUST_BACKTRACE: full @@ -117,7 +117,7 @@ jobs: prerelease: ${{ contains(github.ref_name, '-') }} tag_name: ${{ inputs.tag || github.ref_name }} - build-unix: + build-release-unix: runs-on: ${{ matrix.os }} env: BUILD_EXTRA_FEATURES: "full" @@ -162,7 +162,7 @@ jobs: prerelease: ${{ contains(github.ref_name, '-') }} tag_name: ${{ inputs.tag || github.ref_name }} - build-windows: + build-release-windows: runs-on: windows-latest env: RUSTFLAGS: "-C target-feature=+crt-static" diff --git a/shadowsocks-rust/.github/workflows/deny-check.yml b/shadowsocks-rust/.github/workflows/deny-check.yml index 5e7a6b8e04..ece405af39 100644 --- a/shadowsocks-rust/.github/workflows/deny-check.yml +++ b/shadowsocks-rust/.github/workflows/deny-check.yml @@ -1,7 +1,7 @@ name: Cargo Deny Check on: [push, pull_request] jobs: - cargo-deny: + deny-check: runs-on: ubuntu-latest strategy: matrix: diff --git a/shadowsocks-rust/Cargo.lock b/shadowsocks-rust/Cargo.lock index ea7b9209a2..35178e1adb 100644 --- a/shadowsocks-rust/Cargo.lock +++ b/shadowsocks-rust/Cargo.lock @@ -956,9 +956,9 @@ dependencies = [ [[package]] name = "etherparse" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d8a704b617484e9d867a0423cd45f7577f008c4068e2e33378f8d3860a6d73" +checksum = "b14e4ac78394e3ea04edbbc412099cf54f2f52ded51efb79c466a282729399d2" dependencies = [ "arrayvec", ] @@ -3232,7 +3232,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project", - "rand 0.8.5", + "rand 0.9.0", "sendfd", "serde", "serde_json", @@ -3299,7 +3299,7 @@ dependencies = [ "mimalloc", "mime", "qrcode", - "rand 0.8.5", + "rand 0.9.0", "reqwest", "rpassword", "rpmalloc", @@ -3349,7 +3349,7 @@ dependencies = [ "nix", "once_cell", "pin-project", - "rand 0.8.5", + "rand 0.9.0", "regex", "rustls-native-certs", "serde", diff --git a/shadowsocks-rust/Cargo.toml b/shadowsocks-rust/Cargo.toml index 30c76ba2bf..f94fada023 100644 --- a/shadowsocks-rust/Cargo.toml +++ b/shadowsocks-rust/Cargo.toml @@ -9,7 +9,7 @@ documentation = "https://docs.rs/shadowsocks-rust" keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"] license = "MIT" edition = "2021" -rust-version = "1.80" +rust-version = "1.83" [badges] maintenance = { status = "passively-maintained" } @@ -229,7 +229,7 @@ directories = "6.0" xdg = "2.5" rpassword = "7.3" libc = { version = "0.2", features = ["extra_traits"] } -rand = "0.8" +rand = "0.9" futures = "0.3" tokio = { version = "1", features = ["rt", "signal"] } diff --git a/shadowsocks-rust/clippy.toml b/shadowsocks-rust/clippy.toml index 65f527ae42..f234c90141 100644 --- a/shadowsocks-rust/clippy.toml +++ b/shadowsocks-rust/clippy.toml @@ -1 +1 @@ -msrv = "1.77" +msrv = "1.83" diff --git a/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml b/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml index ab59125172..26bf610e30 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml +++ b/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml @@ -9,7 +9,7 @@ documentation = "https://docs.rs/shadowsocks-service" keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"] license = "MIT" edition = "2021" -rust-version = "1.80" +rust-version = "1.83" [badges] maintenance = { status = "passively-maintained" } @@ -134,7 +134,7 @@ lru_time_cache = "0.11" bytes = "1.7" byte_string = "1.0" byteorder = "1.5" -rand = { version = "0.8", features = ["small_rng"] } +rand = { version = "0.9", features = ["small_rng"] } sled = { version = "0.34.7", optional = true } futures = "0.3" @@ -181,7 +181,7 @@ brotli = { version = "7.0", optional = true } zstd = { version = "0.13", optional = true } tun = { version = "0.7", optional = true, features = ["async"] } -etherparse = { version = "0.16", optional = true } +etherparse = { version = "0.17", optional = true } smoltcp = { version = "0.12", optional = true, default-features = false, features = [ "std", "log", diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/local/dns/server.rs b/shadowsocks-rust/crates/shadowsocks-service/src/local/dns/server.rs index a0d47cae4b..721c55351b 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/local/dns/server.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/local/dns/server.rs @@ -23,7 +23,6 @@ use hickory_resolver::proto::{ rr::{DNSClass, Name, RData, RecordType}, }; use log::{debug, error, info, trace, warn}; -use rand::{thread_rng, Rng}; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::{TcpStream, UdpSocket}, @@ -854,7 +853,7 @@ impl DnsClient { async fn lookup_remote_inner(&self, query: &Query, remote_addr: &Address) -> io::Result { let mut message = Message::new(); - message.set_id(thread_rng().gen()); + message.set_id(rand::random()); message.set_recursion_desired(true); message.add_query(query.clone()); @@ -884,7 +883,7 @@ impl DnsClient { // Then this future will be disabled and have no effect // // Randomly choose from 500ms ~ 1.5s for preventing obvious request pattern - let sleep_time = thread_rng().gen_range(500..=1500); + let sleep_time = rand::random_range(500..=1500); time::sleep(Duration::from_millis(sleep_time)).await; let server = self.balancer.best_tcp_server(); @@ -933,7 +932,7 @@ impl DnsClient { async fn lookup_local_inner(&self, query: &Query, local_addr: &NameServerAddr) -> io::Result { let mut message = Message::new(); - message.set_id(thread_rng().gen()); + message.set_id(rand::random()); message.set_recursion_desired(true); message.add_query(query.clone()); diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/local/dns/upstream.rs b/shadowsocks-rust/crates/shadowsocks-service/src/local/dns/upstream.rs index 9500e4db45..fa7a6c049e 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/local/dns/upstream.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/local/dns/upstream.rs @@ -15,7 +15,6 @@ use bytes::{BufMut, BytesMut}; use hickory_resolver::proto::{op::Message, ProtoError, ProtoErrorKind}; use log::{error, trace}; use lru_time_cache::{Entry, LruCache}; -use rand::{thread_rng, Rng}; use shadowsocks::{ config::ServerConfig, context::SharedContext, @@ -139,7 +138,7 @@ impl DnsClient { async fn inner_lookup(&mut self, msg: &mut Message) -> Result { // Make a random ID - msg.set_id(thread_rng().gen()); + msg.set_id(rand::random()); trace!("DNS lookup {:?}", msg); diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/local/net/udp/association.rs b/shadowsocks-rust/crates/shadowsocks-service/src/local/net/udp/association.rs index d0563158ea..bef3ac9a6a 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/local/net/udp/association.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/local/net/udp/association.rs @@ -234,13 +234,18 @@ where } thread_local! { - static CLIENT_SESSION_RNG: RefCell = RefCell::new(SmallRng::from_entropy()); + static CLIENT_SESSION_RNG: RefCell = RefCell::new(SmallRng::from_os_rng()); } /// Generate an AEAD-2022 Client SessionID #[inline] pub fn generate_client_session_id() -> u64 { - CLIENT_SESSION_RNG.with(|rng| rng.borrow_mut().gen()) + loop { + let id = CLIENT_SESSION_RNG.with(|rng| rng.borrow_mut().random()); + if id != 0 { + break id; + } + } } impl UdpAssociationContext diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/server/udprelay.rs b/shadowsocks-rust/crates/shadowsocks-service/src/server/udprelay.rs index e1aba396b3..f1379be559 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/server/udprelay.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/server/udprelay.rs @@ -462,12 +462,17 @@ impl Drop for UdpAssociationContext { } thread_local! { - static CLIENT_SESSION_RNG: RefCell = RefCell::new(SmallRng::from_entropy()); + static CLIENT_SESSION_RNG: RefCell = RefCell::new(SmallRng::from_os_rng()); } #[inline] fn generate_server_session_id() -> u64 { - CLIENT_SESSION_RNG.with(|rng| rng.borrow_mut().gen()) + loop { + let id = CLIENT_SESSION_RNG.with(|rng| rng.borrow_mut().random()); + if id != 0 { + break id; + } + } } impl UdpAssociationContext { diff --git a/shadowsocks-rust/crates/shadowsocks/Cargo.toml b/shadowsocks-rust/crates/shadowsocks/Cargo.toml index 32ce7a441b..60695ee5f7 100644 --- a/shadowsocks-rust/crates/shadowsocks/Cargo.toml +++ b/shadowsocks-rust/crates/shadowsocks/Cargo.toml @@ -62,7 +62,7 @@ spin = { version = "0.9", features = ["std"] } pin-project = "1.1" bloomfilter = { version = "3.0.0", optional = true } thiserror = "2.0" -rand = { version = "0.8", optional = true } +rand = { version = "0.9", optional = true } lru_time_cache = { version = "0.11", optional = true } serde = { version = "1.0", features = ["derive"] } diff --git a/shadowsocks-rust/crates/shadowsocks/src/relay/mod.rs b/shadowsocks-rust/crates/shadowsocks/src/relay/mod.rs index 52b05a840b..6f4676645b 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/relay/mod.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/relay/mod.rs @@ -18,11 +18,11 @@ fn get_aead_2022_padding_size(payload: &[u8]) -> usize { use rand::{rngs::SmallRng, Rng, SeedableRng}; thread_local! { - static PADDING_RNG: RefCell = RefCell::new(SmallRng::from_entropy()); + static PADDING_RNG: RefCell = RefCell::new(SmallRng::from_os_rng()); } if payload.is_empty() { - PADDING_RNG.with(|rng| rng.borrow_mut().gen::() % AEAD2022_MAX_PADDING_SIZE) + PADDING_RNG.with(|rng| rng.borrow_mut().random_range::(0..=AEAD2022_MAX_PADDING_SIZE)) } else { 0 } diff --git a/shadowsocks-rust/crates/shadowsocks/src/relay/udprelay/proxy_socket.rs b/shadowsocks-rust/crates/shadowsocks/src/relay/udprelay/proxy_socket.rs index 5c1563ed7d..8be8f63c67 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/relay/udprelay/proxy_socket.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/relay/udprelay/proxy_socket.rs @@ -92,9 +92,7 @@ impl ProxySocket { context: SharedContext, svr_cfg: &ServerConfig, ) -> ProxySocketResult> { - ProxySocket::connect_with_opts(context, svr_cfg, &DEFAULT_CONNECT_OPTS) - .await - .map_err(Into::into) + ProxySocket::connect_with_opts(context, svr_cfg, &DEFAULT_CONNECT_OPTS).await } /// Create a client to communicate with Shadowsocks' UDP server (outbound) @@ -127,9 +125,7 @@ impl ProxySocket { context: SharedContext, svr_cfg: &ServerConfig, ) -> ProxySocketResult> { - ProxySocket::bind_with_opts(context, svr_cfg, AcceptOpts::default()) - .await - .map_err(Into::into) + ProxySocket::bind_with_opts(context, svr_cfg, AcceptOpts::default()).await } /// Create a `ProxySocket` binding to a specific address (inbound) @@ -240,9 +236,7 @@ where /// Send a UDP packet to addr through proxy #[inline] pub async fn send(&self, addr: &Address, payload: &[u8]) -> ProxySocketResult { - self.send_with_ctrl(addr, &DEFAULT_SOCKET_CONTROL, payload) - .await - .map_err(Into::into) + self.send_with_ctrl(addr, &DEFAULT_SOCKET_CONTROL, payload).await } /// Send a UDP packet to addr through proxy with `ControlData` @@ -391,9 +385,7 @@ where /// Send a UDP packet to target through proxy `target` pub async fn send_to(&self, target: SocketAddr, addr: &Address, payload: &[u8]) -> ProxySocketResult { - self.send_to_with_ctrl(target, addr, &DEFAULT_SOCKET_CONTROL, payload) - .await - .map_err(Into::into) + self.send_to_with_ctrl(target, addr, &DEFAULT_SOCKET_CONTROL, payload).await } /// Send a UDP packet to target through proxy `target` diff --git a/shadowsocks-rust/src/service/genkey.rs b/shadowsocks-rust/src/service/genkey.rs index a28eaa2b8f..fa49a0e305 100644 --- a/shadowsocks-rust/src/service/genkey.rs +++ b/shadowsocks-rust/src/service/genkey.rs @@ -4,7 +4,6 @@ use std::process::ExitCode; use base64::Engine as _; use clap::{builder::PossibleValuesParser, Arg, ArgAction, ArgMatches, Command}; -use rand::RngCore; use shadowsocks_service::shadowsocks::crypto::{available_ciphers, CipherKind}; @@ -34,8 +33,7 @@ pub fn main(matches: &ArgMatches) -> ExitCode { let key_len = method.key_len(); if key_len > 0 { let mut key = vec![0u8; key_len]; - let mut rng = rand::thread_rng(); - rng.fill_bytes(&mut key); + rand::fill(key.as_mut_slice()); let encoded_key = base64::engine::general_purpose::STANDARD.encode(&key); println!("{encoded_key}"); diff --git a/small/luci-app-passwall/Makefile b/small/luci-app-passwall/Makefile index af6e04ac59..aca3e70dff 100644 --- a/small/luci-app-passwall/Makefile +++ b/small/luci-app-passwall/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall -PKG_VERSION:=25.2.12 +PKG_VERSION:=25.3.2 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/small/luci-app-passwall2/Makefile b/small/luci-app-passwall2/Makefile index ef593f6b6b..146cdf373d 100644 --- a/small/luci-app-passwall2/Makefile +++ b/small/luci-app-passwall2/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=25.1.27 +PKG_VERSION:=25.3.2 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua index bc333c3cd3..ac0bb9e70a 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua @@ -14,6 +14,7 @@ end local normal_list = {} local balancing_list = {} +local urltest_list = {} local shunt_list = {} local iface_list = {} for k, v in pairs(nodes_table) do @@ -23,6 +24,9 @@ for k, v in pairs(nodes_table) do if v.protocol and v.protocol == "_balancing" then balancing_list[#balancing_list + 1] = v end + if v.protocol and v.protocol == "_urltest" then + urltest_list[#urltest_list + 1] = v + end if v.protocol and v.protocol == "_shunt" then shunt_list[#shunt_list + 1] = v end @@ -130,6 +134,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -174,6 +181,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -199,6 +209,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -214,7 +227,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then o:value("", translate("Close")) o:value("main", translate("Preproxy Node")) for k1, v1 in pairs(normal_list) do - if v1.protocol ~= "_balancing" then + if v1.protocol ~= "_balancing" and v1.protocol ~= "_urltest" then o:depends({ [vid .. "-default_node"] = v1.id, [vid .. "-preproxy_enabled"] = "1" }) end end diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua index 75bac734a8..da017c850c 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua @@ -96,6 +96,8 @@ o.cfgvalue = function(t, n) local protocol = m:get(n, "protocol") if protocol == "_balancing" then protocol = translate("Balancing") + elseif protocol == "_urltest" then + protocol = "URLTest" elseif protocol == "_shunt" then protocol = translate("Shunt") elseif protocol == "vmess" then diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index db866d78a8..6191d6081c 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -56,6 +56,7 @@ end if singbox_tags:find("with_quic") then o:value("hysteria2", "Hysteria2") end +o:value("_urltest", translate("URLTest")) o:value("_shunt", translate("Shunt")) o:value("_iface", translate("Custom Interface")) @@ -65,6 +66,7 @@ o:depends({ [_n("protocol")] = "_iface" }) local nodes_table = {} local iface_table = {} +local urltest_table = {} for k, e in ipairs(api.get_valid_nodes()) do if e.node_type == "normal" then nodes_table[#nodes_table + 1] = { @@ -79,6 +81,12 @@ for k, e in ipairs(api.get_valid_nodes()) do remark = e["remark"] } end + if e.protocol == "_urltest" then + urltest_table[#urltest_table + 1] = { + id = e[".name"], + remark = e["remark"] + } + end end local socks_list = {} @@ -91,6 +99,44 @@ m.uci:foreach(appname, "socks", function(s) end end) +--[[ URLTest ]] +o = s:option(DynamicList, _n("urltest_node"), translate("URLTest node list"), translate("List of nodes to test, document")) +o:depends({ [_n("protocol")] = "_urltest" }) +for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end + +o = s:option(Value, _n("urltest_url"), translate("Probe URL")) +o:depends({ [_n("protocol")] = "_urltest" }) +o:value("https://cp.cloudflare.com/", "Cloudflare") +o:value("https://www.gstatic.com/generate_204", "Gstatic") +o:value("https://www.google.com/generate_204", "Google") +o:value("https://www.youtube.com/generate_204", "YouTube") +o:value("https://connect.rom.miui.com/generate_204", "MIUI (CN)") +o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud (CN)") +o.default = "https://www.gstatic.com/generate_204" +o.description = translate("The URL used to detect the connection status.") + +o = s:option(Value, _n("urltest_interval"), translate("Test interval")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "180" +o.description = translate("The test interval in seconds.") .. "
" .. + translate("Test interval must be less or equal than idle timeout.") + +o = s:option(Value, _n("urltest_tolerance"), translate("Test tolerance"), translate("The test tolerance in milliseconds.")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "50" + +o = s:option(Value, _n("urltest_idle_timeout"), translate("Idle timeout"), translate("The idle timeout in seconds.")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "1800" + +o = s:option(Flag, _n("urltest_interrupt_exist_connections"), translate("Interrupt existing connections")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.default = "0" +o.description = translate("Interrupt existing connections when the selected outbound has changed.") + -- [[ 分流模块 ]] if #nodes_table > 0 then o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy")) @@ -101,6 +147,9 @@ if #nodes_table > 0 then for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end @@ -124,6 +173,9 @@ m.uci:foreach(appname, "shunt_rules", function(e) for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end @@ -155,6 +207,9 @@ if #nodes_table > 0 then for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end diff --git a/small/luci-app-passwall2/luasrc/passwall2/api.lua b/small/luci-app-passwall2/luasrc/passwall2/api.lua index 1cc72bc96c..65e873c794 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/api.lua @@ -314,7 +314,7 @@ function strToTable(str) end function is_normal_node(e) - if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then + if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then return false end return true @@ -444,7 +444,7 @@ function get_valid_nodes() uci:foreach(appname, "nodes", function(e) e.id = e[".name"] if e.type and e.remarks then - if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then + if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then local type = e.type if type == "sing-box" then type = "Sing-Box" end e["remark"] = "%s:[%s] " % {type .. " " .. i18n.translatef(e.protocol), e.remarks} @@ -494,7 +494,7 @@ end function get_node_remarks(n) local remarks = "" if n then - if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface") then + if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface" or n.protocol == "_urltest") then remarks = "%s:[%s] " % {n.type .. " " .. i18n.translatef(n.protocol), n.remarks} else local type2 = n.type @@ -1114,7 +1114,7 @@ end function get_version() local version = sys.exec("opkg list-installed luci-app-passwall2 2>/dev/null | awk '{print $3}'") if not version or #version == 0 then - version = sys.exec("apk info -L luci-app-passwall2 2>/dev/null | awk 'NR == 1 {print $1}' | cut -d'-' -f4-") + version = sys.exec("apk list luci-app-passwall2 2>/dev/null | awk '/installed/ {print $1}' | cut -d'-' -f4-") end return version or "" end diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index c590ab38f3..ff2761437e 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -892,6 +892,54 @@ function gen_config(var) node.port = server_port end + local function gen_urltest(_node) + local urltest_id = _node[".name"] + local urltest_tag = "urltest-" .. urltest_id + -- existing urltest + for _, v in ipairs(outbounds) do + if v.tag == urltest_tag then + return urltest_tag + end + end + -- new urltest + local ut_nodes = _node.urltest_node + local valid_nodes = {} + for i = 1, #ut_nodes do + local ut_node_id = ut_nodes[i] + local ut_node_tag = "ut-" .. ut_node_id + local is_new_ut_node = true + for _, outbound in ipairs(outbounds) do + if string.sub(outbound.tag, 1, #ut_node_tag) == ut_node_tag then + is_new_ut_node = false + valid_nodes[#valid_nodes + 1] = outbound.tag + break + end + end + if is_new_ut_node then + local ut_node = uci:get_all(appname, ut_node_id) + local outbound = gen_outbound(flag, ut_node, ut_node_tag) + if outbound then + outbound.tag = outbound.tag .. ":" .. ut_node.remarks + table.insert(outbounds, outbound) + valid_nodes[#valid_nodes + 1] = outbound.tag + end + end + end + if #valid_nodes == 0 then return nil end + local outbound = { + type = "urltest", + tag = urltest_tag, + outbounds = valid_nodes, + url = _node.urltest_url or "https://www.gstatic.com/generate_204", + interval = _node.urltest_interval and tonumber(_node.urltest_interval) and string.format("%dm", tonumber(_node.urltest_interval) / 60) or "3m", + tolerance = _node.urltest_tolerance and tonumber(_node.urltest_tolerance) and tonumber(_node.urltest_tolerance) or 50, + idle_timeout = _node.urltest_idle_timeout and tonumber(_node.urltest_idle_timeout) and string.format("%dm", tonumber(_node.urltest_idle_timeout) / 60) or "30m", + interrupt_exist_connections = (_node.urltest_interrupt_exist_connections == "true" or _node.urltest_interrupt_exist_connections == "1") and true or false + } + table.insert(outbounds, outbound) + return urltest_tag + end + local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name) if not node or not outbound or not outbounds_table then return nil end local default_outTag = outbound.tag @@ -1046,6 +1094,8 @@ function gen_config(var) end end end + elseif _node.protocol == "_urltest" then + rule_outboundTag = gen_urltest(_node) elseif _node.protocol == "_iface" then if _node.iface then local _outbound = { @@ -1220,6 +1270,10 @@ function gen_config(var) for index, value in ipairs(rules) do table.insert(route.rules, rules[index]) end + elseif node.protocol == "_urltest" then + if node.urltest_node then + COMMON.default_outbound_tag = gen_urltest(node) + end elseif node.protocol == "_iface" then if node.iface then local outbound = { diff --git a/small/luci-app-passwall2/po/zh-cn/passwall2.po b/small/luci-app-passwall2/po/zh-cn/passwall2.po index 8950086d07..7ec3a16cee 100644 --- a/small/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/small/luci-app-passwall2/po/zh-cn/passwall2.po @@ -1423,9 +1423,6 @@ msgstr "最大并发连接数" msgid "XUDP Mux concurrency" msgstr "XUDP 最大并发连接数" -msgid "Mux idle timeout" -msgstr "最大闲置时间" - msgid "Padding" msgstr "填充" @@ -1444,9 +1441,6 @@ msgstr "推荐值:Sec-WebSocket-Protocol" msgid "Health check" msgstr "健康检查" -msgid "Idle timeout" -msgstr "闲置时间" - msgid "Health check timeout" msgstr "检查超时时间" @@ -1647,3 +1641,39 @@ msgstr "是否要恢复客户端默认配置?" msgid "Are you sure you want to restore the client to default settings?" msgstr "是否真的要恢复客户端默认配置?" + +msgid "_urltest" +msgstr "URLTest" + +msgid "URLTest node list" +msgstr "URLTest 节点列表" + +msgid "List of nodes to test, document" +msgstr "要测试的节点列表,文档原理" + +msgid "Test interval" +msgstr "测试间隔" + +msgid "The test interval in seconds." +msgstr "测试间隔时间(单位:秒)。" + +msgid "Test interval must be less or equal than idle timeout." +msgstr "测试间隔时间必须小于或等于空闲超时时间。" + +msgid "Test tolerance" +msgstr "测试容差" + +msgid "The test tolerance in milliseconds." +msgstr "测试容差时间(单位:毫秒)。" + +msgid "Idle timeout" +msgstr "空闲超时" + +msgid "The idle timeout in seconds." +msgstr "空闲超时时间(单位:秒)。" + +msgid "Interrupt existing connections" +msgstr "中断现有连接" + +msgid "Interrupt existing connections when the selected outbound has changed." +msgstr "当选择的出站发生变化时中断现有连接。" diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/app.sh b/small/luci-app-passwall2/root/usr/share/passwall2/app.sh index f07d50ab53..353fe85720 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -589,7 +589,7 @@ run_socks() { if [ "$type" == "sing-box" ] || [ "$type" == "xray" ]; then local protocol=$(config_n_get $node protocol) - if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ]; then + if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ] || [ "$protocol" == "_urltest" ]; then unset error_msg fi fi diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index a3f2cabc53..b8f7229a65 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -303,6 +303,36 @@ do end } end + elseif node.protocol and node.protocol == '_urltest' then + local flag = "Sing-Box URLTest节点[" .. node_id .. "]列表" + local currentNodes = {} + local newNodes = {} + if node.urltest_node then + for k, node in pairs(node.urltest_node) do + currentNodes[#currentNodes + 1] = { + log = false, + node = node, + currentNode = node and uci:get_all(appname, node) or nil, + remarks = node, + set = function(o, server) + if o and server and server ~= "nil" then + table.insert(o.newNodes, server) + end + end + } + end + end + CONFIG[#CONFIG + 1] = { + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, node_id, "urltest_node", newNodes or {}) + end + end + } else --前置代理节点 local currentNode = uci:get_all(appname, node_id) or nil @@ -1682,7 +1712,7 @@ local execute = function() f:close() raw = trim(stdout) local old_md5 = value.md5 or "" - local new_md5 = luci.sys.exec("[ -f " .. tmp_file .. " ] && md5sum " .. tmp_file .. " | awk '{print $1}' || echo 0") + local new_md5 = luci.sys.exec("[ -f " .. tmp_file .. " ] && md5sum " .. tmp_file .. " | awk '{print $1}' || echo 0"):gsub("\n", "") os.remove(tmp_file) if old_md5 == new_md5 then log('订阅:【' .. remark .. '】没有变化,无需更新。') diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/test.sh b/small/luci-app-passwall2/root/usr/share/passwall2/test.sh index 7fa5b3189e..a985a9cd66 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/test.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/test.sh @@ -71,7 +71,7 @@ url_test_node() { sleep 1s result=$(curl --connect-timeout 3 -o /dev/null -I -skL -w "%{http_code}:%{time_starttransfer}" -x $curlx "https://www.google.com/generate_204") pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 - rm -rf "/tmp/etc/${CONFIG}/url_test_${node_id}.json" + rm -rf "/tmp/etc/${CONFIG}/url_test_${node_id}"*.json } echo $result } diff --git a/small/v2ray-geodata/Makefile b/small/v2ray-geodata/Makefile index 5d07574076..b0e03836bb 100644 --- a/small/v2ray-geodata/Makefile +++ b/small/v2ray-geodata/Makefile @@ -21,13 +21,13 @@ define Download/geoip HASH:=f2f5f03da44d007fa91fb6a37c077c9efae8ad0269ef0e4130cf90b0822873e3 endef -GEOSITE_VER:=20250227085631 +GEOSITE_VER:=20250302153845 GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER) define Download/geosite URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/ URL_FILE:=dlc.dat FILE:=$(GEOSITE_FILE) - HASH:=463eb36a757705c7ffefe7977752d7b610e62271e8b63a1ffcf55b27d50b0f73 + HASH:=525dcdd8ac80d473ad128b568d7f3e16d0392872945a9468d18ac2afddd5b253 endef GEOSITE_IRAN_VER:=202502240036 diff --git a/v2rayn/v2rayN/Directory.Build.props b/v2rayn/v2rayN/Directory.Build.props index 8df422b9d4..b53a144c5d 100644 --- a/v2rayn/v2rayN/Directory.Build.props +++ b/v2rayn/v2rayN/Directory.Build.props @@ -1,7 +1,7 @@ - 7.10.0 + 7.10.1 diff --git a/v2rayn/v2rayN/Directory.Packages.props b/v2rayn/v2rayN/Directory.Packages.props index da2e149e92..36d814775c 100644 --- a/v2rayn/v2rayN/Directory.Packages.props +++ b/v2rayn/v2rayN/Directory.Packages.props @@ -5,21 +5,21 @@ false - - - - + + + + - + - - + + @@ -27,4 +27,4 @@ - + \ No newline at end of file diff --git a/xray-core/infra/conf/transport_internet.go b/xray-core/infra/conf/transport_internet.go index 7b993a36ab..0de5bfcc97 100644 --- a/xray-core/infra/conf/transport_internet.go +++ b/xray-core/infra/conf/transport_internet.go @@ -711,6 +711,7 @@ type SocketConfig struct { Interface string `json:"interface"` TcpMptcp bool `json:"tcpMptcp"` CustomSockopt []*CustomSockoptConfig `json:"customSockopt"` + AddressPortStrategy string `json:"addressPortStrategy"` } // Build implements Buildable. @@ -780,6 +781,26 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) { customSockopts = append(customSockopts, customSockopt) } + addressPortStrategy := internet.AddressPortStrategy_None + switch strings.ToLower(c.AddressPortStrategy) { + case "none", "": + addressPortStrategy = internet.AddressPortStrategy_None + case "srvportonly": + addressPortStrategy = internet.AddressPortStrategy_SrvPortOnly + case "srvaddressonly": + addressPortStrategy = internet.AddressPortStrategy_SrvAddressOnly + case "srvportandaddress": + addressPortStrategy = internet.AddressPortStrategy_SrvPortAndAddress + case "txtportonly": + addressPortStrategy = internet.AddressPortStrategy_TxtPortOnly + case "txtaddressonly": + addressPortStrategy = internet.AddressPortStrategy_TxtAddressOnly + case "txtportandaddress": + addressPortStrategy = internet.AddressPortStrategy_TxtPortAndAddress + default: + return nil, errors.New("unsupported address and port strategy: ", c.AddressPortStrategy) + } + return &internet.SocketConfig{ Mark: c.Mark, Tfo: tfo, @@ -798,6 +819,7 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) { Interface: c.Interface, TcpMptcp: c.TcpMptcp, CustomSockopt: customSockopts, + AddressPortStrategy: addressPortStrategy, }, nil } diff --git a/xray-core/transport/internet/config.pb.go b/xray-core/transport/internet/config.pb.go index d74fa665a4..ae1b38f3c8 100644 --- a/xray-core/transport/internet/config.pb.go +++ b/xray-core/transport/internet/config.pb.go @@ -95,6 +95,67 @@ func (DomainStrategy) EnumDescriptor() ([]byte, []int) { return file_transport_internet_config_proto_rawDescGZIP(), []int{0} } +type AddressPortStrategy int32 + +const ( + AddressPortStrategy_None AddressPortStrategy = 0 + AddressPortStrategy_SrvPortOnly AddressPortStrategy = 1 + AddressPortStrategy_SrvAddressOnly AddressPortStrategy = 2 + AddressPortStrategy_SrvPortAndAddress AddressPortStrategy = 3 + AddressPortStrategy_TxtPortOnly AddressPortStrategy = 4 + AddressPortStrategy_TxtAddressOnly AddressPortStrategy = 5 + AddressPortStrategy_TxtPortAndAddress AddressPortStrategy = 6 +) + +// Enum value maps for AddressPortStrategy. +var ( + AddressPortStrategy_name = map[int32]string{ + 0: "None", + 1: "SrvPortOnly", + 2: "SrvAddressOnly", + 3: "SrvPortAndAddress", + 4: "TxtPortOnly", + 5: "TxtAddressOnly", + 6: "TxtPortAndAddress", + } + AddressPortStrategy_value = map[string]int32{ + "None": 0, + "SrvPortOnly": 1, + "SrvAddressOnly": 2, + "SrvPortAndAddress": 3, + "TxtPortOnly": 4, + "TxtAddressOnly": 5, + "TxtPortAndAddress": 6, + } +) + +func (x AddressPortStrategy) Enum() *AddressPortStrategy { + p := new(AddressPortStrategy) + *p = x + return p +} + +func (x AddressPortStrategy) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AddressPortStrategy) Descriptor() protoreflect.EnumDescriptor { + return file_transport_internet_config_proto_enumTypes[1].Descriptor() +} + +func (AddressPortStrategy) Type() protoreflect.EnumType { + return &file_transport_internet_config_proto_enumTypes[1] +} + +func (x AddressPortStrategy) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AddressPortStrategy.Descriptor instead. +func (AddressPortStrategy) EnumDescriptor() ([]byte, []int) { + return file_transport_internet_config_proto_rawDescGZIP(), []int{1} +} + type SocketConfig_TProxyMode int32 const ( @@ -131,11 +192,11 @@ func (x SocketConfig_TProxyMode) String() string { } func (SocketConfig_TProxyMode) Descriptor() protoreflect.EnumDescriptor { - return file_transport_internet_config_proto_enumTypes[1].Descriptor() + return file_transport_internet_config_proto_enumTypes[2].Descriptor() } func (SocketConfig_TProxyMode) Type() protoreflect.EnumType { - return &file_transport_internet_config_proto_enumTypes[1] + return &file_transport_internet_config_proto_enumTypes[2] } func (x SocketConfig_TProxyMode) Number() protoreflect.EnumNumber { @@ -434,23 +495,24 @@ type SocketConfig struct { Tproxy SocketConfig_TProxyMode `protobuf:"varint,3,opt,name=tproxy,proto3,enum=xray.transport.internet.SocketConfig_TProxyMode" json:"tproxy,omitempty"` // ReceiveOriginalDestAddress is for enabling IP_RECVORIGDSTADDR socket // option. This option is for UDP only. - ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"` - BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"` - BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"` - AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` - DomainStrategy DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"` - DialerProxy string `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"` - TcpKeepAliveInterval int32 `protobuf:"varint,10,opt,name=tcp_keep_alive_interval,json=tcpKeepAliveInterval,proto3" json:"tcp_keep_alive_interval,omitempty"` - TcpKeepAliveIdle int32 `protobuf:"varint,11,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"` - TcpCongestion string `protobuf:"bytes,12,opt,name=tcp_congestion,json=tcpCongestion,proto3" json:"tcp_congestion,omitempty"` - Interface string `protobuf:"bytes,13,opt,name=interface,proto3" json:"interface,omitempty"` - V6Only bool `protobuf:"varint,14,opt,name=v6only,proto3" json:"v6only,omitempty"` - TcpWindowClamp int32 `protobuf:"varint,15,opt,name=tcp_window_clamp,json=tcpWindowClamp,proto3" json:"tcp_window_clamp,omitempty"` - TcpUserTimeout int32 `protobuf:"varint,16,opt,name=tcp_user_timeout,json=tcpUserTimeout,proto3" json:"tcp_user_timeout,omitempty"` - TcpMaxSeg int32 `protobuf:"varint,17,opt,name=tcp_max_seg,json=tcpMaxSeg,proto3" json:"tcp_max_seg,omitempty"` - Penetrate bool `protobuf:"varint,18,opt,name=penetrate,proto3" json:"penetrate,omitempty"` - TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"` - CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"` + ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"` + BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"` + BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"` + AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` + DomainStrategy DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"` + DialerProxy string `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"` + TcpKeepAliveInterval int32 `protobuf:"varint,10,opt,name=tcp_keep_alive_interval,json=tcpKeepAliveInterval,proto3" json:"tcp_keep_alive_interval,omitempty"` + TcpKeepAliveIdle int32 `protobuf:"varint,11,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"` + TcpCongestion string `protobuf:"bytes,12,opt,name=tcp_congestion,json=tcpCongestion,proto3" json:"tcp_congestion,omitempty"` + Interface string `protobuf:"bytes,13,opt,name=interface,proto3" json:"interface,omitempty"` + V6Only bool `protobuf:"varint,14,opt,name=v6only,proto3" json:"v6only,omitempty"` + TcpWindowClamp int32 `protobuf:"varint,15,opt,name=tcp_window_clamp,json=tcpWindowClamp,proto3" json:"tcp_window_clamp,omitempty"` + TcpUserTimeout int32 `protobuf:"varint,16,opt,name=tcp_user_timeout,json=tcpUserTimeout,proto3" json:"tcp_user_timeout,omitempty"` + TcpMaxSeg int32 `protobuf:"varint,17,opt,name=tcp_max_seg,json=tcpMaxSeg,proto3" json:"tcp_max_seg,omitempty"` + Penetrate bool `protobuf:"varint,18,opt,name=penetrate,proto3" json:"penetrate,omitempty"` + TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"` + CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"` + AddressPortStrategy AddressPortStrategy `protobuf:"varint,21,opt,name=address_port_strategy,json=addressPortStrategy,proto3,enum=xray.transport.internet.AddressPortStrategy" json:"address_port_strategy,omitempty"` } func (x *SocketConfig) Reset() { @@ -623,6 +685,13 @@ func (x *SocketConfig) GetCustomSockopt() []*CustomSockopt { return nil } +func (x *SocketConfig) GetAddressPortStrategy() AddressPortStrategy { + if x != nil { + return x.AddressPortStrategy + } + return AddressPortStrategy_None +} + var File_transport_internet_config_proto protoreflect.FileDescriptor var file_transport_internet_config_proto_rawDesc = []byte{ @@ -678,7 +747,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x22, 0x9b, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x65, 0x22, 0xfd, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f, @@ -732,28 +801,44 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x52, - 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x22, 0x2f, - 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, - 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, - 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, - 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, - 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, - 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, - 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, - 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, - 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, - 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, - 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, - 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, - 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, - 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42, 0x67, 0x0a, 0x1b, 0x63, - 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, - 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, - 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, - 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x12, 0x60, + 0x0a, 0x15, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, + 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, + 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x13, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, + 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, + 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, + 0x02, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, + 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, + 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, + 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, + 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, + 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, + 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, + 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, + 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, + 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x2a, 0x97, 0x01, + 0x0a, 0x13, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, + 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, + 0x0f, 0x0a, 0x0b, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x01, + 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x72, 0x76, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e, + 0x6c, 0x79, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x41, + 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, + 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, + 0x54, 0x78, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x05, + 0x12, 0x15, 0x0a, 0x11, 0x54, 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x6e, 0x64, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x06, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, + 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, + 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -768,33 +853,35 @@ func file_transport_internet_config_proto_rawDescGZIP() []byte { return file_transport_internet_config_proto_rawDescData } -var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_transport_internet_config_proto_goTypes = []any{ (DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy - (SocketConfig_TProxyMode)(0), // 1: xray.transport.internet.SocketConfig.TProxyMode - (*TransportConfig)(nil), // 2: xray.transport.internet.TransportConfig - (*StreamConfig)(nil), // 3: xray.transport.internet.StreamConfig - (*ProxyConfig)(nil), // 4: xray.transport.internet.ProxyConfig - (*CustomSockopt)(nil), // 5: xray.transport.internet.CustomSockopt - (*SocketConfig)(nil), // 6: xray.transport.internet.SocketConfig - (*serial.TypedMessage)(nil), // 7: xray.common.serial.TypedMessage - (*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain + (AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy + (SocketConfig_TProxyMode)(0), // 2: xray.transport.internet.SocketConfig.TProxyMode + (*TransportConfig)(nil), // 3: xray.transport.internet.TransportConfig + (*StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig + (*ProxyConfig)(nil), // 5: xray.transport.internet.ProxyConfig + (*CustomSockopt)(nil), // 6: xray.transport.internet.CustomSockopt + (*SocketConfig)(nil), // 7: xray.transport.internet.SocketConfig + (*serial.TypedMessage)(nil), // 8: xray.common.serial.TypedMessage + (*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain } var file_transport_internet_config_proto_depIdxs = []int32{ - 7, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage - 8, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain - 2, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig - 7, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage - 6, // 4: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig - 1, // 5: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode + 8, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage + 9, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain + 3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig + 8, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage + 7, // 4: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig + 2, // 5: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode 0, // 6: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy - 5, // 7: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 6, // 7: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt + 1, // 8: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy + 9, // [9:9] is the sub-list for method output_type + 9, // [9:9] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_transport_internet_config_proto_init() } @@ -807,7 +894,7 @@ func file_transport_internet_config_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_transport_internet_config_proto_rawDesc, - NumEnums: 2, + NumEnums: 3, NumMessages: 5, NumExtensions: 0, NumServices: 0, diff --git a/xray-core/transport/internet/config.proto b/xray-core/transport/internet/config.proto index 9293179ec4..d51998b228 100644 --- a/xray-core/transport/internet/config.proto +++ b/xray-core/transport/internet/config.proto @@ -23,6 +23,16 @@ enum DomainStrategy { FORCE_IP64 = 10; } +enum AddressPortStrategy { + None = 0; + SrvPortOnly = 1; + SrvAddressOnly = 2; + SrvPortAndAddress = 3; + TxtPortOnly = 4; + TxtAddressOnly = 5; + TxtPortAndAddress = 6; +} + message TransportConfig { // Transport protocol name. string protocol_name = 3; @@ -116,4 +126,6 @@ message SocketConfig { bool tcp_mptcp = 19; repeated CustomSockopt customSockopt = 20; + + AddressPortStrategy address_port_strategy = 21; } diff --git a/xray-core/transport/internet/dialer.go b/xray-core/transport/internet/dialer.go index 8ab51551b9..3b6fbfd57b 100644 --- a/xray-core/transport/internet/dialer.go +++ b/xray-core/transport/internet/dialer.go @@ -2,6 +2,9 @@ package internet import ( "context" + "fmt" + gonet "net" + "strings" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/dice" @@ -140,6 +143,93 @@ func redirect(ctx context.Context, dst net.Destination, obt string) net.Conn { return nil } +func checkAddressPortStrategy(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (*net.Destination, error) { + if sockopt.AddressPortStrategy == AddressPortStrategy_None { + return nil, nil + } + newDest := dest + var OverridePort, OverrideAddress bool + var OverrideBy string + switch sockopt.AddressPortStrategy { + case AddressPortStrategy_SrvPortOnly: + OverridePort = true + OverrideAddress = false + OverrideBy = "srv" + case AddressPortStrategy_SrvAddressOnly: + OverridePort = false + OverrideAddress = true + OverrideBy = "srv" + case AddressPortStrategy_SrvPortAndAddress: + OverridePort = true + OverrideAddress = true + OverrideBy = "srv" + case AddressPortStrategy_TxtPortOnly: + OverridePort = true + OverrideAddress = false + OverrideBy = "txt" + case AddressPortStrategy_TxtAddressOnly: + OverridePort = false + OverrideAddress = true + OverrideBy = "txt" + case AddressPortStrategy_TxtPortAndAddress: + OverridePort = true + OverrideAddress = true + OverrideBy = "txt" + default: + return nil, errors.New("unknown AddressPortStrategy") + } + + if !dest.Address.Family().IsDomain() { + return nil, nil + } + + if OverrideBy == "srv" { + errors.LogDebug(ctx, "query SRV record for "+dest.Address.String()) + parts := strings.SplitN(dest.Address.String(), ".", 3) + if len(parts) != 3 { + return nil, errors.New("invalid address format", dest.Address.String()) + } + _, srvRecords, err := gonet.DefaultResolver.LookupSRV(context.Background(), parts[0][1:], parts[1][1:], parts[2]) + if err != nil { + return nil, errors.New("failed to lookup SRV record").Base(err) + } + errors.LogDebug(ctx, "SRV record: "+fmt.Sprintf("addr=%s, port=%d, priority=%d, weight=%d", srvRecords[0].Target, srvRecords[0].Port, srvRecords[0].Priority, srvRecords[0].Weight)) + if OverridePort { + newDest.Port = net.Port(srvRecords[0].Port) + } + if OverrideAddress { + newDest.Address = net.ParseAddress(srvRecords[0].Target) + } + return &newDest, nil + } + if OverrideBy == "txt" { + errors.LogDebug(ctx, "query TXT record for "+dest.Address.String()) + txtRecords, err := gonet.DefaultResolver.LookupTXT(ctx, dest.Address.String()) + if err != nil { + errors.LogError(ctx, "failed to lookup SRV record: "+err.Error()) + return nil, errors.New("failed to lookup SRV record").Base(err) + } + for _, txtRecord := range txtRecords { + errors.LogDebug(ctx, "TXT record: "+txtRecord) + addr_s, port_s, _ := net.SplitHostPort(string(txtRecord)) + addr := net.ParseAddress(addr_s) + port, err := net.PortFromString(port_s) + if err != nil { + continue + } + + if OverridePort { + newDest.Port = port + } + if OverrideAddress { + newDest.Address = addr + } + return &newDest, nil + } + } + return nil, nil +} + // DialSystem calls system dialer to create a network connection. func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { var src net.Address @@ -152,6 +242,11 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig return effectiveSystemDialer.Dial(ctx, src, dest, sockopt) } + if newDest, err := checkAddressPortStrategy(ctx, dest, sockopt); err == nil && newDest != nil { + errors.LogInfo(ctx, "replace destination with "+newDest.String()) + dest = *newDest + } + if canLookupIP(ctx, dest, sockopt) { ips, err := lookupIP(dest.Address.String(), sockopt.DomainStrategy, src) if err == nil && len(ips) > 0 {