diff --git a/.github/update.log b/.github/update.log index 8f9fc660ef..2c75ff1f84 100644 --- a/.github/update.log +++ b/.github/update.log @@ -800,3 +800,4 @@ Update On Thu Oct 17 20:34:12 CEST 2024 Update On Fri Oct 18 20:36:34 CEST 2024 Update On Sat Oct 19 20:34:29 CEST 2024 Update On Sun Oct 20 20:32:12 CEST 2024 +Update On Mon Oct 21 20:36:16 CEST 2024 diff --git a/clash-meta/go.mod b/clash-meta/go.mod index a223cf77ac..098030629a 100644 --- a/clash-meta/go.mod +++ b/clash-meta/go.mod @@ -20,12 +20,12 @@ require ( github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 github.com/metacubex/chacha v0.1.0 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 - github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4 + github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174 github.com/metacubex/randv2 v0.2.0 github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 github.com/metacubex/sing-shadowsocks v0.2.8 github.com/metacubex/sing-shadowsocks2 v0.2.2 - github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1 + github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3 github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa @@ -39,7 +39,7 @@ require ( github.com/sagernet/cors v1.2.1 github.com/sagernet/fswatch v0.1.1 github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a - github.com/sagernet/sing v0.5.0-alpha.13 + github.com/sagernet/sing v0.5.0-rc.4 github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 github.com/sagernet/sing-shadowtls v0.1.4 github.com/samber/lo v1.47.0 @@ -116,4 +116,4 @@ require ( golang.org/x/tools v0.24.0 // indirect ) -replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297 +replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a diff --git a/clash-meta/go.sum b/clash-meta/go.sum index 2b3bba6542..0508ac59ce 100644 --- a/clash-meta/go.sum +++ b/clash-meta/go.sum @@ -104,20 +104,20 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw= -github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4 h1:CgdUBRxmNlxEGkp35HwvgQ10jwOOUJKWdOxpi8yWi8o= -github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4/go.mod h1:Y7yRGqFE6UQL/3aKPYmiYdjfVkeujJaStP4+jiZMcN8= +github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174 h1:GvigRPEU+cbnzdLWne47cxLrc28Abohl3ECtVdnrbq0= +github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174/go.mod h1:AiZ+UPgrkO1DTnmiAX4b+kRoV1Vfc65UkYD7RbFlIZA= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= -github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297 h1:YG/JkwGPbca5rUtEMHIu8ZuqzR7BSVm1iqY8hNoMeMA= -github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a h1:JuR0/7RDxQtlZp/GOzrdqNq04HplTxavPRHrek8ouJk= +github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 h1:HobpULaPK6OoxrHMmgcwLkwwIduXVmwdcznwUfH1GQM= github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8= github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4= github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0= github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo= github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q= -github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1 h1:ypfofGDZbP8p3Y4P/m74JYu7sQViesi3c8nbmT6cS0Y= -github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1/go.mod h1:olbEx9yVcaw5tHTNlRamRoxmMKcvDvcVS1YLnQGzvWE= +github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c h1:qfUZ8xBrViOCZamvcC8CyV7Ii8sAUrn7RqZxFGn56tQ= +github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c/go.mod h1:lCrP0AW7ieKnXG1JEeZLW+9h99QzjuOX0MfCQfz6TgE= github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I= github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY= github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3 h1:xg71VmzLS6ByAzi/57phwDvjE+dLLs+ozH00k4DnOns= diff --git a/clash-meta/listener/sing_tun/server.go b/clash-meta/listener/sing_tun/server.go index 79856c466c..ad3d113e4a 100644 --- a/clash-meta/listener/sing_tun/server.go +++ b/clash-meta/listener/sing_tun/server.go @@ -279,7 +279,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis return } - defaultInterfaceMonitor, err = tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{OverrideAndroidVPN: true}) + defaultInterfaceMonitor, err = tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{InterfaceFinder: interfaceFinder, OverrideAndroidVPN: true}) if err != nil { err = E.Cause(err, "create DefaultInterfaceMonitor") return diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index e4553511df..b5bde63fa8 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -358,7 +358,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -548,7 +548,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -583,7 +583,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -623,7 +623,7 @@ checksum = "99e1aca718ea7b89985790c94aad72d77533063fe00bc497bb79a7c2dae6a661" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -848,7 +848,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "log", @@ -858,7 +858,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.81", + "syn 2.0.82", "which 4.4.2", ] @@ -1046,7 +1046,7 @@ checksum = "240f4126219a83519bad05c9a40bfc0303921eeb571fc2d7e44c17ffac99d3f1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "synstructure", ] @@ -1167,7 +1167,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -1461,7 +1461,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -1729,7 +1729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" dependencies = [ "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -1984,7 +1984,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -1994,7 +1994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2065,7 +2065,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2076,7 +2076,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2180,7 +2180,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2201,7 +2201,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2211,7 +2211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2224,7 +2224,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2356,7 +2356,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2388,7 +2388,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2659,7 +2659,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2680,7 +2680,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -2982,7 +2982,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -3106,7 +3106,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -3394,7 +3394,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -3668,7 +3668,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -4122,7 +4122,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -4306,7 +4306,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -5013,7 +5013,7 @@ checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -5389,7 +5389,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -5449,7 +5449,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -5506,7 +5506,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -5835,7 +5835,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -5986,7 +5986,7 @@ checksum = "0a4b29106d9f2bbcca4f5ee7a9325c99844ff9721d10103625cd5278795507fe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -6226,7 +6226,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -6364,7 +6364,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -6417,7 +6417,7 @@ checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -6568,7 +6568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -6654,7 +6654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -6989,7 +6989,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -7237,7 +7237,7 @@ dependencies = [ "serde", "serde_json", "serde_yml", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -7422,7 +7422,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -7564,7 +7564,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -7575,7 +7575,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -7608,7 +7608,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -7659,7 +7659,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -8162,7 +8162,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -8215,9 +8215,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.81" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198514704ca887dd5a1e408c6c6cdcba43672f9b4062e1b24aa34e74e6d7faae" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", @@ -8247,7 +8247,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -8368,7 +8368,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -8485,7 +8485,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", - "syn 2.0.81", + "syn 2.0.82", "tauri-utils", "thiserror", "time", @@ -8503,7 +8503,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "tauri-codegen", "tauri-utils", ] @@ -8558,9 +8558,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.0.1" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddb2fe88b602461c118722c574e2775ab26a4e68886680583874b2f6520608b7" +checksum = "4307310e1d2c09ab110235834722e7c2b85099b683e1eb7342ab351b0be5ada3" dependencies = [ "log", "raw-window-handle", @@ -8576,9 +8576,9 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.0.1" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab300488ebec3487ca5f56289692e7e45feb07eea8d5e1dba497f7dc9dd9c407" +checksum = "96ba7d46e86db8c830d143ef90ab5a453328365b0cc834c24edea4267b16aba0" dependencies = [ "anyhow", "dunce", @@ -8659,9 +8659,9 @@ dependencies = [ [[package]] name = "tauri-plugin-shell" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "371fb9aca2823990a2d0db7970573be5fdf07881fcaa2b835b29631feb84aec1" +checksum = "0ad7880c5586b6b2104be451e3d7fc0f3800c84bda69e9ba81c828f87cb34267" dependencies = [ "encoding_rs", "log", @@ -8916,7 +8916,7 @@ checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -8959,7 +8959,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -9115,7 +9115,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -9295,7 +9295,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -9936,7 +9936,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "wasm-bindgen-shared", ] @@ -9970,7 +9970,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10241,7 +10241,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -10548,7 +10548,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -10559,7 +10559,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -10570,7 +10570,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -10581,7 +10581,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -10592,7 +10592,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -10603,7 +10603,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -11170,7 +11170,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "synstructure", ] @@ -11231,7 +11231,7 @@ checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "zbus-lockstep", "zbus_xml", "zvariant", @@ -11246,7 +11246,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "zvariant_utils", ] @@ -11292,7 +11292,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -11312,7 +11312,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "synstructure", ] @@ -11333,7 +11333,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -11355,7 +11355,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] [[package]] @@ -11485,7 +11485,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", "zvariant_utils", ] @@ -11497,5 +11497,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.81", + "syn 2.0.82", ] diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 71282ed26d..fc739a695a 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -21,7 +21,7 @@ "@mui/material": "6.1.4", "@nyanpasu/interface": "workspace:^", "@nyanpasu/ui": "workspace:^", - "@tanstack/router-zod-adapter": "1.74.0", + "@tanstack/router-zod-adapter": "1.74.4", "@tauri-apps/api": "2.0.2", "@types/json-schema": "7.0.15", "ahooks": "3.8.1", @@ -29,7 +29,7 @@ "country-code-emoji": "2.3.0", "dayjs": "1.11.13", "framer-motion": "12.0.0-alpha.1", - "i18next": "23.16.1", + "i18next": "23.16.2", "jotai": "2.10.1", "json-schema": "0.4.0", "material-react-table": "3.0.1", @@ -52,18 +52,18 @@ "@csstools/normalize.css": "12.1.1", "@emotion/babel-plugin": "11.12.0", "@emotion/react": "11.13.3", - "@iconify/json": "2.2.261", + "@iconify/json": "2.2.262", "@monaco-editor/react": "4.6.0", - "@tanstack/react-router": "1.74.0", - "@tanstack/router-devtools": "1.74.0", - "@tanstack/router-plugin": "1.73.1", + "@tanstack/react-router": "1.74.4", + "@tanstack/router-devtools": "1.74.4", + "@tanstack/router-plugin": "1.74.2", "@tauri-apps/plugin-clipboard-manager": "2.0.0", "@tauri-apps/plugin-dialog": "2.0.1", - "@tauri-apps/plugin-fs": "2.0.0", + "@tauri-apps/plugin-fs": "2.0.1", "@tauri-apps/plugin-notification": "2.0.0", "@tauri-apps/plugin-os": "2.0.0", "@tauri-apps/plugin-process": "2.0.0", - "@tauri-apps/plugin-shell": "2.0.0", + "@tauri-apps/plugin-shell": "2.0.1", "@tauri-apps/plugin-updater": "2.0.0", "@types/react": "18.3.11", "@types/react-dom": "18.3.1", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 5fc733c383..cd0781a66c 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -217,8 +217,8 @@ importers: specifier: workspace:^ version: link:../ui '@tanstack/router-zod-adapter': - specifier: 1.74.0 - version: 1.74.0(@tanstack/react-router@1.74.0(@tanstack/router-generator@1.73.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(zod@3.23.8) + specifier: 1.74.4 + version: 1.74.4(@tanstack/react-router@1.74.4(@tanstack/router-generator@1.74.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(zod@3.23.8) '@tauri-apps/api': specifier: 2.0.2 version: 2.0.2 @@ -241,8 +241,8 @@ importers: specifier: 12.0.0-alpha.1 version: 12.0.0-alpha.1(@emotion/is-prop-valid@1.3.0)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) i18next: - specifier: 23.16.1 - version: 23.16.1 + specifier: 23.16.2 + version: 23.16.2 jotai: specifier: 2.10.1 version: 2.10.1(react@19.0.0-rc-65a56d0e-20241020)(types-react@19.0.0-rc.1) @@ -275,7 +275,7 @@ importers: version: 7.4.0(xjqvl6gudwt62pepgh7ow64mzi) react-i18next: specifier: 15.0.3 - version: 15.0.3(i18next@23.16.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) + version: 15.0.3(i18next@23.16.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) react-markdown: specifier: 9.0.1 version: 9.0.1(react@19.0.0-rc-65a56d0e-20241020)(types-react@19.0.0-rc.1) @@ -305,20 +305,20 @@ importers: specifier: 11.13.3 version: 11.13.3(react@19.0.0-rc-65a56d0e-20241020)(types-react@19.0.0-rc.1) '@iconify/json': - specifier: 2.2.261 - version: 2.2.261 + specifier: 2.2.262 + version: 2.2.262 '@monaco-editor/react': specifier: 4.6.0 version: 4.6.0(monaco-editor@0.52.0)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) '@tanstack/react-router': - specifier: 1.74.0 - version: 1.74.0(@tanstack/router-generator@1.73.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) + specifier: 1.74.4 + version: 1.74.4(@tanstack/router-generator@1.74.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) '@tanstack/router-devtools': - specifier: 1.74.0 - version: 1.74.0(@tanstack/react-router@1.74.0(@tanstack/router-generator@1.73.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(csstype@3.1.3)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) + specifier: 1.74.4 + version: 1.74.4(@tanstack/react-router@1.74.4(@tanstack/router-generator@1.74.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(csstype@3.1.3)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) '@tanstack/router-plugin': - specifier: 1.73.1 - version: 1.73.1(vite@5.4.9(@types/node@22.7.7)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.80.3)(stylus@0.62.0))(webpack-sources@3.2.3) + specifier: 1.74.2 + version: 1.74.2(vite@5.4.9(@types/node@22.7.7)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.80.3)(stylus@0.62.0))(webpack-sources@3.2.3) '@tauri-apps/plugin-clipboard-manager': specifier: 2.0.0 version: 2.0.0 @@ -326,8 +326,8 @@ importers: specifier: 2.0.1 version: 2.0.1 '@tauri-apps/plugin-fs': - specifier: 2.0.0 - version: 2.0.0 + specifier: 2.0.1 + version: 2.0.1 '@tauri-apps/plugin-notification': specifier: 2.0.0 version: 2.0.0 @@ -338,8 +338,8 @@ importers: specifier: 2.0.0 version: 2.0.0 '@tauri-apps/plugin-shell': - specifier: 2.0.0 - version: 2.0.0 + specifier: 2.0.1 + version: 2.0.1 '@tauri-apps/plugin-updater': specifier: 2.0.0 version: 2.0.0 @@ -462,7 +462,7 @@ importers: version: 4.1.2(react@19.0.0-rc-65a56d0e-20241020) react-i18next: specifier: 15.0.3 - version: 15.0.3(i18next@23.16.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) + version: 15.0.3(i18next@23.16.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) react-use: specifier: 17.5.1 version: 17.5.1(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) @@ -801,10 +801,6 @@ packages: resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} engines: {node: '>=6.9.0'} - '@babel/template@7.25.0': - resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} - engines: {node: '>=6.9.0'} - '@babel/template@7.25.7': resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} engines: {node: '>=6.9.0'} @@ -1377,8 +1373,8 @@ packages: '@vue/compiler-sfc': optional: true - '@iconify/json@2.2.261': - resolution: {integrity: sha512-uUm8Svulz5aRRF0X+r2/UG5P0xcUCGOGVmAFJ/ZANx29wqE79PvGCYXHuznNC0h8+UW1fnvprj7FmgJELvMYZw==} + '@iconify/json@2.2.262': + resolution: {integrity: sha512-h7zMbLxsKohKXvf2Lpq6Xob7dxkqXxrUVR58ZvZBgCSrHcE69QJmcFG/KaAwM1eGuKToWvgPWeb1xE6zy7juqg==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -2307,11 +2303,11 @@ packages: resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} - '@tanstack/react-router@1.74.0': - resolution: {integrity: sha512-dthfscAM25bi1AjA38t9jPsU2jqNk0f6a6ziorEi845ss6Uwrbw4FSFQ1oI1UmUfaJR73S5SO8TGXKZAIxhlWQ==} + '@tanstack/react-router@1.74.4': + resolution: {integrity: sha512-dVI8L1Nc4d/njlFFm2O5NPLcqOd6/D10LaODIYNsbWts4UjQpQFBZcY5PGDBp9yPJxYMZ1wVctcWSGHrAUL4HQ==} engines: {node: '>=12'} peerDependencies: - '@tanstack/router-generator': 1.73.1 + '@tanstack/router-generator': 1.74.2 react: '>=18' react-dom: '>=18' peerDependenciesMeta: @@ -2337,20 +2333,20 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@tanstack/router-devtools@1.74.0': - resolution: {integrity: sha512-lr7e5PU43tDD//7mN+bBfSgQphchzHk5NbhzlwgEuEW74lYc6CCRUUeORR+pPAUFdf8+7yQ6iv5Ow7iaXb17ng==} + '@tanstack/router-devtools@1.74.4': + resolution: {integrity: sha512-g0ZNtee60k4sGSVSIqqeOgXgIG18e7QJysJhrPqotlRKCLBKjScqivoNejM3pYWjyJVmzdZEiclwsOOJ6CezOA==} engines: {node: '>=12'} peerDependencies: - '@tanstack/react-router': ^1.74.0 + '@tanstack/react-router': ^1.74.4 react: '>=18' react-dom: '>=18' - '@tanstack/router-generator@1.73.1': - resolution: {integrity: sha512-+oHYnspeS3f4bpbnUymH9dEGJbxhfV0rSwHl0cTq4pXSPXuLYcqYZmSGCqBfiq6CGtgOXZ2wEUMgezt3R2PvZg==} + '@tanstack/router-generator@1.74.2': + resolution: {integrity: sha512-S69fXvYcL+tQsO5Fe9ju/XVa/hZvk4pCaWbtoR2MNjIgR2RmjiFKOgXYeLRMNom/IpP/HAQmQ3m1DwU9jjSUKA==} engines: {node: '>=12'} - '@tanstack/router-plugin@1.73.1': - resolution: {integrity: sha512-pJMTWVFEIvTXLL6kzYZlPRlQ7WwfsBNZGIJck+dX0NQVjw6CEj1a4w9hlJFSqIOBbRdjtY6hS3Y00DDFGf9Inw==} + '@tanstack/router-plugin@1.74.2': + resolution: {integrity: sha512-HcG0FwSZ77g0QH9Ev2I1QYeXS+WWjdThO5Whgm/9abkyJq5GfsiLm2Ey2cw2Va+iHgD2nQdkraP9xL/z9/s6BQ==} engines: {node: '>=12'} peerDependencies: '@rsbuild/core': '>=1.0.2' @@ -2364,8 +2360,8 @@ packages: webpack: optional: true - '@tanstack/router-zod-adapter@1.74.0': - resolution: {integrity: sha512-YBYVNyRJ/XIVJ/QUt27s+2oaEO1YcANwlRLfvfIPDk+V3DHTz33z4+oNJ/I/YlJUOTNcoqv7mlqmWnk8Zn4Cmw==} + '@tanstack/router-zod-adapter@1.74.4': + resolution: {integrity: sha512-931F+4poa6dnKN/ecHRRBPuhYUysAsd60uNWfr0Yj9XYo0OuNa8R3J2T7NBV7gVtWTg5ywxm360KXoHCJ6gSWQ==} engines: {node: '>=12'} peerDependencies: '@tanstack/react-router': '>=1.43.2' @@ -2465,8 +2461,8 @@ packages: '@tauri-apps/plugin-dialog@2.0.1': resolution: {integrity: sha512-fnUrNr6EfvTqdls/ufusU7h6UbNFzLKvHk/zTuOiBq01R3dTODqwctZlzakdbfSp/7pNwTKvgKTAgl/NAP/Z0Q==} - '@tauri-apps/plugin-fs@2.0.0': - resolution: {integrity: sha512-BNEeQQ5aH8J5SwYuWgRszVyItsmquRuzK2QRkVj8Z0sCsLnSvJFYI3JHRzzr3ltZGq1nMPtblrlZzuKqVzRawA==} + '@tauri-apps/plugin-fs@2.0.1': + resolution: {integrity: sha512-PkeZG2WAob9Xpmr66aPvj+McDVgFjV2a7YBzYVZjiCvbGeMs6Yk09tlXhCe3EyZdT/pwWMSi8lXUace+hlsjsw==} '@tauri-apps/plugin-notification@2.0.0': resolution: {integrity: sha512-6qEDYJS7mgXZWLXA0EFL+DVCJh8sJlzSoyw6B50pxhLPVFjc5Vr5DVzl5W3mUHaYhod5wsC984eQnlCCGqxYDA==} @@ -2477,8 +2473,8 @@ packages: '@tauri-apps/plugin-process@2.0.0': resolution: {integrity: sha512-OYzi0GnkrF4NAnsHZU7U3tjSoP0PbeAlO7T1Z+vJoBUH9sFQ1NSLqWYWQyf8hcb3gVWe7P1JggjiskO+LST1ug==} - '@tauri-apps/plugin-shell@2.0.0': - resolution: {integrity: sha512-OpW2+ycgJLrEoZityWeWYk+6ZWP9VyiAfbO+N/O8VfLkqyOym8kXh7odKDfINx9RAotkSGBtQM4abyKfJDkcUg==} + '@tauri-apps/plugin-shell@2.0.1': + resolution: {integrity: sha512-akU1b77sw3qHiynrK0s930y8zKmcdrSD60htjH+mFZqv5WaakZA/XxHR3/sF1nNv9Mgmt/Shls37HwnOr00aSw==} '@tauri-apps/plugin-updater@2.0.0': resolution: {integrity: sha512-N0cl71g7RPr7zK2Fe5aoIwzw14NcdLcz7XMGFWZVjprsqgDRWoxbnUkknyCQMZthjhGkppCd/wN2MIsUz+eAhQ==} @@ -4422,8 +4418,8 @@ packages: hyphenate-style-name@1.1.0: resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} - i18next@23.16.1: - resolution: {integrity: sha512-H73h/H7BN7PI38Sq9XsOXzWFBH6mtyCYFiUMVtd9BxiYNDWPPIzKcBmDrqhjKbw3IXP5j6JoSW4ugJlaZuOvKw==} + i18next@23.16.2: + resolution: {integrity: sha512-dFyxwLXxEQK32f6tITBMaRht25mZPJhQ0WbC0p3bO2mWBal9lABTMqSka5k+GLSRWLzeJBKDpH7BeIA9TZI7Jg==} iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} @@ -7333,14 +7329,14 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 + '@babel/generator': 7.25.7 '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) '@babel/helpers': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 + '@babel/parser': 7.25.8 + '@babel/template': 7.25.7 + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 convert-source-map: 2.0.0 debug: 4.3.7 gensync: 1.0.0-beta.2 @@ -7469,7 +7465,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-module-imports': 7.24.7 '@babel/helper-simple-access': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 + '@babel/helper-validator-identifier': 7.25.7 '@babel/traverse': 7.25.7 transitivePeerDependencies: - supports-color @@ -7609,12 +7605,6 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.25.0': - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.25.8 - '@babel/types': 7.25.8 - '@babel/template@7.25.7': dependencies: '@babel/code-frame': 7.25.7 @@ -8162,7 +8152,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@iconify/json@2.2.261': + '@iconify/json@2.2.262': dependencies: '@iconify/types': 2.0.0 pathe: 1.1.2 @@ -9066,7 +9056,7 @@ snapshots: dependencies: remove-accents: 0.5.0 - '@tanstack/react-router@1.74.0(@tanstack/router-generator@1.73.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020)': + '@tanstack/react-router@1.74.4(@tanstack/router-generator@1.74.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020)': dependencies: '@tanstack/history': 1.61.1 '@tanstack/react-store': 0.5.5(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) @@ -9075,7 +9065,7 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 optionalDependencies: - '@tanstack/router-generator': 1.73.1 + '@tanstack/router-generator': 1.74.2 '@tanstack/react-store@0.5.5(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020)': dependencies: @@ -9096,9 +9086,9 @@ snapshots: react: 19.0.0-rc-65a56d0e-20241020 react-dom: 19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020) - '@tanstack/router-devtools@1.74.0(@tanstack/react-router@1.74.0(@tanstack/router-generator@1.73.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(csstype@3.1.3)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020)': + '@tanstack/router-devtools@1.74.4(@tanstack/react-router@1.74.4(@tanstack/router-generator@1.74.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(csstype@3.1.3)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020)': dependencies: - '@tanstack/react-router': 1.74.0(@tanstack/router-generator@1.73.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) + '@tanstack/react-router': 1.74.4(@tanstack/router-generator@1.74.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) clsx: 2.1.1 goober: 2.1.16(csstype@3.1.3) react: 19.0.0-rc-65a56d0e-20241020 @@ -9106,14 +9096,14 @@ snapshots: transitivePeerDependencies: - csstype - '@tanstack/router-generator@1.73.1': + '@tanstack/router-generator@1.74.2': dependencies: '@tanstack/virtual-file-routes': 1.64.0 prettier: 3.3.3 tsx: 4.19.1 zod: 3.23.8 - '@tanstack/router-plugin@1.73.1(vite@5.4.9(@types/node@22.7.7)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.80.3)(stylus@0.62.0))(webpack-sources@3.2.3)': + '@tanstack/router-plugin@1.74.2(vite@5.4.9(@types/node@22.7.7)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.80.3)(stylus@0.62.0))(webpack-sources@3.2.3)': dependencies: '@babel/core': 7.25.8 '@babel/generator': 7.25.7 @@ -9123,7 +9113,7 @@ snapshots: '@babel/template': 7.25.7 '@babel/traverse': 7.25.7 '@babel/types': 7.25.8 - '@tanstack/router-generator': 1.73.1 + '@tanstack/router-generator': 1.74.2 '@tanstack/virtual-file-routes': 1.64.0 '@types/babel__core': 7.20.5 '@types/babel__generator': 7.6.8 @@ -9139,9 +9129,9 @@ snapshots: - supports-color - webpack-sources - '@tanstack/router-zod-adapter@1.74.0(@tanstack/react-router@1.74.0(@tanstack/router-generator@1.73.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(zod@3.23.8)': + '@tanstack/router-zod-adapter@1.74.4(@tanstack/react-router@1.74.4(@tanstack/router-generator@1.74.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(zod@3.23.8)': dependencies: - '@tanstack/react-router': 1.74.0(@tanstack/router-generator@1.73.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) + '@tanstack/react-router': 1.74.4(@tanstack/router-generator@1.74.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) zod: 3.23.8 '@tanstack/store@0.5.5': {} @@ -9211,7 +9201,7 @@ snapshots: dependencies: '@tauri-apps/api': 2.0.2 - '@tauri-apps/plugin-fs@2.0.0': + '@tauri-apps/plugin-fs@2.0.1': dependencies: '@tauri-apps/api': 2.0.2 @@ -9227,7 +9217,7 @@ snapshots: dependencies: '@tauri-apps/api': 2.0.2 - '@tauri-apps/plugin-shell@2.0.0': + '@tauri-apps/plugin-shell@2.0.1': dependencies: '@tauri-apps/api': 2.0.2 @@ -11549,7 +11539,7 @@ snapshots: hyphenate-style-name@1.1.0: {} - i18next@23.16.1: + i18next@23.16.2: dependencies: '@babel/runtime': 7.25.7 @@ -13035,11 +13025,11 @@ snapshots: dependencies: react: 19.0.0-rc-65a56d0e-20241020 - react-i18next@15.0.3(i18next@23.16.1)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020): + react-i18next@15.0.3(i18next@23.16.2)(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020): dependencies: '@babel/runtime': 7.25.6 html-parse-stringify: 3.0.1 - i18next: 23.16.1 + i18next: 23.16.2 react: 19.0.0-rc-65a56d0e-20241020 optionalDependencies: react-dom: 19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020) diff --git a/clash-verge-rev/.github/ISSUE_TEMPLATE/bug_report.yml b/clash-verge-rev/.github/ISSUE_TEMPLATE/bug_report.yml index 542e9937de..f6e5ef2b99 100644 --- a/clash-verge-rev/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/clash-verge-rev/.github/ISSUE_TEMPLATE/bug_report.yml @@ -24,7 +24,13 @@ body: id: description attributes: label: 问题描述 / Describe the bug - description: 详细清晰地描述你遇到的问题 / A clear and concise description of what the bug is + description: 详细清晰地描述你遇到的问题,并配合截图 / Describe the problem you encountered in detail and clearly, and provide screenshots + validations: + required: true + - type: textarea + attributes: + label: 软件版本 / Verge Version + description: 请提供Verge的具体版本,如果是alpha版本,请注明下载时间(精确到小时分钟) / Please provide the specific version of Verge. If it is an alpha version, please indicate the download time (accurate to hours and minutes) validations: required: true - type: textarea @@ -51,6 +57,6 @@ body: - type: textarea attributes: label: 日志 / Log - description: 请提供完整或相关部分的Debug日志 / Please provide the complete or relevant part of the Debug log + description: 请提供完整或相关部分的Debug日志(请在“软件左侧菜单”->“设置”->“日志等级”调整到debug,Verge错误请把“杂项设置”->“app日志等级”调整到trace,并重启Verge生效。日志文件在“软件左侧菜单”->“设置”->“日志目录”下) / Please provide a complete or relevant part of the Debug log (please adjust the "Log level" to debug in "Software left menu" -> "Settings" -> "Log level". If there is a Verge error, please adjust "Miscellaneous settings" -> "app log level" to trace, and restart Verge to take effect. The log file is under "Software left menu" -> "Settings" -> "Log directory") validations: required: true diff --git a/clash-verge-rev/.github/workflows/alpha.yml b/clash-verge-rev/.github/workflows/alpha.yml index 66f47c32e8..9fd3706121 100644 --- a/clash-verge-rev/.github/workflows/alpha.yml +++ b/clash-verge-rev/.github/workflows/alpha.yml @@ -22,8 +22,6 @@ jobs: include: - os: windows-latest target: x86_64-pc-windows-msvc - - os: windows-latest - target: i686-pc-windows-msvc - os: windows-latest target: aarch64-pc-windows-msvc - os: macos-latest @@ -37,7 +35,7 @@ jobs: uses: actions/checkout@v4 - name: Install Rust Stable - uses: dtolnay/rust-toolchain@1.77.0 + uses: dtolnay/rust-toolchain@stable - name: Add Rust Target run: rustup target add ${{ matrix.target }} @@ -140,9 +138,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 @@ -240,7 +235,7 @@ jobs: cat > release.txt << 'EOF' ## 我应该下载哪个版本? - ### MacOS (提示文件损坏或开发者无法验证请查看下面FAQ) + ### MacOS - MacOS intel芯片: x64.dmg - MacOS apple M芯片: aarch64.dmg @@ -250,20 +245,18 @@ jobs: ### Windows (Win7 用户请查看下面FAQ中的解决方案) #### 正常版本(推荐) - 64位: x64-setup.exe - - 32位: x86-setup.exe - arm64架构: arm64-setup.exe - #### 便携版(不推荐使用,无法自动更新) - - 64位: x64_portable.zip - - 32位: x86_portable.zip - - arm64架构: arm64_portable.zip - #### 内置Webview2版(体积较大,仅在企业版系统或Win7无法安装webview2时使用) + #### 便携版问题很多不再提供 + #### 内置Webview2版(体积较大,仅在企业版系统或无法安装webview2时使用) - 64位: x64_fixed_webview2-setup.exe - - 32位: x86_fixed_webview2-setup.exe - arm64架构: arm64_fixed_webview2-setup.exe ### FAQ - - [FAQ](https://clash-verge-rev.github.io/faq/windows.html) + - [常见问题](https://clash-verge-rev.github.io/faq/windows.html) + + ### 稳定机场VPN推荐 + - [狗狗加速](https://verge.dginv.click/#/register?code=oaxsAGo6) Created at ${{ env.BUILDTIME }}. EOF diff --git a/clash-verge-rev/.github/workflows/dev.yml b/clash-verge-rev/.github/workflows/dev.yml index b0ffada7b6..c1013f5b58 100644 --- a/clash-verge-rev/.github/workflows/dev.yml +++ b/clash-verge-rev/.github/workflows/dev.yml @@ -33,7 +33,7 @@ jobs: uses: actions/checkout@v4 - name: Install Rust Stable - uses: dtolnay/rust-toolchain@1.77.0 + uses: dtolnay/rust-toolchain@stable - name: Add Rust Target run: rustup target add ${{ matrix.target }} @@ -65,6 +65,14 @@ jobs: env: NODE_OPTIONS: "--max_old_space_size=4096" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} with: tauriScript: pnpm args: --target ${{ matrix.target }} -b ${{ matrix.bundle }} diff --git a/clash-verge-rev/.github/workflows/release.yml b/clash-verge-rev/.github/workflows/release.yml index 0cb5fb3864..d753d6aa18 100644 --- a/clash-verge-rev/.github/workflows/release.yml +++ b/clash-verge-rev/.github/workflows/release.yml @@ -15,8 +15,6 @@ jobs: include: - os: windows-latest target: x86_64-pc-windows-msvc - - os: windows-latest - target: i686-pc-windows-msvc - os: windows-latest target: aarch64-pc-windows-msvc - os: macos-latest @@ -30,7 +28,7 @@ jobs: uses: actions/checkout@v4 - name: Install Rust Stable - uses: dtolnay/rust-toolchain@1.77.0 + uses: dtolnay/rust-toolchain@stable - name: Add Rust Target run: rustup target add ${{ matrix.target }} @@ -89,12 +87,6 @@ jobs: include: - os: ubuntu-latest target: x86_64-unknown-linux-gnu - - os: ubuntu-latest - target: i686-unknown-linux-gnu - - os: ubuntu-latest - target: aarch64-unknown-linux-gnu - - os: ubuntu-latest - target: armv7-unknown-linux-gnueabihf runs-on: ${{ matrix.os }} steps: - name: Checkout Repository diff --git a/clash-verge-rev/UPDATELOG.md b/clash-verge-rev/UPDATELOG.md index 69806df800..b8ea2b40c3 100644 --- a/clash-verge-rev/UPDATELOG.md +++ b/clash-verge-rev/UPDATELOG.md @@ -1,10 +1,44 @@ ## v2.0.0 +### Notice + +- 由于更改了服务安装逻辑,Mac/Linux 首次安装需要输入 2 遍系统密码卸载和安装服务,以后可以丝滑使用 tun(虚拟网卡)模式 + ### Breaking changes - 重大框架升级:使用 Tauri 2.0(巨量改进与性能提升) +- 强烈建议完全删除 1.x 老版本再安装此版本 - 敬请测试,出现 bug 到 issues 中提出 +### Features + +- Meta(mihomo)内核升级 1.18.9 +- Win 下的系统代理替换为 Shadowsocks/CFW/v2rayN 等成熟的 sysproxy.exe 方案,解决拨号/VPN 环境下无法设置系统代理的问题 +- 服务模式改进为启动软件时自动安装,TUN 模式可自由开启不再限制于服务模式 +- Mac 下可用 URL Scheme 导入订阅 +- 可使用 Ctrl(cmd)+Q 快捷键退出程序 +- 成功导入订阅的提示消息 +- 能自动选中新导入的订阅 +- 日志加入颜色区分 +- 改进多处文本表述 +- 加入图标 svg 格式检测 +- 增加更多 app 调试日志 + +### Performance + +- 优化及重构内核启动管理逻辑 +- 优化 TUN 启动逻辑 +- 重构和优化 app_handle +- 重构系统代理绕过逻辑 +- 移除无用的 PID 创建逻辑 + +### Bugs Fixes + +- 修复已有多个订阅导入新订阅会跳选订阅的问题 +- 修复多个 Linux 下的 bug, Tun 模式在 Linux 下目前工作正常 +- 修复 Linux wayland 下任务栏图标缺失的问题 +- 移除多余退出变量和钩子 + --- ## v1.7.7 diff --git a/clash-verge-rev/package.json b/clash-verge-rev/package.json index e46a234ab4..9cc1024fa6 100644 --- a/clash-verge-rev/package.json +++ b/clash-verge-rev/package.json @@ -1,11 +1,11 @@ { "name": "clash-verge", - "version": "2.0.0", + "version": "2.0.0-rc.2", "license": "GPL-3.0-only", "scripts": { - "dev": "tauri dev", - "dev:diff": "tauri dev -f verge-dev", - "build": "tauri build", + "dev": "cross-env RUST_BACKTRACE=1 tauri dev", + "dev:diff": "cross-env RUST_BACKTRACE=1 tauri dev -f verge-dev", + "build": "cross-env NODE_OPTIONS='--max-old-space-size=4096' tauri build", "tauri": "tauri", "web:dev": "vite", "web:build": "tsc && vite build", @@ -40,8 +40,10 @@ "@types/json-schema": "^7.0.15", "ahooks": "^3.8.0", "axios": "^1.7.2", + "cli-color": "^2.0.4", "dayjs": "1.11.5", "foxact": "^0.2.35", + "glob": "^11.0.0", "i18next": "^23.11.5", "js-base64": "^3.7.7", "js-yaml": "^4.1.0", @@ -68,8 +70,7 @@ }, "devDependencies": { "@actions/github": "^5.1.1", - "@tauri-apps/cli": "2.0.0-rc.8", - "@types/fs-extra": "^9.0.13", + "@tauri-apps/cli": "2.0.3", "@types/js-cookie": "^3.0.6", "@types/js-yaml": "^4.0.9", "@types/lodash-es": "^4.17.12", @@ -80,7 +81,6 @@ "@vitejs/plugin-react": "^4.3.1", "adm-zip": "^0.5.14", "cross-env": "^7.0.3", - "fs-extra": "^11.2.0", "https-proxy-agent": "^5.0.1", "husky": "^7.0.4", "node-fetch": "^3.3.2", diff --git a/clash-verge-rev/pnpm-lock.yaml b/clash-verge-rev/pnpm-lock.yaml index 637363e264..baec87c380 100644 --- a/clash-verge-rev/pnpm-lock.yaml +++ b/clash-verge-rev/pnpm-lock.yaml @@ -73,12 +73,18 @@ importers: axios: specifier: ^1.7.2 version: 1.7.2 + cli-color: + specifier: ^2.0.4 + version: 2.0.4 dayjs: specifier: 1.11.5 version: 1.11.5 foxact: specifier: ^0.2.35 version: 0.2.35(react@18.3.1) + glob: + specifier: ^11.0.0 + version: 11.0.0 i18next: specifier: ^23.11.5 version: 23.11.5 @@ -153,11 +159,8 @@ importers: specifier: ^5.1.1 version: 5.1.1 "@tauri-apps/cli": - specifier: 2.0.0-rc.8 - version: 2.0.0-rc.8 - "@types/fs-extra": - specifier: ^9.0.13 - version: 9.0.13 + specifier: 2.0.3 + version: 2.0.3 "@types/js-cookie": specifier: ^3.0.6 version: 3.0.6 @@ -188,9 +191,6 @@ importers: cross-env: specifier: ^7.0.3 version: 7.0.3 - fs-extra: - specifier: ^11.2.0 - version: 11.2.0 https-proxy-agent: specifier: ^5.0.1 version: 5.0.1 @@ -1531,6 +1531,13 @@ packages: integrity: sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==, } + "@isaacs/cliui@8.0.2": + resolution: + { + integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, + } + engines: { node: ">=12" } + "@jridgewell/gen-mapping@0.3.5": resolution: { @@ -2106,100 +2113,100 @@ packages: integrity: sha512-UNiIhhKG08j4ooss2oEEVexffmWkgkYlC2M3GcX3VPtNsqFgVNL8Mcw/4Y7rO9M9S+ffAMnLOF5ypzyuyb8tyg==, } - "@tauri-apps/cli-darwin-arm64@2.0.0-rc.8": + "@tauri-apps/cli-darwin-arm64@2.0.3": resolution: { - integrity: sha512-XDjFLfCz7gOsKg9qFyK7S9EbrdcLhWE2bSTvHDpnFdMc+DcjMR4O3HuCO7SrPmmFUf86OknYFiuMPEUoHf0Fiw==, + integrity: sha512-jIsbxGWS+As1ZN7umo90nkql/ZAbrDK0GBT6UsgHSz5zSwwArICsZFFwE1pLZip5yoiV5mn3TGG2c1+v+0puzQ==, } engines: { node: ">= 10" } cpu: [arm64] os: [darwin] - "@tauri-apps/cli-darwin-x64@2.0.0-rc.8": + "@tauri-apps/cli-darwin-x64@2.0.3": resolution: { - integrity: sha512-vYuITao7qq45jzTXRFdAcB+rVBULmofksWsKzoi+cgI8R0kcfB3bts+FRBdV3j+fkbpBQKpriW6Y6gdOzbf6Ow==, + integrity: sha512-ROITHtLTA1muyrwgyuwyasmaLCGtT4as/Kd1kerXaSDtFcYrnxiM984ZD0+FDUEDl5BgXtYa/sKKkKQFjgmM0A==, } engines: { node: ">= 10" } cpu: [x64] os: [darwin] - "@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.8": + "@tauri-apps/cli-linux-arm-gnueabihf@2.0.3": resolution: { - integrity: sha512-iW1gJyRBvwxCeBEu+ain18v8FtFBhrsqepzuUyOy7hZJWUMPdKHJhbFVz6xp3RGZf5ycsLUr3ZhqMB3vKtv7iQ==, + integrity: sha512-bQ3EZwCFfrLg/ZQ2I8sLuifSxESz4TP56SleTkKsPtTIZgNnKpM88PRDz4neiRroHVOq8NK0X276qi9LjGcXPw==, } engines: { node: ">= 10" } cpu: [arm] os: [linux] - "@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.8": + "@tauri-apps/cli-linux-arm64-gnu@2.0.3": resolution: { - integrity: sha512-k1HQHpu59B8JteXALCSdCQBUVb+ytsg1u/QEWPzCm7mFhzr7jqdfBjQVAKt0T5rdQQTcNtK341oB7izuXmJE2A==, + integrity: sha512-aLfAA8P9OTErVUk3sATxtXqpAtlfDPMPp4fGjDysEELG/MyekGhmh2k/kG/i32OdPeCfO+Nr37wJksARJKubGw==, } engines: { node: ">= 10" } cpu: [arm64] os: [linux] - "@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.8": + "@tauri-apps/cli-linux-arm64-musl@2.0.3": resolution: { - integrity: sha512-tMotP7J/dMqCL8zPCwtMwjeO3SK1yxU9bUMZ3mwdAtf+3xr2d2hpmGo4KXk5r2jQee9+dIC3IBXexFhrVJGRHA==, + integrity: sha512-I4MVD7nf6lLLRmNQPpe5beEIFM6q7Zkmh77ROA5BNu/+vHNL5kiTMD+bmd10ZL2r753A6pO7AvqkIxcBuIl0tg==, } engines: { node: ">= 10" } cpu: [arm64] os: [linux] - "@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.8": + "@tauri-apps/cli-linux-x64-gnu@2.0.3": resolution: { - integrity: sha512-AnLghADQgt4oyp4rQyjpKfGpdAqofd+SRO9kht5d4c0RSViqwHBjIxrCt9FDhBpBwwkC6T6NNuQqaofZSnOH6Q==, + integrity: sha512-C6Jkx2zZGKkoi+sg5FK9GoH/0EvAaOgrZfF5azV5EALGba46g7VpWcZgp9zFUd7K2IzTi+0OOY8TQ2OVfKZgew==, } engines: { node: ">= 10" } cpu: [x64] os: [linux] - "@tauri-apps/cli-linux-x64-musl@2.0.0-rc.8": + "@tauri-apps/cli-linux-x64-musl@2.0.3": resolution: { - integrity: sha512-jv/uiXI2K41/XMA2vnKMcpdv1tKvez70HHvBoIwHhelmXV5V6Tpu5fTMEAXbA6WbJNfcFRi0kd55YRBOS0DZcw==, + integrity: sha512-qi4ghmTfSAl+EEUDwmwI9AJUiOLNSmU1RgiGgcPRE+7A/W+Am9UnxYySAiRbB/gJgTl9sj/pqH5Y9duP1/sqHg==, } engines: { node: ">= 10" } cpu: [x64] os: [linux] - "@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.8": + "@tauri-apps/cli-win32-arm64-msvc@2.0.3": resolution: { - integrity: sha512-wctgwSfuyJ0lXBzQSzGq5TAy2m9VZichZPPJ7GitYzdHbqIRLmvxM1abRen7HikP1lpjdmjl96/kWQOebEV0qw==, + integrity: sha512-UXxHkYmFesC97qVmZre4vY7oDxRDtC2OeKNv0bH+iSnuUp/ROxzJYGyaelnv9Ybvgl4YVqDCnxgB28qMM938TA==, } engines: { node: ">= 10" } cpu: [arm64] os: [win32] - "@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.8": + "@tauri-apps/cli-win32-ia32-msvc@2.0.3": resolution: { - integrity: sha512-BBjoAezNpHscGhBICHrt+X+IyJIh9jYnaEIGvbCIMcGB6sSDxvtttw4ef9+4jNh3JixotOR2mwIudTc1H9HffQ==, + integrity: sha512-D+xoaa35RGlkXDpnL5uDTpj29untuC5Wp6bN9snfgFDagD0wnFfC8+2ZQGu16bD0IteWqDI0OSoIXhNvy+F+wg==, } engines: { node: ">= 10" } cpu: [ia32] os: [win32] - "@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.8": + "@tauri-apps/cli-win32-x64-msvc@2.0.3": resolution: { - integrity: sha512-1pgDw2woeyDMvXctmqc53LBxsaAYqiRNUVgwvzlmzJDbUHv4+Pj4B1OGKQh1YKlsmks8LK3mK9uSbk+k1OLZhw==, + integrity: sha512-eWV9XWb4dSYHXl13OtYWLjX1JHphUEkHkkGwJrhr8qFBm7RbxXxQvrsUEprSi51ug/dwJenjJgM4zR8By4htfw==, } engines: { node: ">= 10" } cpu: [x64] os: [win32] - "@tauri-apps/cli@2.0.0-rc.8": + "@tauri-apps/cli@2.0.3": resolution: { - integrity: sha512-hB6Pa0IaJs/As3Hc5IOiiK4Ilh9jspEA+2uPURCRQg4BkzQWwQzNdGQ4gjAzFNFAWPzy/4uuIXdnd1a+jC4wLA==, + integrity: sha512-JwEyhc5BAVpn4E8kxzY/h7+bVOiXQdudR1r3ODMfyyumZBfgIWqpD/WuTcPq6Yjchju1BSS+80jAE/oYwI/RKg==, } engines: { node: ">= 10" } hasBin: true @@ -2294,12 +2301,6 @@ packages: integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==, } - "@types/fs-extra@9.0.13": - resolution: - { - integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==, - } - "@types/hast@3.0.4": resolution: { @@ -2452,6 +2453,20 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 + ansi-regex@5.0.1: + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, + } + engines: { node: ">=8" } + + ansi-regex@6.1.0: + resolution: + { + integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==, + } + engines: { node: ">=12" } + ansi-styles@3.2.1: resolution: { @@ -2459,6 +2474,20 @@ packages: } engines: { node: ">=4" } + ansi-styles@4.3.0: + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, + } + engines: { node: ">=8" } + + ansi-styles@6.2.1: + resolution: + { + integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==, + } + engines: { node: ">=12" } + anymatch@3.1.3: resolution: { @@ -2521,6 +2550,12 @@ packages: integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==, } + balanced-match@1.0.2: + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, + } + before-after-hook@2.2.3: resolution: { @@ -2534,6 +2569,12 @@ packages: } engines: { node: ">=8" } + brace-expansion@2.0.1: + resolution: + { + integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==, + } + braces@3.0.3: resolution: { @@ -2636,6 +2677,13 @@ packages: } engines: { node: ">=10" } + cli-color@2.0.4: + resolution: + { + integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==, + } + engines: { node: ">=0.10" } + client-only@0.0.1: resolution: { @@ -2655,12 +2703,25 @@ packages: integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, } + color-convert@2.0.1: + resolution: + { + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, + } + engines: { node: ">=7.0.0" } + color-name@1.1.3: resolution: { integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, } + color-name@1.1.4: + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, + } + combined-stream@1.0.8: resolution: { @@ -2751,6 +2812,13 @@ packages: integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==, } + d@1.0.2: + resolution: + { + integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==, + } + engines: { node: ">=0.12" } + data-uri-to-buffer@4.0.1: resolution: { @@ -2820,12 +2888,30 @@ packages: integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==, } + eastasianwidth@0.2.0: + resolution: + { + integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, + } + electron-to-chromium@1.4.818: resolution: { integrity: sha512-eGvIk2V0dGImV9gWLq8fDfTTsCAeMDwZqEPMr+jMInxZdnp9Us8UpovYpRCf9NQ7VOFgrN2doNSgvISbsbNpxA==, } + emoji-regex@8.0.0: + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, + } + + emoji-regex@9.2.2: + resolution: + { + integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, + } + end-of-stream@1.4.4: resolution: { @@ -2845,6 +2931,32 @@ packages: integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==, } + es5-ext@0.10.64: + resolution: + { + integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==, + } + engines: { node: ">=0.10" } + + es6-iterator@2.0.3: + resolution: + { + integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==, + } + + es6-symbol@3.1.4: + resolution: + { + integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==, + } + engines: { node: ">=0.12" } + + es6-weak-map@2.0.3: + resolution: + { + integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==, + } + esbuild@0.21.5: resolution: { @@ -2874,6 +2986,13 @@ packages: } engines: { node: ">=10" } + esniff@2.0.1: + resolution: + { + integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==, + } + engines: { node: ">=0.10" } + estree-util-is-identifier-name@3.0.0: resolution: { @@ -2893,6 +3012,12 @@ packages: } engines: { node: ">=0.10.0" } + event-emitter@0.3.5: + resolution: + { + integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==, + } + execa@4.1.0: resolution: { @@ -2900,6 +3025,12 @@ packages: } engines: { node: ">=10" } + ext@1.7.0: + resolution: + { + integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==, + } + extend@3.0.2: resolution: { @@ -2945,6 +3076,13 @@ packages: debug: optional: true + foreground-child@3.3.0: + resolution: + { + integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==, + } + engines: { node: ">=14" } + form-data@4.0.0: resolution: { @@ -2970,13 +3108,6 @@ packages: react: optional: true - fs-extra@11.2.0: - resolution: - { - integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==, - } - engines: { node: ">=14.14" } - fs-minipass@2.1.0: resolution: { @@ -3019,6 +3150,14 @@ packages: } engines: { node: ">= 6" } + glob@11.0.0: + resolution: + { + integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==, + } + engines: { node: 20 || >=22 } + hasBin: true + globals@11.12.0: resolution: { @@ -3026,12 +3165,6 @@ packages: } engines: { node: ">=4" } - graceful-fs@4.2.11: - resolution: - { - integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, - } - has-flag@3.0.0: resolution: { @@ -3181,6 +3314,13 @@ packages: } engines: { node: ">=0.10.0" } + is-fullwidth-code-point@3.0.0: + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, + } + engines: { node: ">=8" } + is-glob@4.0.3: resolution: { @@ -3215,6 +3355,12 @@ packages: } engines: { node: ">=0.10.0" } + is-promise@2.2.2: + resolution: + { + integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==, + } + is-stream@2.0.1: resolution: { @@ -3228,6 +3374,13 @@ packages: integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, } + jackspeak@4.0.2: + resolution: + { + integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==, + } + engines: { node: 20 || >=22 } + js-base64@3.7.7: resolution: { @@ -3288,12 +3441,6 @@ packages: integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==, } - jsonfile@6.1.0: - resolution: - { - integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==, - } - lines-and-columns@1.2.4: resolution: { @@ -3344,6 +3491,13 @@ packages: integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==, } + lru-cache@11.0.1: + resolution: + { + integrity: sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==, + } + engines: { node: 20 || >=22 } + lru-cache@5.1.1: resolution: { @@ -3357,6 +3511,12 @@ packages: } engines: { node: ">=10" } + lru-queue@0.1.0: + resolution: + { + integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==, + } + magic-string@0.30.10: resolution: { @@ -3411,6 +3571,13 @@ packages: integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==, } + memoizee@0.4.17: + resolution: + { + integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==, + } + engines: { node: ">=0.12" } + meow@13.2.0: resolution: { @@ -3577,6 +3744,13 @@ packages: } engines: { node: ">=6" } + minimatch@10.0.1: + resolution: + { + integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==, + } + engines: { node: 20 || >=22 } + minipass@3.3.6: resolution: { @@ -3591,6 +3765,13 @@ packages: } engines: { node: ">=8" } + minipass@7.1.2: + resolution: + { + integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==, + } + engines: { node: ">=16 || 14 >=14.17" } + minizlib@2.1.2: resolution: { @@ -3675,6 +3856,12 @@ packages: engines: { node: ^18 || >=20 } hasBin: true + next-tick@1.1.0: + resolution: + { + integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==, + } + no-case@3.0.4: resolution: { @@ -3768,6 +3955,12 @@ packages: } engines: { node: ">=6" } + package-json-from-dist@1.0.1: + resolution: + { + integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, + } + parent-module@1.0.1: resolution: { @@ -3814,6 +4007,13 @@ packages: integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, } + path-scurry@2.0.0: + resolution: + { + integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==, + } + engines: { node: 20 || >=22 } + path-type@4.0.0: resolution: { @@ -4183,6 +4383,13 @@ packages: integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, } + signal-exit@4.1.0: + resolution: + { + integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, + } + engines: { node: ">=14" } + snake-case@3.0.4: resolution: { @@ -4235,12 +4442,40 @@ packages: integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==, } + string-width@4.2.3: + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, + } + engines: { node: ">=8" } + + string-width@5.1.2: + resolution: + { + integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, + } + engines: { node: ">=12" } + stringify-entities@4.0.4: resolution: { integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==, } + strip-ansi@6.0.1: + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, + } + engines: { node: ">=8" } + + strip-ansi@7.1.0: + resolution: + { + integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==, + } + engines: { node: ">=12" } + strip-final-newline@2.0.0: resolution: { @@ -4309,6 +4544,13 @@ packages: engines: { node: ">=10" } hasBin: true + timers-ext@0.1.8: + resolution: + { + integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==, + } + engines: { node: ">=0.12" } + to-fast-properties@2.0.0: resolution: { @@ -4354,6 +4596,12 @@ packages: } engines: { node: ">=0.6.11 <=0.7.0 || >=0.7.3" } + type@2.7.3: + resolution: + { + integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==, + } + types-pac@1.0.2: resolution: { @@ -4457,13 +4705,6 @@ packages: integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==, } - universalify@2.0.1: - resolution: - { - integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, - } - engines: { node: ">= 10.0.0" } - update-browserslist-db@1.1.0: resolution: { @@ -4605,6 +4846,20 @@ packages: engines: { node: ">= 8" } hasBin: true + wrap-ansi@7.0.0: + resolution: + { + integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, + } + engines: { node: ">=10" } + + wrap-ansi@8.1.0: + resolution: + { + integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, + } + engines: { node: ">=12" } + wrappy@1.0.2: resolution: { @@ -5638,6 +5893,15 @@ snapshots: "@floating-ui/utils@0.2.4": {} + "@isaacs/cliui@8.0.2": + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + "@jridgewell/gen-mapping@0.3.5": dependencies: "@jridgewell/set-array": 1.2.1 @@ -6032,48 +6296,48 @@ snapshots: "@tauri-apps/api@2.0.0-rc.4": {} - "@tauri-apps/cli-darwin-arm64@2.0.0-rc.8": + "@tauri-apps/cli-darwin-arm64@2.0.3": optional: true - "@tauri-apps/cli-darwin-x64@2.0.0-rc.8": + "@tauri-apps/cli-darwin-x64@2.0.3": optional: true - "@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.8": + "@tauri-apps/cli-linux-arm-gnueabihf@2.0.3": optional: true - "@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.8": + "@tauri-apps/cli-linux-arm64-gnu@2.0.3": optional: true - "@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.8": + "@tauri-apps/cli-linux-arm64-musl@2.0.3": optional: true - "@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.8": + "@tauri-apps/cli-linux-x64-gnu@2.0.3": optional: true - "@tauri-apps/cli-linux-x64-musl@2.0.0-rc.8": + "@tauri-apps/cli-linux-x64-musl@2.0.3": optional: true - "@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.8": + "@tauri-apps/cli-win32-arm64-msvc@2.0.3": optional: true - "@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.8": + "@tauri-apps/cli-win32-ia32-msvc@2.0.3": optional: true - "@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.8": + "@tauri-apps/cli-win32-x64-msvc@2.0.3": optional: true - "@tauri-apps/cli@2.0.0-rc.8": + "@tauri-apps/cli@2.0.3": optionalDependencies: - "@tauri-apps/cli-darwin-arm64": 2.0.0-rc.8 - "@tauri-apps/cli-darwin-x64": 2.0.0-rc.8 - "@tauri-apps/cli-linux-arm-gnueabihf": 2.0.0-rc.8 - "@tauri-apps/cli-linux-arm64-gnu": 2.0.0-rc.8 - "@tauri-apps/cli-linux-arm64-musl": 2.0.0-rc.8 - "@tauri-apps/cli-linux-x64-gnu": 2.0.0-rc.8 - "@tauri-apps/cli-linux-x64-musl": 2.0.0-rc.8 - "@tauri-apps/cli-win32-arm64-msvc": 2.0.0-rc.8 - "@tauri-apps/cli-win32-ia32-msvc": 2.0.0-rc.8 - "@tauri-apps/cli-win32-x64-msvc": 2.0.0-rc.8 + "@tauri-apps/cli-darwin-arm64": 2.0.3 + "@tauri-apps/cli-darwin-x64": 2.0.3 + "@tauri-apps/cli-linux-arm-gnueabihf": 2.0.3 + "@tauri-apps/cli-linux-arm64-gnu": 2.0.3 + "@tauri-apps/cli-linux-arm64-musl": 2.0.3 + "@tauri-apps/cli-linux-x64-gnu": 2.0.3 + "@tauri-apps/cli-linux-x64-musl": 2.0.3 + "@tauri-apps/cli-win32-arm64-msvc": 2.0.3 + "@tauri-apps/cli-win32-ia32-msvc": 2.0.3 + "@tauri-apps/cli-win32-x64-msvc": 2.0.3 "@tauri-apps/plugin-clipboard-manager@2.0.0-rc.0": dependencies: @@ -6138,10 +6402,6 @@ snapshots: "@types/estree@1.0.5": {} - "@types/fs-extra@9.0.13": - dependencies: - "@types/node": 20.14.10 - "@types/hast@3.0.4": dependencies: "@types/unist": 3.0.2 @@ -6167,6 +6427,7 @@ snapshots: "@types/node@20.14.10": dependencies: undici-types: 5.26.5 + optional: true "@types/parse-json@4.0.2": {} @@ -6240,10 +6501,20 @@ snapshots: screenfull: 5.2.0 tslib: 2.6.3 + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -6293,10 +6564,16 @@ snapshots: bail@2.0.2: {} + balanced-match@1.0.2: {} + before-after-hook@2.2.3: {} binary-extensions@2.3.0: {} + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -6351,6 +6628,14 @@ snapshots: chownr@2.0.0: {} + cli-color@2.0.4: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-iterator: 2.0.3 + memoizee: 0.4.17 + timers-ext: 0.1.8 + client-only@0.0.1: {} clsx@2.1.1: {} @@ -6359,8 +6644,14 @@ snapshots: dependencies: color-name: 1.1.3 + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + color-name@1.1.3: {} + color-name@1.1.4: {} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -6410,6 +6701,11 @@ snapshots: csstype@3.1.3: {} + d@1.0.2: + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + data-uri-to-buffer@4.0.1: {} dayjs@1.11.5: {} @@ -6442,8 +6738,14 @@ snapshots: no-case: 3.0.4 tslib: 2.6.3 + eastasianwidth@0.2.0: {} + electron-to-chromium@1.4.818: {} + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + end-of-stream@1.4.4: dependencies: once: 1.4.0 @@ -6454,6 +6756,31 @@ snapshots: dependencies: is-arrayish: 0.2.1 + es5-ext@0.10.64: + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + + es6-iterator@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + es6-symbol@3.1.4: + dependencies: + d: 1.0.2 + ext: 1.7.0 + + es6-weak-map@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esbuild@0.21.5: optionalDependencies: "@esbuild/aix-ppc64": 0.21.5 @@ -6486,12 +6813,24 @@ snapshots: escape-string-regexp@4.0.0: {} + esniff@2.0.1: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + estree-util-is-identifier-name@3.0.0: {} estree-walker@2.0.2: {} esutils@2.0.3: {} + event-emitter@0.3.5: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + execa@4.1.0: dependencies: cross-spawn: 7.0.3 @@ -6504,6 +6843,10 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + ext@1.7.0: + dependencies: + type: 2.7.3 + extend@3.0.2: {} fetch-blob@3.2.0: @@ -6524,6 +6867,11 @@ snapshots: follow-redirects@1.15.6: {} + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + form-data@4.0.0: dependencies: asynckit: 0.4.0 @@ -6541,12 +6889,6 @@ snapshots: optionalDependencies: react: 18.3.1 - fs-extra@11.2.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - fs-minipass@2.1.0: dependencies: minipass: 3.3.6 @@ -6566,9 +6908,16 @@ snapshots: dependencies: is-glob: 4.0.3 - globals@11.12.0: {} + glob@11.0.0: + dependencies: + foreground-child: 3.3.0 + jackspeak: 4.0.2 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 - graceful-fs@4.2.11: {} + globals@11.12.0: {} has-flag@3.0.0: {} @@ -6659,6 +7008,8 @@ snapshots: is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -6671,10 +7022,16 @@ snapshots: is-plain-object@5.0.0: {} + is-promise@2.2.2: {} + is-stream@2.0.1: {} isexe@2.0.0: {} + jackspeak@4.0.2: + dependencies: + "@isaacs/cliui": 8.0.2 + js-base64@3.7.7: {} js-cookie@2.2.1: {} @@ -6695,12 +7052,6 @@ snapshots: jsonc-parser@3.3.1: {} - jsonfile@6.1.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - lines-and-columns@1.2.4: {} locate-path@5.0.0: @@ -6723,6 +7074,8 @@ snapshots: dependencies: tslib: 2.6.3 + lru-cache@11.0.1: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -6731,6 +7084,10 @@ snapshots: dependencies: yallist: 4.0.0 + lru-queue@0.1.0: + dependencies: + es5-ext: 0.10.64 + magic-string@0.30.10: dependencies: "@jridgewell/sourcemap-codec": 1.4.15 @@ -6824,6 +7181,17 @@ snapshots: dependencies: "@types/mdast": 4.0.4 + memoizee@0.4.17: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-weak-map: 2.0.3 + event-emitter: 0.3.5 + is-promise: 2.2.2 + lru-queue: 0.1.0 + next-tick: 1.1.0 + timers-ext: 0.1.8 + meow@13.2.0: {} merge-stream@2.0.0: {} @@ -6971,12 +7339,18 @@ snapshots: mimic-fn@2.1.0: {} + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + minipass@3.3.6: dependencies: yallist: 4.0.0 minipass@5.0.0: {} + minipass@7.1.2: {} + minizlib@2.1.2: dependencies: minipass: 3.3.6 @@ -7026,6 +7400,8 @@ snapshots: nanoid@5.0.7: {} + next-tick@1.1.0: {} + no-case@3.0.4: dependencies: lower-case: 2.0.2 @@ -7071,6 +7447,8 @@ snapshots: p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -7101,6 +7479,11 @@ snapshots: path-parse@1.0.7: {} + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.1 + minipass: 7.1.2 + path-type@4.0.0: {} peggy@4.0.3: @@ -7343,6 +7726,8 @@ snapshots: signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + snake-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -7365,11 +7750,31 @@ snapshots: space-separated-tokens@2.0.2: {} + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + strip-final-newline@2.0.0: {} style-to-object@1.0.6: @@ -7410,6 +7815,11 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + timers-ext@0.1.8: + dependencies: + es5-ext: 0.10.64 + next-tick: 1.1.0 + to-fast-properties@2.0.0: {} to-regex-range@5.0.1: @@ -7426,11 +7836,14 @@ snapshots: tunnel@0.0.6: {} + type@2.7.3: {} + types-pac@1.0.2: {} typescript@5.5.3: {} - undici-types@5.26.5: {} + undici-types@5.26.5: + optional: true undici@5.28.4: dependencies: @@ -7487,8 +7900,6 @@ snapshots: universal-user-agent@6.0.1: {} - universalify@2.0.1: {} - update-browserslist-db@1.1.0(browserslist@4.23.1): dependencies: browserslist: 4.23.1 @@ -7564,6 +7975,18 @@ snapshots: dependencies: isexe: 2.0.0 + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} yallist@3.1.1: {} diff --git a/clash-verge-rev/scripts/check.mjs b/clash-verge-rev/scripts/check.mjs index 19e2ac6444..bf75cbacd4 100644 --- a/clash-verge-rev/scripts/check.mjs +++ b/clash-verge-rev/scripts/check.mjs @@ -1,4 +1,5 @@ -import fs from "fs-extra"; +import fs from "fs"; +import fsp from "fs/promises"; import zlib from "zlib"; import tar from "tar"; import path from "path"; @@ -6,6 +7,8 @@ import AdmZip from "adm-zip"; import fetch from "node-fetch"; import proxyAgent from "https-proxy-agent"; import { execSync } from "child_process"; +import { log_info, log_debug, log_error, log_success } from "./utils.mjs"; +import { glob } from "glob"; const cwd = process.cwd(); const TEMP_DIR = path.join(cwd, "node_modules/.verge"); @@ -91,9 +94,9 @@ async function getLatestAlphaVersion() { }); let v = await response.text(); META_ALPHA_VERSION = v.trim(); // Trim to remove extra whitespaces - console.log(`Latest alpha version: ${META_ALPHA_VERSION}`); + log_info(`Latest alpha version: ${META_ALPHA_VERSION}`); } catch (error) { - console.error("Error fetching latest alpha version:", error.message); + log_error("Error fetching latest alpha version:", error.message); process.exit(1); } } @@ -138,9 +141,9 @@ async function getLatestReleaseVersion() { }); let v = await response.text(); META_VERSION = v.trim(); // Trim to remove extra whitespaces - console.log(`Latest release version: ${META_VERSION}`); + log_info(`Latest release version: ${META_VERSION}`); } catch (error) { - console.error("Error fetching latest release version:", error.message); + log_error("Error fetching latest release version:", error.message); process.exit(1); } } @@ -205,44 +208,44 @@ async function resolveSidecar(binInfo) { const sidecarDir = path.join(cwd, "src-tauri", "sidecar"); const sidecarPath = path.join(sidecarDir, targetFile); - await fs.mkdirp(sidecarDir); - if (!FORCE && (await fs.pathExists(sidecarPath))) return; + await fsp.mkdir(sidecarDir, { recursive: true }); + if (!FORCE && fs.existsSync(sidecarPath)) return; const tempDir = path.join(TEMP_DIR, name); const tempZip = path.join(tempDir, zipFile); const tempExe = path.join(tempDir, exeFile); - await fs.mkdirp(tempDir); + await fsp.mkdir(tempDir, { recursive: true }); try { - if (!(await fs.pathExists(tempZip))) { + if (!fs.existsSync(tempZip)) { await downloadFile(downloadURL, tempZip); } if (zipFile.endsWith(".zip")) { const zip = new AdmZip(tempZip); zip.getEntries().forEach((entry) => { - console.log(`[DEBUG]: "${name}" entry name`, entry.entryName); + log_debug(`"${name}" entry name`, entry.entryName); }); zip.extractAllTo(tempDir, true); - await fs.rename(tempExe, sidecarPath); - console.log(`[INFO]: "${name}" unzip finished`); + await fsp.rename(tempExe, sidecarPath); + log_success(`unzip finished: "${name}"`); } else if (zipFile.endsWith(".tgz")) { // tgz - await fs.mkdirp(tempDir); + await fsp.mkdir(tempDir, { recursive: true }); await tar.extract({ cwd: tempDir, file: tempZip, //strip: 1, // 可能需要根据实际的 .tgz 文件结构调整 }); - const files = await fs.readdir(tempDir); - console.log(`[DEBUG]: "${name}" files in tempDir:`, files); + const files = await fsp.readdir(tempDir); + log_debug(`"${name}" files in tempDir:`, files); const extractedFile = files.find((file) => file.startsWith("虚空终端-")); if (extractedFile) { const extractedFilePath = path.join(tempDir, extractedFile); - await fs.rename(extractedFilePath, sidecarPath); - console.log(`[INFO]: "${name}" file renamed to "${sidecarPath}"`); + await fsp.rename(extractedFilePath, sidecarPath); + log_success(`"${name}" file renamed to "${sidecarPath}"`); execSync(`chmod 755 ${sidecarPath}`); - console.log(`[INFO]: "${name}" chmod binary finished`); + log_success(`chmod binary finished: "${name}"`); } else { throw new Error(`Expected file not found in ${tempDir}`); } @@ -252,16 +255,15 @@ async function resolveSidecar(binInfo) { const writeStream = fs.createWriteStream(sidecarPath); await new Promise((resolve, reject) => { const onError = (error) => { - console.error(`[ERROR]: "${name}" gz failed:`, error.message); + log_error(`"${name}" gz failed:`, error.message); reject(error); }; readStream .pipe(zlib.createGunzip().on("error", onError)) .pipe(writeStream) .on("finish", () => { - console.log(`[INFO]: "${name}" gunzip finished`); execSync(`chmod 755 ${sidecarPath}`); - console.log(`[INFO]: "${name}" chmod binary finished`); + log_success(`chmod binary finished: "${name}"`); resolve(); }) .on("error", onError); @@ -269,11 +271,11 @@ async function resolveSidecar(binInfo) { } } catch (err) { // 需要删除文件 - await fs.remove(sidecarPath); + await fsp.rm(sidecarPath, { recursive: true, force: true }); throw err; } finally { // delete temp dir - await fs.remove(tempDir); + await fsp.rm(tempDir, { recursive: true, force: true }); } } @@ -286,12 +288,12 @@ async function resolveResource(binInfo) { const resDir = path.join(cwd, "src-tauri/resources"); const targetPath = path.join(resDir, file); - if (!FORCE && (await fs.pathExists(targetPath))) return; + if (!FORCE && fs.existsSync(targetPath)) return; - await fs.mkdirp(resDir); + await fsp.mkdir(resDir, { recursive: true }); await downloadFile(downloadURL, targetPath); - console.log(`[INFO]: ${file} finished`); + log_success(`${file} finished`); } /** @@ -316,9 +318,9 @@ async function downloadFile(url, path) { headers: { "Content-Type": "application/octet-stream" }, }); const buffer = await response.arrayBuffer(); - await fs.writeFile(path, new Uint8Array(buffer)); + await fsp.writeFile(path, new Uint8Array(buffer)); - console.log(`[INFO]: download finished "${url}"`); + log_success(`download finished: ${url}`); } // SimpleSC.dll @@ -334,38 +336,41 @@ const resolvePlugin = async () => { const tempDll = path.join(tempDir, "SimpleSC.dll"); const pluginDir = path.join(process.env.APPDATA, "Local/NSIS"); const pluginPath = path.join(pluginDir, "SimpleSC.dll"); - await fs.mkdirp(pluginDir); - await fs.mkdirp(tempDir); - if (!FORCE && (await fs.pathExists(pluginPath))) return; + await fsp.mkdir(pluginDir, { recursive: true }); + await fsp.mkdir(tempDir, { recursive: true }); + if (!FORCE && fs.existsSync(pluginPath)) return; try { - if (!(await fs.pathExists(tempZip))) { + if (!fs.existsSync(tempZip)) { await downloadFile(url, tempZip); } const zip = new AdmZip(tempZip); zip.getEntries().forEach((entry) => { - console.log(`[DEBUG]: "SimpleSC" entry name`, entry.entryName); + log_debug(`"SimpleSC" entry name`, entry.entryName); }); zip.extractAllTo(tempDir, true); - await fs.copyFile(tempDll, pluginPath); - console.log(`[INFO]: "SimpleSC" unzip finished`); + await fsp.cp(tempDll, pluginPath, { recursive: true, force: true }); + log_success(`unzip finished: "SimpleSC"`); } finally { - await fs.remove(tempDir); + await fsp.rm(tempDir, { recursive: true, force: true }); } }; // service chmod const resolveServicePermission = async () => { const serviceExecutables = [ - "clash-verge-service", - "install-service", - "uninstall-service", + "clash-verge-service*", + "install-service*", + "uninstall-service*", ]; const resDir = path.join(cwd, "src-tauri/resources"); for (let f of serviceExecutables) { - const targetPath = path.join(resDir, f); - if (await fs.pathExists(targetPath)) { - execSync(`chmod 755 ${targetPath}`); - console.log(`[INFO]: "${targetPath}" chmod finished`); + // 使用glob模块来处理通配符 + const files = glob.sync(path.join(resDir, f)); + for (let filePath of files) { + if (fs.existsSync(filePath)) { + execSync(`chmod 755 ${filePath}`); + log_success(`chmod finished: "${filePath}"`); + } } } }; @@ -373,29 +378,32 @@ const resolveServicePermission = async () => { /** * main */ - const SERVICE_URL = `https://github.com/clash-verge-rev/clash-verge-service/releases/download/${SIDECAR_HOST}`; const resolveService = () => { let ext = platform === "win32" ? ".exe" : ""; + let suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; resolveResource({ - file: "clash-verge-service" + ext, + file: "clash-verge-service" + suffix + ext, downloadURL: `${SERVICE_URL}/clash-verge-service${ext}`, }); }; const resolveInstall = () => { let ext = platform === "win32" ? ".exe" : ""; + let suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; resolveResource({ - file: "install-service" + ext, + file: "install-service" + suffix + ext, downloadURL: `${SERVICE_URL}/install-service${ext}`, }); }; const resolveUninstall = () => { let ext = platform === "win32" ? ".exe" : ""; + let suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; + resolveResource({ - file: "uninstall-service" + ext, + file: "uninstall-service" + suffix + ext, downloadURL: `${SERVICE_URL}/uninstall-service${ext}`, }); }; @@ -421,6 +429,12 @@ const resolveEnableLoopback = () => downloadURL: `https://github.com/Kuingsmile/uwp-tool/releases/download/latest/enableLoopback.exe`, }); +const resolveWinSysproxy = () => + resolveResource({ + file: "sysproxy.exe", + downloadURL: `https://github.com/clash-verge-rev/sysproxy/releases/download/${arch}/sysproxy.exe`, + }); + const tasks = [ // { name: "clash", func: resolveClash, retry: 5 }, { @@ -454,6 +468,12 @@ const tasks = [ retry: 1, unixOnly: true, }, + { + name: "windows-sysproxy", + func: resolveWinSysproxy, + retry: 5, + winOnly: true, + }, ]; async function runTask() { @@ -468,7 +488,7 @@ async function runTask() { await task.func(); break; } catch (err) { - console.error(`[ERROR]: task::${task.name} try ${i} ==`, err.message); + log_error(`task::${task.name} try ${i} ==`, err.message); if (i === task.retry - 1) throw err; } } diff --git a/clash-verge-rev/scripts/portable-fixed-webview2.mjs b/clash-verge-rev/scripts/portable-fixed-webview2.mjs index 94285ce70c..696c21eaea 100644 --- a/clash-verge-rev/scripts/portable-fixed-webview2.mjs +++ b/clash-verge-rev/scripts/portable-fixed-webview2.mjs @@ -1,4 +1,5 @@ -import fs from "fs-extra"; +import fs from "fs"; +import fsp from "fs/promises"; import path from "path"; import AdmZip from "adm-zip"; import { createRequire } from "module"; @@ -30,12 +31,14 @@ async function resolvePortable() { const configDir = path.join(releaseDir, ".config"); - if (!(await fs.pathExists(releaseDir))) { + if (!fs.existsSync(releaseDir)) { throw new Error("could not found the release dir"); } - await fs.mkdir(configDir); - await fs.createFile(path.join(configDir, "PORTABLE")); + await fsp.mkdir(configDir, { recursive: true }); + if (!fs.existsSync(path.join(configDir, "PORTABLE"))) { + await fsp.writeFile(path.join(configDir, "PORTABLE"), ""); + } const zip = new AdmZip(); diff --git a/clash-verge-rev/scripts/portable.mjs b/clash-verge-rev/scripts/portable.mjs index 1a9d125883..97a00d4ac9 100644 --- a/clash-verge-rev/scripts/portable.mjs +++ b/clash-verge-rev/scripts/portable.mjs @@ -1,4 +1,4 @@ -import fs from "fs-extra"; +import fs from "fs"; import path from "path"; import AdmZip from "adm-zip"; import { createRequire } from "module"; @@ -29,12 +29,14 @@ async function resolvePortable() { : `./src-tauri/target/release`; const configDir = path.join(releaseDir, ".config"); - if (!(await fs.pathExists(releaseDir))) { + if (!fs.existsSync(releaseDir)) { throw new Error("could not found the release dir"); } - await fs.mkdir(configDir); - await fs.createFile(path.join(configDir, "PORTABLE")); + await fsp.mkdir(configDir, { recursive: true }); + if (!fs.existsSync(path.join(configDir, "PORTABLE"))) { + await fsp.writeFile(path.join(configDir, "PORTABLE"), ""); + } const zip = new AdmZip(); diff --git a/clash-verge-rev/scripts/updatelog.mjs b/clash-verge-rev/scripts/updatelog.mjs index fae7f628f4..914098cb5f 100644 --- a/clash-verge-rev/scripts/updatelog.mjs +++ b/clash-verge-rev/scripts/updatelog.mjs @@ -1,4 +1,5 @@ -import fs from "fs-extra"; +import fs from "fs"; +import fsp from "fs/promises"; import path from "path"; const UPDATE_LOG = "UPDATELOG.md"; @@ -12,11 +13,11 @@ export async function resolveUpdateLog(tag) { const file = path.join(cwd, UPDATE_LOG); - if (!(await fs.pathExists(file))) { + if (!fs.existsSync(file)) { throw new Error("could not found UPDATELOG.md"); } - const data = await fs.readFile(file).then((d) => d.toString("utf8")); + const data = await fsp.readFile(file, "utf-8"); const map = {}; let p = ""; diff --git a/clash-verge-rev/scripts/utils.mjs b/clash-verge-rev/scripts/utils.mjs new file mode 100644 index 0000000000..3db9a14e2a --- /dev/null +++ b/clash-verge-rev/scripts/utils.mjs @@ -0,0 +1,11 @@ +import clc from "cli-color"; + +export const log_success = (msg, ...optionalParams) => + console.log(clc.green(msg), ...optionalParams); +export const log_error = (msg, ...optionalParams) => + console.log(clc.red(msg), ...optionalParams); +export const log_info = (msg, ...optionalParams) => + console.log(clc.bgBlue(msg), ...optionalParams); +var debugMsg = clc.xterm(245); +export const log_debug = (msg, ...optionalParams) => + console.log(debugMsg(msg), ...optionalParams); diff --git a/clash-verge-rev/src-tauri/Cargo.lock b/clash-verge-rev/src-tauri/Cargo.lock index 6c809a3e87..39c76f2d4a 100644 --- a/clash-verge-rev/src-tauri/Cargo.lock +++ b/clash-verge-rev/src-tauri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -45,6 +45,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -83,9 +89,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" [[package]] name = "arbitrary" @@ -98,13 +104,13 @@ dependencies = [ [[package]] name = "arboard" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb4009533e8ff8f1450a5bcbc30f4242a1d34442221f72314bea1f5dc9c7f89" +checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" dependencies = [ "clipboard-win", "core-graphics 0.23.2", - "image 0.25.2", + "image", "log", "objc2", "objc2-app-kit", @@ -120,6 +126,17 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.81", +] + [[package]] name = "arrayvec" version = "0.7.6" @@ -128,18 +145,22 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ashpd" -version = "0.8.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" +checksum = "4d43c03d9e36dd40cab48435be0b09646da362c278223ca535493877b2c1dee9" dependencies = [ "enumflags2", "futures-channel", "futures-util", "rand 0.8.5", + "raw-window-handle 0.6.2", "serde", "serde_repr", "tokio", "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", "zbus", ] @@ -180,9 +201,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", @@ -247,7 +268,7 @@ dependencies = [ "futures-lite 2.3.0", "parking", "polling 3.7.3", - "rustix 0.38.35", + "rustix 0.38.37", "slab", "tracing", "windows-sys 0.59.0", @@ -297,15 +318,15 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.35", + "rustix 0.38.37", "windows-sys 0.48.0", ] [[package]] name = "async-process" -version = "2.2.4" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel 2.3.1", "async-io 2.3.4", @@ -316,9 +337,8 @@ dependencies = [ "cfg-if", "event-listener 5.3.0", "futures-lite 2.3.0", - "rustix 0.38.35", + "rustix 0.38.37", "tracing", - "windows-sys 0.59.0", ] [[package]] @@ -329,7 +349,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -344,7 +364,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 0.38.35", + "rustix 0.38.37", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -352,9 +372,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -363,13 +383,13 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -380,13 +400,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -431,9 +451,32 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 7.1.3", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" +dependencies = [ + "arrayvec", +] [[package]] name = "axum" @@ -448,7 +491,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.31", "itoa 1.0.11", "matchit", "memchr", @@ -482,17 +525,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide 0.8.0", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -534,6 +577,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bitstream-io" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b81e1519b0d82120d2fd469d5bfb2919a9361c48b02d82d04befc1cdd2002452" + [[package]] name = "block" version = "0.1.6" @@ -582,23 +631,23 @@ dependencies = [ [[package]] name = "boa_ast" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b6fb81ca0f301f33aff7401e2ffab37dc9e0e4a1cf0ccf6b34f4d9e60aa0682" +checksum = "3a69ee3a749ea36d4e56d92941e7b25076b493d4917c3d155b6cf369e23547d9" dependencies = [ "bitflags 2.6.0", "boa_interner", "boa_macros", - "indexmap 2.5.0", + "indexmap 2.6.0", "num-bigint", - "rustc-hash 1.1.0", + "rustc-hash", ] [[package]] name = "boa_engine" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "600e4e4a65b26efcef08a7b1cf2899d3845a32e82e067ee3b75eaf7e413ff31c" +checksum = "06e4559b35b80ceb2e6328481c0eca9a24506663ea33ee1e279be6b5b618b25c" dependencies = [ "arrayvec", "bitflags 2.6.0", @@ -608,26 +657,26 @@ dependencies = [ "boa_macros", "boa_parser", "boa_profiler", + "boa_string", "bytemuck", "cfg-if", "dashmap", "fast-float", "hashbrown 0.14.5", "icu_normalizer", - "indexmap 2.5.0", + "indexmap 2.6.0", "intrusive-collections", - "itertools", + "itertools 0.13.0", "num-bigint", "num-integer", "num-traits", "num_enum", "once_cell", - "paste", "pollster", "portable-atomic", "rand 0.8.5", "regress", - "rustc-hash 1.1.0", + "rustc-hash", "ryu-js", "serde", "serde_json", @@ -641,49 +690,50 @@ dependencies = [ [[package]] name = "boa_gc" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c055ef3cd87ea7db014779195bc90c6adfc35de4902e3b2fe587adecbd384578" +checksum = "716406f57d67bc3ac7fd227d5513b42df401dff14a3be22cbd8ee29817225363" dependencies = [ "boa_macros", "boa_profiler", + "boa_string", "hashbrown 0.14.5", "thin-vec", ] [[package]] name = "boa_interner" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cacc9caf022d92195c827a3e5bf83f96089d4bfaff834b359ac7b6be46e9187" +checksum = "4e18df2272616e1ba0322a69333d37dbb78797f1aa0595aad9dc41e8ecd06ad9" dependencies = [ "boa_gc", "boa_macros", "hashbrown 0.14.5", - "indexmap 2.5.0", + "indexmap 2.6.0", "once_cell", "phf 0.11.2", - "rustc-hash 1.1.0", + "rustc-hash", "static_assertions", ] [[package]] name = "boa_macros" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6be9c93793b60dac381af475b98634d4b451e28336e72218cad9a20176218dbc" +checksum = "240f4126219a83519bad05c9a40bfc0303921eeb571fc2d7e44c17ffac99d3f1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", "synstructure", ] [[package]] name = "boa_parser" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8592556849f0619ed142ce2b3a19086769314a8d657f93a5765d06dbce4818" +checksum = "62b59dc05bf1dc019b11478a92986f590cff43fced4d20e866eefb913493e91c" dependencies = [ "bitflags 2.6.0", "boa_ast", @@ -695,14 +745,27 @@ dependencies = [ "num-bigint", "num-traits", "regress", - "rustc-hash 1.1.0", + "rustc-hash", ] [[package]] name = "boa_profiler" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d8372f2d5cbac600a260de87877141b42da1e18d2c7a08ccb493a49cbd55c0" +checksum = "00ee0645509b3b91abd724f25072649d9e8e65653a78ff0b6e592788a58dd838" + +[[package]] +name = "boa_string" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae85205289bab1f2c7c8a30ddf0541cf89ba2ff7dbd144feef50bbfa664288d4" +dependencies = [ + "fast-float", + "paste", + "rustc-hash", + "sptr", + "static_assertions", +] [[package]] name = "brotli" @@ -725,6 +788,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "built" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b" + [[package]] name = "bumpalo" version = "3.16.0" @@ -733,22 +802,22 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.17.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -765,9 +834,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] @@ -841,10 +910,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.15" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -933,6 +1004,7 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-clipboard-manager", + "tauri-plugin-deep-link", "tauri-plugin-devtools", "tauri-plugin-dialog", "tauri-plugin-fs", @@ -942,6 +1014,7 @@ dependencies = [ "tauri-plugin-shell", "tauri-plugin-updater", "tokio", + "url", "users", "warp", "window-shadows", @@ -1050,7 +1123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1062,6 +1135,26 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "tiny-keccak", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -1144,9 +1237,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -1245,7 +1338,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1255,7 +1348,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1279,7 +1372,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1290,7 +1383,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1380,7 +1473,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1393,7 +1486,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1404,16 +1497,16 @@ checksum = "3c877555693c14d2f84191cfd3ad8582790fc52b5e2274b40b59cf5f5cea25c7" [[package]] name = "devtools-core" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f21c374111065b917a9ed5d1e377cd5792cd19f641ee0bf316f72878908bb99" +checksum = "e78cdd51f6f62ad4eb9b6581d7e238e1779db3144ddbd711388f552e6ed3194b" dependencies = [ "async-stream", "bytes", "devtools-wire-format", "futures", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.31", "log", "prost-types", "ringbuf", @@ -1433,9 +1526,9 @@ dependencies = [ [[package]] name = "devtools-wire-format" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d841ad485c6bc179ffed4886197490045644f2f194b52ce090c8488bb0028b" +checksum = "a1c0de542960449c9566001c1879d10ede95f3f2e0013fdae0cc3b153bfabb0d" dependencies = [ "bitflags 2.6.0", "prost", @@ -1539,7 +1632,16 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading 0.8.5", ] [[package]] @@ -1562,9 +1664,24 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dpi" version = "0.1.1" @@ -1609,9 +1726,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "embed-resource" -version = "2.4.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4edcacde9351c33139a41e3c97eb2334351a81a2791bebb0b243df837128f602" +checksum = "f4e24052d7be71f0efb50c201557f6fe7d237cfd5a64fd5bcd7fd8fe32dbbffa" dependencies = [ "cc", "memchr", @@ -1660,7 +1777,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1691,9 +1808,9 @@ dependencies = [ [[package]] name = "error-code" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" [[package]] name = "event-listener" @@ -1772,9 +1889,9 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" dependencies = [ "simd-adler32", ] @@ -1814,9 +1931,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1833,9 +1950,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "spin", ] @@ -1846,6 +1963,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1873,7 +1996,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -1909,9 +2032,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1924,9 +2047,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1934,15 +2057,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1951,9 +2074,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1985,32 +2108,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -2132,19 +2255,6 @@ 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" @@ -2199,9 +2309,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gio" @@ -2269,7 +2379,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -2290,15 +2400,14 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "global-hotkey" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298a7667d6011efe6b35673c6b29001b88677ae1b3d6b2feccfbff4b44892866" +checksum = "d1b75248f33c73df1ed69673f6cb36d2e048ae84d29aa1d3e53199d138ebb1df" dependencies = [ - "bitflags 2.6.0", - "cocoa 0.26.0", "crossbeam-channel", "keyboard-types", - "objc", + "objc2", + "objc2-app-kit", "once_cell", "serde", "thiserror", @@ -2366,7 +2475,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -2381,7 +2490,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.5.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2400,7 +2509,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.5.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2447,6 +2556,17 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "headers" version = "0.3.9" @@ -2594,9 +2714,9 @@ checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -2612,9 +2732,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -2636,9 +2756,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -2656,13 +2776,13 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "rustls", "rustls-pki-types", @@ -2678,7 +2798,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.30", + "hyper 0.14.31", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -2692,7 +2812,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "native-tls", "tokio", @@ -2702,29 +2822,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.0", "pin-project-lite", "socket2 0.5.7", "tokio", - "tower", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2755,9 +2874,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "137d96353afc8544d437e8a99eceb10ab291352699573b0de5b08bda38c78c60" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ "displaydoc", "yoke", @@ -2767,9 +2886,9 @@ dependencies = [ [[package]] name = "icu_locid" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c0aa2536adc14c07e2a521e95512b75ed8ef832f0fdf9299d4a0a45d2be2a9d" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", "litemap", @@ -2780,9 +2899,9 @@ dependencies = [ [[package]] name = "icu_locid_transform" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c17d8f6524fdca4471101dd71f0a132eb6382b5d6d7f2970441cb25f6f435a" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" dependencies = [ "displaydoc", "icu_locid", @@ -2794,15 +2913,15 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545c6c3e8bf9580e2dafee8de6f9ec14826aaf359787789c7724f1f85f47d3dc" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" [[package]] name = "icu_normalizer" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accb85c5b2e76f8dade22978b3795ae1e550198c6cfc7e915144e17cd6e2ab56" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ "displaydoc", "icu_collections", @@ -2818,15 +2937,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3744fecc0df9ce19999cdaf1f9f3a48c253431ce1d67ef499128fe9d0b607ab" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" [[package]] name = "icu_properties" -version = "1.4.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db9e559598096627aeca8cdfb98138a70eb4078025f8d1d5f2416a361241f756" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ "displaydoc", "icu_collections", @@ -2839,15 +2958,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70a8b51ee5dd4ff8f20ee9b1dd1bc07afc110886a3747b1fec04cc6e5a15815" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" [[package]] name = "icu_provider" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba58e782287eb6950247abbf11719f83f5d4e4a5c1f2cd490d30a334bc47c2f4" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" dependencies = [ "displaydoc", "icu_locid", @@ -2862,13 +2981,13 @@ dependencies = [ [[package]] name = "icu_provider_macros" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -2889,35 +3008,43 @@ dependencies = [ [[package]] name = "image" -version = "0.24.9" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "jpeg-decoder", - "num-traits", - "png", - "qoi", - "tiff", -] - -[[package]] -name = "image" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" +checksum = "bc144d44a31d753b02ce64093d532f55ff8dc4ebf2ffb8a63c0dda691385acae" dependencies = [ "bytemuck", "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", "num-traits", "png", + "qoi", + "ravif", + "rayon", + "rgb", "tiff", + "zune-core", + "zune-jpeg", ] +[[package]] +name = "image-webp" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" + [[package]] name = "indexmap" version = "1.9.3" @@ -2931,20 +3058,20 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "serde", ] [[package]] name = "infer" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb33622da908807a06f9513c19b3c1ad50fab3e4137d82a78107d502075aa199" +checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847" dependencies = [ "cfb", ] @@ -2975,10 +3102,21 @@ dependencies = [ ] [[package]] -name = "intrusive-collections" -version = "0.9.6" +name = "interpolate_name" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b694dc9f70c3bda874626d2aed13b780f137aab435f4e9814121955cf706122e" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.81", +] + +[[package]] +name = "intrusive-collections" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86" dependencies = [ "memoffset 0.9.1", ] @@ -2996,9 +3134,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "iptools" @@ -3039,6 +3177,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -3096,20 +3243,26 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" -dependencies = [ - "rayon", -] [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -3193,15 +3346,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ "gtk-sys", - "libloading", + "libloading 0.7.4", "once_cell", ] [[package]] name = "libc" -version = "0.2.158" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] [[package]] name = "libloading" @@ -3213,6 +3377,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + [[package]] name = "libredox" version = "0.1.3" @@ -3308,27 +3482,21 @@ dependencies = [ ] [[package]] -name = "loom" -version = "0.5.6" +name = "loop9" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "serde", - "serde_json", - "tracing", - "tracing-subscriber", + "imgref", ] [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] @@ -3339,9 +3507,9 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "mac-notification-sys" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51fca4d74ff9dbaac16a01b924bc3693fa2bba0862c2c633abc73f9a8ea21f64" +checksum = "dce8f34f3717aa37177e723df6c1fc5fb02b2a1087374ea3fe0ea42316dc8f91" dependencies = [ "cc", "dirs-next", @@ -3394,6 +3562,15 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.7.4" @@ -3459,7 +3636,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", - "simd-adler32", ] [[package]] @@ -3469,6 +3645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -3485,16 +3662,17 @@ dependencies = [ [[package]] name = "muda" -version = "0.14.1" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba8ac4080fb1e097c2c22acae467e46e4da72d941f02e82b67a87a2a89fa38b1" +checksum = "b8123dfd4996055ac9b15a60ad263b44b01e539007523ad7a4a533a3d93b0591" dependencies = [ - "cocoa 0.26.0", "crossbeam-channel", "dpi", "gtk", "keyboard-types", - "objc", + "objc2", + "objc2-app-kit", + "objc2-foundation", "once_cell", "png", "serde", @@ -3672,10 +3850,16 @@ dependencies = [ ] [[package]] -name = "notify-rust" -version = "4.11.1" +name = "noop_proc_macro" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a1d03b6305ecefdd9c6c60150179bb8d9f0cd4e64bbcad1e41419e7bf5e414" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "notify-rust" +version = "4.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5134a72dc570b178bff81b01e81ab14a6fcc015391ed4b3b14853090658cd3a3" dependencies = [ "log", "mac-notification-sys", @@ -3731,6 +3915,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.81", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -3740,6 +3935,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -3767,7 +3973,7 @@ dependencies = [ "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -3786,7 +3992,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", - "objc_exception", ] [[package]] @@ -3805,6 +4010,9 @@ name = "objc-sys" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" +dependencies = [ + "cc", +] [[package]] name = "objc2" @@ -3832,6 +4040,30 @@ dependencies = [ "objc2-quartz-core", ] +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + [[package]] name = "objc2-core-data" version = "0.2.2" @@ -3856,6 +4088,18 @@ dependencies = [ "objc2-metal", ] +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + [[package]] name = "objc2-encode" version = "4.0.3" @@ -3875,6 +4119,18 @@ dependencies = [ "objc2", ] +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + [[package]] name = "objc2-metal" version = "0.2.2" @@ -3901,12 +4157,71 @@ dependencies = [ ] [[package]] -name = "objc_exception" -version = "0.1.2" +name = "objc2-symbols" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "cc", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-web-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bc69301064cebefc6c4c90ce9cba69225239e4b8ff99d445a2b5563797da65" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", ] [[package]] @@ -3920,18 +4235,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" @@ -3952,9 +4267,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -3973,7 +4288,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -3984,9 +4299,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -4009,6 +4324,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + [[package]] name = "ordered-stream" version = "0.2.0" @@ -4062,9 +4387,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -4097,9 +4422,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" [[package]] name = "pathsearch" @@ -4119,9 +4444,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", "thiserror", @@ -4130,9 +4455,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" dependencies = [ "pest", "pest_generator", @@ -4140,22 +4465,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" dependencies = [ "once_cell", "pest", @@ -4276,7 +4601,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -4308,22 +4633,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -4351,9 +4676,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plist" @@ -4362,7 +4687,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64 0.22.1", - "indexmap 2.5.0", + "indexmap 2.6.0", "quick-xml 0.32.0", "serde", "time", @@ -4370,15 +4695,15 @@ dependencies = [ [[package]] name = "png" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" dependencies = [ "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.4", + "miniz_oxide 0.8.0", ] [[package]] @@ -4407,7 +4732,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.35", + "rustix 0.38.37", "tracing", "windows-sys 0.59.0", ] @@ -4426,9 +4751,9 @@ checksum = "325a6d2ac5dee293c3b2612d4993b98aec1dff096b0a2dae70ed7d95784a05da" [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "powerfmt" @@ -4503,13 +4828,32 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn 2.0.81", +] + [[package]] name = "prost" version = "0.12.6" @@ -4527,10 +4871,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -4576,16 +4920,25 @@ dependencies = [ ] [[package]] -name = "quinn" -version = "0.11.3" +name = "quick-xml" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", + "rustc-hash", "rustls", "socket2 0.5.7", "thiserror", @@ -4595,14 +4948,14 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" dependencies = [ "bytes", "rand 0.8.5", "ring", - "rustc-hash 2.0.0", + "rustc-hash", "rustls", "slab", "thiserror", @@ -4612,15 +4965,15 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" dependencies = [ "libc", "once_cell", "socket2 0.5.7", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4713,6 +5066,55 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.12.1", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive 0.4.2", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand 0.8.5", + "rand_chacha 0.3.1", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rgb", +] + [[package]] name = "raw-window-handle" version = "0.5.2" @@ -4747,9 +5149,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -4767,14 +5169,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -4788,13 +5190,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -4805,15 +5207,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "regress" -version = "0.9.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eae2a1ebfecc58aff952ef8ccd364329abe627762f5bf09ff42eb9d98522479" +checksum = "1541daf4e4ed43a0922b7969bdc2170178bcacc5dabf7e39bc508a9fa3953a7a" dependencies = [ "hashbrown 0.14.5", "memchr", @@ -4821,9 +5223,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", @@ -4834,7 +5236,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-rustls", "hyper-tls", "hyper-util", @@ -4866,26 +5268,25 @@ dependencies = [ "wasm-streams", "web-sys", "webpki-roots", - "windows-registry", + "windows-registry 0.2.0", ] [[package]] name = "rfd" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" +checksum = "8af382a047821a08aa6bfc09ab0d80ff48d45d8726f7cd8e44891f7cb4a4278e" dependencies = [ "ashpd", - "block", - "dispatch", + "block2", "glib-sys", "gobject-sys", "gtk-sys", "js-sys", "log", - "objc", - "objc-foundation", - "objc_id", + "objc2", + "objc2-app-kit", + "objc2-foundation", "raw-window-handle 0.6.2", "wasm-bindgen", "wasm-bindgen-futures", @@ -4893,6 +5294,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + [[package]] name = "ring" version = "0.17.8" @@ -4910,11 +5317,12 @@ dependencies = [ [[package]] name = "ringbuf" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f7f1b88601a8ee13cabf203611ccdf64345dc1c5d24de8b11e1a678ee619b6" +checksum = "726bb493fe9cac765e8f96a144c3a8396bdf766dedad22e504b70b908dcbceb4" dependencies = [ "crossbeam-utils", + "portable-atomic", ] [[package]] @@ -4935,18 +5343,23 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rust-ini" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f" +dependencies = [ + "cfg-if", + "ordered-multimap", + "trim-in-place", +] + [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.0.0" @@ -4987,9 +5400,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -5000,9 +5413,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "once_cell", "ring", @@ -5014,25 +5427,24 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" -version = "0.102.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -5041,9 +5453,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -5068,11 +5480,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5087,6 +5499,7 @@ dependencies = [ "serde", "serde_json", "url", + "uuid", ] [[package]] @@ -5098,7 +5511,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -5128,9 +5541,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -5200,9 +5613,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -5230,13 +5643,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -5247,14 +5660,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa 1.0.11", "memchr", @@ -5270,14 +5683,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -5296,15 +5709,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -5314,14 +5727,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -5330,7 +5743,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "itoa 1.0.11", "ryu", "serde", @@ -5464,6 +5877,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -5524,25 +5946,24 @@ dependencies = [ [[package]] name = "softbuffer" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d623bff5d06f60d738990980d782c8c866997d9194cfe79ecad00aa2f76826dd" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" dependencies = [ "bytemuck", "cfg_aliases", - "core-graphics 0.23.2", + "core-graphics 0.24.0", "foreign-types 0.5.0", "js-sys", "log", "objc2", - "objc2-app-kit", "objc2-foundation", "objc2-quartz-core", "raw-window-handle 0.6.2", "redox_syscall", "wasm-bindgen", "web-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5592,15 +6013,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "state" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" -dependencies = [ - "loom", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -5669,9 +6081,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "198514704ca887dd5a1e408c6c6cdcba43672f9b4062e1b24aa34e74e6d7faae" dependencies = [ "proc-macro2", "quote", @@ -5701,28 +6113,27 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] name = "sysinfo" -version = "0.30.13" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" +checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" dependencies = [ - "cfg-if", "core-foundation-sys", "libc", + "memchr", "ntapi", - "once_cell", "rayon", - "windows 0.52.0", + "windows 0.57.0", ] [[package]] name = "sysproxy" version = "0.3.0" -source = "git+https://github.com/zzzgydi/sysproxy-rs?branch=main#45fffb0cdddb7c2d0ce30300dd72a934bb458c09" +source = "git+https://github.com/clash-verge-rev/sysproxy-rs?branch=main#b18d75d31976efc26cd7b70e07b877e406b5133e" dependencies = [ "interfaces", "iptools", @@ -5769,9 +6180,9 @@ dependencies = [ [[package]] name = "tao" -version = "0.29.1" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a97abbc7d6cfd0720da3e06fcb1cf2ac87cbfdb5bbbce103a1279a211c4d81" +checksum = "a0dbbebe82d02044dfa481adca1550d6dd7bd16e086bc34fa0fbecceb5a63751" dependencies = [ "bitflags 2.6.0", "cocoa 0.26.0", @@ -5814,7 +6225,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -5825,9 +6236,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020" dependencies = [ "filetime", "libc", @@ -5842,13 +6253,12 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.0.0-rc.8" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8345ccc676ef16e26b61fc0f5340b4e770678b1e1f53f08c69ebdac5e56b422" +checksum = "5ce2818e803ce3097987296623ed8c0d9f65ed93b4137ff9a83e168bdbf62932" dependencies = [ "anyhow", "bytes", - "cocoa 0.26.0", "dirs 5.0.1", "dunce", "embed_plist", @@ -5859,21 +6269,23 @@ dependencies = [ "heck 0.5.0", "http 1.1.0", "http-range", - "image 0.24.9", + "image", "jni", "libc", "log", "mime", "muda", - "objc", + "objc2", + "objc2-app-kit", + "objc2-foundation", "percent-encoding", + "plist", "raw-window-handle 0.6.2", "reqwest", "serde", "serde_json", "serde_repr", "serialize-to-javascript", - "state", "swift-rs", "tauri-build", "tauri-macros", @@ -5894,9 +6306,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.0-rc.7" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5ad5fcfaf02cf79aa6727f6c5df38567d8dce172b00b62690c6bc46c08b7ce" +checksum = "935f9b3c49b22b3e2e485a57f46d61cd1ae07b1cbb2ba87387a387caf2d8c4e7" dependencies = [ "anyhow", "cargo_toml", @@ -5916,9 +6328,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.0-rc.7" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809ef6316726fc72593d296cf6f4e7461326e310c313d6a6c42b6e7f1e2671cf" +checksum = "95d7443dd4f0b597704b6a14b964ee2ed16e99928d8e6292ae9825f09fbcd30e" dependencies = [ "base64 0.22.1", "brotli", @@ -5932,7 +6344,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", - "syn 2.0.77", + "syn 2.0.81", "tauri-utils", "thiserror", "time", @@ -5943,23 +6355,23 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.0-rc.6" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1359e8861d210d25731f8b1bfbb4d111dd06406cf73c59659366ef450364d811" +checksum = "4d2c0963ccfc3f5194415f2cce7acc975942a8797fbabfb0aa1ed6f59326ae7f" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.0.0-rc.7" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7dded420c86183f592d0fe925ef9447f41e26fa79f0bdfef8d3f17bfbcdbfb7" +checksum = "b2e6660a409963e4d57b9bfab4addd141eeff41bd3a7fb14e13004a832cf7ef6" dependencies = [ "anyhow", "glob", @@ -5974,12 +6386,12 @@ dependencies = [ [[package]] name = "tauri-plugin-clipboard-manager" -version = "2.1.0-beta.7" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "becbc5a692e842f8d6a7ab5e490c3c36d267b5c3d5bf4b6a0cdd039d7df25569" +checksum = "78b7d556886c15849198c0948fd7f4c880492f0461539176da0a8a70272e2904" dependencies = [ "arboard", - "image 0.24.9", + "image", "log", "serde", "serde_json", @@ -5989,14 +6401,34 @@ dependencies = [ ] [[package]] -name = "tauri-plugin-devtools" -version = "2.0.0-rc.0" +name = "tauri-plugin-deep-link" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7333811c0b81f32e980d34894effc92454f464409fb97a7e566294b7ebddd0" +checksum = "31a9b5725027c6e9e075b06cb2d5c2cd3b5c29daa8012b404e1ff755cc56082f" +dependencies = [ + "dunce", + "log", + "rust-ini", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-utils", + "thiserror", + "url", + "windows-registry 0.3.0", + "windows-result 0.2.0", +] + +[[package]] +name = "tauri-plugin-devtools" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5cd17faa36a826e5686bd0fda5bc3f4c903682263f00cd50f2f778fc4bb866" dependencies = [ "async-stream", "bytes", - "cocoa 0.25.0", + "cocoa 0.26.0", "colored", "devtools-core", "futures", @@ -6017,11 +6449,10 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.0.0-rc.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa8bd381f75c47687f41fb603f67fdd99a1af377da22d03d8fb959d2481845c1" +checksum = "6ff33d09331cc22bf4771a2633b62afc1038e36273eef22bff12f53d33decd91" dependencies = [ - "dunce", "log", "raw-window-handle 0.6.2", "rfd", @@ -6036,12 +6467,14 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.0.0-rc.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "694a746b0e0c1d318198fabf4957800c42fb4b705e866e0eed7ec21476ef88db" +checksum = "16d0816b27207c29aaff632c73b702785140cf16fe6150c201a2720245b8ea88" dependencies = [ "anyhow", + "dunce", "glob", + "percent-encoding", "schemars", "serde", "serde_json", @@ -6055,9 +6488,9 @@ dependencies = [ [[package]] name = "tauri-plugin-global-shortcut" -version = "2.0.0-rc.2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91f141154ffde51f57325dc324f696c2c7b5f194d2228a5ec46b1c419f81dd76" +checksum = "2c15fb7f5e4c80a73ce97217dcff27e423f496178cbcb87e13b4efe99eebb550" dependencies = [ "global-hotkey", "log", @@ -6070,9 +6503,9 @@ dependencies = [ [[package]] name = "tauri-plugin-notification" -version = "2.0.0-rc.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf32fba3a2650f89c7dfc532b38de566a37779e482f07dccabf45fe24444e26" +checksum = "ef492a2d19b6376bb4c9e0c4fab3f3bf8a220ea112d24f35027b737ff55de20c" dependencies = [ "log", "notify-rust", @@ -6089,9 +6522,9 @@ dependencies = [ [[package]] name = "tauri-plugin-process" -version = "2.0.0-rc.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9eb80b601682dcbd45dc5ed5f7cc214f1d994aeea730d500899cc616784559" +checksum = "ae06a00087c148962a52814a2d7265b1a0505bced5ffb74f8c284a5f96a4d03d" dependencies = [ "tauri", "tauri-plugin", @@ -6099,9 +6532,9 @@ dependencies = [ [[package]] name = "tauri-plugin-shell" -version = "2.0.0-rc.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83800ddf78b820172efb5ed7310344e8e4f97fd30cd8237a3f20c12a79eb136" +checksum = "0ad7880c5586b6b2104be451e3d7fc0f3800c84bda69e9ba81c828f87cb34267" dependencies = [ "encoding_rs", "log", @@ -6120,9 +6553,9 @@ dependencies = [ [[package]] name = "tauri-plugin-updater" -version = "2.0.0-rc.2" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7048854b4271f3bc58ee850f0582f8d9bb0190118afa8397f36fc260daaa68b" +checksum = "1dd3d2fe0f02bf52eebb5a9d23b987fffac6684646ab6fd683d706dafb18da87" dependencies = [ "base64 0.22.1", "dirs 5.0.1", @@ -6131,6 +6564,7 @@ dependencies = [ "http 1.1.0", "infer", "minisign-verify", + "percent-encoding", "reqwest", "semver 1.0.23", "serde", @@ -6149,9 +6583,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.0.0-rc.7" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c72b844f387bfc3341c355f3e16b8cbf4161848fa4e348670effb222cd3ba5" +checksum = "c8f437293d6f5e5dce829250f4dbdce4e0b52905e297a6689cc2963eb53ac728" dependencies = [ "dpi", "gtk", @@ -6168,15 +6602,17 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.0.0-rc.7" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73accf936a7cd01d1382de7850726fdf6c1f6ab3b01ccb7a0950cb852e332596" +checksum = "1431602bcc71f2f840ad623915c9842ecc32999b867c4a787d975a17a9625cc6" dependencies = [ - "cocoa 0.26.0", "gtk", "http 1.1.0", "jni", "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", "percent-encoding", "raw-window-handle 0.6.2", "softbuffer", @@ -6193,9 +6629,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.0-rc.7" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53d9fe87e985b273696ae22ce2b9f099a8f1b44bc8fb127467bda5fcb3e4371" +checksum = "c38b0230d6880cf6dd07b6d7dd7789a0869f98ac12146e0d18d1c1049215a045" dependencies = [ "brotli", "cargo_metadata", @@ -6223,6 +6659,7 @@ dependencies = [ "toml 0.8.2", "url", "urlpattern", + "uuid", "walkdir", ] @@ -6249,14 +6686,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand 2.1.1", "once_cell", - "rustix 0.38.35", + "rustix 0.38.37", "windows-sys 0.59.0", ] @@ -6309,7 +6746,7 @@ dependencies = [ "libc", "log", "memmem", - "num-derive", + "num-derive 0.3.3", "num-traits", "ordered-float", "regex", @@ -6339,22 +6776,22 @@ checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -6422,6 +6859,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinystr" version = "0.7.6" @@ -6484,7 +6930,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -6510,9 +6956,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -6533,9 +6979,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -6583,7 +7029,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -6596,7 +7042,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -6617,7 +7063,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.31", "hyper-timeout", "percent-encoding", "pin-project", @@ -6653,7 +7099,7 @@ dependencies = [ "bytes", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.31", "pin-project", "tokio-stream", "tonic", @@ -6733,7 +7179,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -6777,9 +7223,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.16.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131a65b2cef2081bc14dbcd414c906edbfa3bb5323dd7e748cc298614681196b" +checksum = "7c92af36a182b46206723bdf8a7942e20838cde1cf062e5b97854d57eb01763b" dependencies = [ "core-graphics 0.24.0", "crossbeam-channel", @@ -6796,6 +7242,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "trim-in-place" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" + [[package]] name = "try-lock" version = "0.2.5" @@ -6844,9 +7296,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uds_windows" @@ -6902,39 +7354,36 @@ dependencies = [ [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unsafe-any-ors" @@ -6971,11 +7420,10 @@ dependencies = [ [[package]] name = "urlpattern" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9bd5ff03aea02fa45b13a7980151fe45009af1980ba69f651ec367121a31609" +checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" dependencies = [ - "derive_more", "regex", "serde", "unic-ucd-ident", @@ -7018,11 +7466,23 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom 0.2.15", + "serde", +] + +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", ] [[package]] @@ -7114,7 +7574,7 @@ dependencies = [ "futures-util", "headers", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.31", "log", "mime", "mime_guess", @@ -7146,9 +7606,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -7157,24 +7617,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -7184,9 +7644,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7194,28 +7654,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ "futures-util", "js-sys", @@ -7225,10 +7685,70 @@ dependencies = [ ] [[package]] -name = "web-sys" -version = "0.3.70" +name = "wayland-backend" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix 0.38.37", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" +dependencies = [ + "bitflags 2.6.0", + "rustix 0.38.37", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml 0.36.2", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -7280,9 +7800,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.5" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -7309,7 +7829,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -7338,7 +7858,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.35", + "rustix 0.38.37", ] [[package]] @@ -7386,36 +7906,18 @@ dependencies = [ [[package]] name = "window-vibrancy" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8cdd6999298d969289d8078dae02ce798ad23452075985cccba8b6326711ecf" +checksum = "3ea403deff7b51fff19e261330f71608ff2cdef5721d72b64180bb95be7c4150" dependencies = [ - "cocoa 0.26.0", - "objc", + "objc2", + "objc2-app-kit", + "objc2-foundation", "raw-window-handle 0.6.2", "windows-sys 0.59.0", "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core 0.52.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.56.0" @@ -7426,6 +7928,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.58.0" @@ -7457,6 +7969,18 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.58.0" @@ -7466,7 +7990,7 @@ dependencies = [ "windows-implement 0.58.0", "windows-interface 0.58.0", "windows-result 0.2.0", - "windows-strings", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] @@ -7478,7 +8002,18 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.81", ] [[package]] @@ -7489,7 +8024,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -7500,7 +8035,18 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.81", ] [[package]] @@ -7511,7 +8057,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -7521,7 +8067,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result 0.2.0", - "windows-strings", + "windows-strings 0.1.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafa604f2104cf5ae2cc2db1dee84b7e6a5d11b05f737b60def0ffdc398cbc0a" +dependencies = [ + "windows-result 0.2.0", + "windows-strings 0.2.0", "windows-targets 0.52.6", ] @@ -7553,6 +8110,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978d65aedf914c664c510d9de43c8fd85ca745eaff1ed53edf409b479e441663" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -7818,14 +8384,12 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "wry" -version = "0.42.0" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b8049c8f239cdbfaaea4bacb9646f6b208938ceec0acd5b3e99cd05f70903f" +checksum = "6fa1c8c760041c64ce6be99f83d6cb55fe3fcd85a1ad46d32895f6e65cee87ba" dependencies = [ "base64 0.22.1", - "block", - "cocoa 0.26.0", - "core-graphics 0.24.0", + "block2", "crossbeam-channel", "dpi", "dunce", @@ -7838,8 +8402,11 @@ dependencies = [ "kuchikiki", "libc", "ndk", - "objc", - "objc_id", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", "once_cell", "percent-encoding", "raw-window-handle 0.6.2", @@ -7885,7 +8452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "gethostname", - "rustix 0.38.35", + "rustix 0.38.37", "x11rb-protocol", ] @@ -7903,7 +8470,7 @@ checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", "linux-raw-sys 0.4.14", - "rustix 0.38.35", + "rustix 0.38.37", ] [[package]] @@ -7942,7 +8509,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", "synstructure", ] @@ -7957,7 +8524,7 @@ dependencies = [ "async-fs 2.1.2", "async-io 2.3.4", "async-lock 3.4.0", - "async-process 2.2.4", + "async-process 2.3.0", "async-recursion", "async-task", "async-trait", @@ -8029,7 +8596,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -8049,7 +8616,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", "synstructure", ] @@ -8078,7 +8645,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.81", ] [[package]] @@ -8091,11 +8658,17 @@ dependencies = [ "crc32fast", "crossbeam-utils", "displaydoc", - "indexmap 2.5.0", + "indexmap 2.6.0", "memchr", "thiserror", ] +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + [[package]] name = "zune-inflate" version = "0.2.54" @@ -8105,6 +8678,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "zune-jpeg" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" +dependencies = [ + "zune-core", +] + [[package]] name = "zvariant" version = "4.0.0" diff --git a/clash-verge-rev/src-tauri/Cargo.toml b/clash-verge-rev/src-tauri/Cargo.toml old mode 100644 new mode 100755 index f39a2a4dfc..00b6da9860 --- a/clash-verge-rev/src-tauri/Cargo.toml +++ b/clash-verge-rev/src-tauri/Cargo.toml @@ -22,8 +22,8 @@ dunce = "1.0" log4rs = "1" nanoid = "0.4" chrono = "0.4" -sysinfo = "0.30" -boa_engine = "0.18" +sysinfo = "0.31.4" +boa_engine = "0.19.1" serde_json = "1.0" serde_yaml = "0.9" once_cell = "1.19" @@ -36,7 +36,7 @@ window-shadows = { version = "0.2.2" } tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } reqwest = { version = "0.12", features = ["json", "rustls-tls"] } -sysproxy = { git = "https://github.com/zzzgydi/sysproxy-rs", branch = "main" } +sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs", branch = "main" } tauri = { version = "2.0.0-rc", features = [ "protocol-asset", "devtools", @@ -45,17 +45,21 @@ tauri = { version = "2.0.0-rc", features = [ "image-png", ] } network-interface = { version = "2.0.0", features = ["serde"] } -tauri-plugin-shell = "2.0.0-rc" -tauri-plugin-dialog = "2.0.0-rc" -tauri-plugin-fs = "2.0.0-rc" -tauri-plugin-notification = "2.0.0-rc" -tauri-plugin-process = "2.0.0-rc" -tauri-plugin-clipboard-manager = "2.1.0-beta.7" +tauri-plugin-shell = "2.0.2" +tauri-plugin-dialog = "2.0.2" +tauri-plugin-fs = "2.0.2" +tauri-plugin-notification = "2.0.1" +tauri-plugin-process = "2.0.1" +tauri-plugin-clipboard-manager = "2.0.1" +tauri-plugin-deep-link = "2.0.1" tauri-plugin-devtools = "2.0.0-rc" +url = "2.5.2" [target.'cfg(windows)'.dependencies] runas = "=1.2.0" deelevate = "0.2.0" winreg = "0.52.0" +url = "2.5.2" + [target.'cfg(target_os = "linux")'.dependencies] users = "0.11.0" @@ -79,3 +83,7 @@ strip = true [profile.dev] incremental = true + +[lib] +name = "app_lib" +crate-type = ["staticlib", "cdylib", "rlib"] diff --git a/clash-verge-rev/src-tauri/Info.plist b/clash-verge-rev/src-tauri/Info.plist deleted file mode 100644 index 954d43a9c9..0000000000 --- a/clash-verge-rev/src-tauri/Info.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - -CFBundleURLTypes - - - CFBundleURLName - Clash Verge - CFBundleURLSchemes - - clash - - - - - \ No newline at end of file diff --git a/clash-verge-rev/src-tauri/capabilities/desktop.json b/clash-verge-rev/src-tauri/capabilities/desktop.json old mode 100644 new mode 100755 index c4936c0d7e..fbb332b0eb --- a/clash-verge-rev/src-tauri/capabilities/desktop.json +++ b/clash-verge-rev/src-tauri/capabilities/desktop.json @@ -3,5 +3,9 @@ "platforms": ["macOS", "windows", "linux"], "webviews": ["main"], "windows": ["main"], - "permissions": ["global-shortcut:default", "updater:default"] + "permissions": [ + "global-shortcut:default", + "updater:default", + "deep-link:default" + ] } diff --git a/clash-verge-rev/src-tauri/capabilities/migrated.json b/clash-verge-rev/src-tauri/capabilities/migrated.json index f707b9d649..7cce56b504 100644 --- a/clash-verge-rev/src-tauri/capabilities/migrated.json +++ b/clash-verge-rev/src-tauri/capabilities/migrated.json @@ -11,6 +11,11 @@ "identifier": "fs:scope", "allow": ["$APPDATA/**", "$RESOURCE/../**", "**"] }, + "fs:allow-write-file", + { + "identifier": "fs:scope", + "allow": ["$APPDATA/**", "$RESOURCE/../**", "**"] + }, "core:window:allow-create", "core:window:allow-center", "core:window:allow-request-user-attention", @@ -43,6 +48,13 @@ "core:window:allow-set-cursor-position", "core:window:allow-set-ignore-cursor-events", "core:window:allow-start-dragging", + "core:window:allow-maximize", + "core:window:allow-toggle-maximize", + "core:window:allow-unmaximize", + "core:window:allow-minimize", + "core:window:allow-unminimize", + "core:window:allow-set-maximizable", + "core:window:allow-set-minimizable", "core:webview:allow-print", "shell:allow-execute", "shell:allow-open", diff --git a/clash-verge-rev/src-tauri/src/cmds.rs b/clash-verge-rev/src-tauri/src/cmds.rs index a560fd8041..a2c7cb8ac5 100644 --- a/clash-verge-rev/src-tauri/src/cmds.rs +++ b/clash-verge-rev/src-tauri/src/cmds.rs @@ -2,7 +2,7 @@ use crate::{ config::*, core::*, feat, - utils::{dirs, help, resolve}, + utils::{dirs, help}, }; use crate::{ret_err, wrap_err}; use anyhow::{Context, Result}; @@ -14,8 +14,8 @@ type CmdResult = Result; use tauri::Manager; #[tauri::command] -pub fn copy_clash_env(app_handle: tauri::AppHandle) -> CmdResult { - feat::copy_clash_env(&app_handle); +pub fn copy_clash_env() -> CmdResult { + feat::copy_clash_env(); Ok(()) } @@ -185,7 +185,7 @@ pub async fn change_clash_core(clash_core: Option) -> CmdResult { /// restart the sidecar #[tauri::command] pub async fn restart_sidecar() -> CmdResult { - wrap_err!(CoreManager::global().run_core().await) + wrap_err!(CoreManager::global().restart_core().await) } /// get the system proxy @@ -337,7 +337,7 @@ pub fn get_network_interfaces() -> Vec { for (interface_name, _) in &networks { result.push(interface_name.clone()); } - return result; + result } #[tauri::command] @@ -371,11 +371,8 @@ pub fn open_devtools(app_handle: tauri::AppHandle) { } #[tauri::command] -pub fn exit_app(app_handle: tauri::AppHandle) { - let _ = resolve::save_window_size_position(&app_handle, true); - resolve::resolve_reset(); - app_handle.exit(0); - std::process::exit(0); +pub fn exit_app() { + feat::quit(Some(0)); } pub mod service { @@ -386,16 +383,6 @@ pub mod service { pub async fn check_service() -> CmdResult { wrap_err!(service::check_service().await) } - - #[tauri::command] - pub async fn install_service(passwd: String) -> CmdResult { - wrap_err!(service::install_service(passwd).await) - } - - #[tauri::command] - pub async fn uninstall_service(passwd: String) -> CmdResult { - wrap_err!(service::uninstall_service(passwd).await) - } } #[cfg(not(windows))] diff --git a/clash-verge-rev/src-tauri/src/config/clash.rs b/clash-verge-rev/src-tauri/src/config/clash.rs index e1d4aa3ed5..8054ccae8b 100644 --- a/clash-verge-rev/src-tauri/src/config/clash.rs +++ b/clash-verge-rev/src-tauri/src/config/clash.rs @@ -32,13 +32,12 @@ impl IClashTemp { pub fn template() -> Self { let mut map = Mapping::new(); let mut tun = Mapping::new(); + tun.insert("enable".into(), false.into()); tun.insert("stack".into(), "gvisor".into()); - tun.insert("device".into(), "Mihomo".into()); tun.insert("auto-route".into(), true.into()); tun.insert("strict-route".into(), false.into()); tun.insert("auto-detect-interface".into(), true.into()); tun.insert("dns-hijack".into(), vec!["any:53"].into()); - tun.insert("mtu".into(), 1500.into()); #[cfg(not(target_os = "windows"))] map.insert("redir-port".into(), 7895.into()); #[cfg(target_os = "linux")] @@ -50,9 +49,12 @@ impl IClashTemp { map.insert("allow-lan".into(), false.into()); map.insert("mode".into(), "rule".into()); map.insert("external-controller".into(), "127.0.0.1:9097".into()); + let mut cors_map = Mapping::new(); + cors_map.insert("allow-private-network".into(), true.into()); + cors_map.insert("allow-origins".into(), vec!["*"].into()); map.insert("secret".into(), "".into()); map.insert("tun".into(), tun.into()); - + map.insert("external-controller-cors".into(), cors_map.into()); Self(map) } diff --git a/clash-verge-rev/src-tauri/src/config/verge.rs b/clash-verge-rev/src-tauri/src/config/verge.rs index 6086b8cea7..3f9888315d 100644 --- a/clash-verge-rev/src-tauri/src/config/verge.rs +++ b/clash-verge-rev/src-tauri/src/config/verge.rs @@ -7,9 +7,6 @@ use serde::{Deserialize, Serialize}; /// ### `verge.yaml` schema #[derive(Default, Debug, Clone, Deserialize, Serialize)] pub struct IVerge { - /// app listening port for app singleton - pub app_singleton_port: Option, - /// app log level /// silent | error | warn | info | debug | trace pub app_log_level: Option, @@ -59,10 +56,6 @@ pub struct IVerge { /// clash tun mode pub enable_tun_mode: Option, - /// windows service mode - #[serde(skip_serializing_if = "Option::is_none")] - pub enable_service_mode: Option, - /// can the app auto startup pub enable_auto_launch: Option, @@ -282,7 +275,6 @@ impl IVerge { patch!(tun_tray_icon); patch!(enable_tun_mode); - patch!(enable_service_mode); patch!(enable_auto_launch); patch!(enable_silent_start); patch!(enable_random_port); @@ -330,11 +322,7 @@ impl IVerge { const SERVER_PORT: u16 = 33331; #[cfg(feature = "verge-dev")] const SERVER_PORT: u16 = 11233; - - match dirs::verge_path().and_then(|path| help::read_yaml::(&path)) { - Ok(config) => config.app_singleton_port.unwrap_or(SERVER_PORT), - Err(_) => SERVER_PORT, // 这里就不log错误了 - } + SERVER_PORT } /// 获取日志等级 diff --git a/clash-verge-rev/src-tauri/src/core/clash_api.rs b/clash-verge-rev/src-tauri/src/core/clash_api.rs index 67fc112de0..4a21fa2810 100644 --- a/clash-verge-rev/src-tauri/src/core/clash_api.rs +++ b/clash-verge-rev/src-tauri/src/core/clash_api.rs @@ -127,7 +127,7 @@ pub fn parse_check_output(log: String) -> String { #[test] fn test_parse_check_output() { let str1 = r#"xxxx\n time="2022-11-18T20:42:58+08:00" level=error msg="proxy 0: 'alpn' expected type 'string', got unconvertible type '[]interface {}'""#; - let str2 = r#"20:43:49 ERR [Config] configuration file test failed error=proxy 0: unsupport proxy type: hysteria path=xxx"#; + //let str2 = r#"20:43:49 ERR [Config] configuration file test failed error=proxy 0: unsupport proxy type: hysteria path=xxx"#; let str3 = r#" "time="2022-11-18T21:38:01+08:00" level=info msg="Start initial configuration in progress" time="2022-11-18T21:38:01+08:00" level=error msg="proxy 0: 'alpn' expected type 'string', got unconvertible type '[]interface {}'" @@ -135,12 +135,8 @@ fn test_parse_check_output() { "#; let res1 = parse_check_output(str1.into()); - let res2 = parse_check_output(str2.into()); + // let res2 = parse_check_output(str2.into()); let res3 = parse_check_output(str3.into()); - println!("res1: {res1}"); - println!("res2: {res2}"); - println!("res3: {res3}"); - assert_eq!(res1, res3); } diff --git a/clash-verge-rev/src-tauri/src/core/core.rs b/clash-verge-rev/src-tauri/src/core/core.rs index 09d127022f..ea02df957e 100644 --- a/clash-verge-rev/src-tauri/src/core/core.rs +++ b/clash-verge-rev/src-tauri/src/core/core.rs @@ -2,46 +2,32 @@ use crate::config::*; use crate::core::{clash_api, handle, logger::Logger, service}; use crate::log_err; use crate::utils::dirs; -use anyhow::{bail, Context, Result}; +use anyhow::{bail, Result}; use once_cell::sync::OnceCell; -use parking_lot::Mutex; use serde_yaml::Mapping; -use std::{fs, io::Write, sync::Arc, time::Duration}; -use sysinfo::{ProcessRefreshKind, RefreshKind, System}; -use tauri::AppHandle; -use tauri_plugin_shell::process::{CommandChild, CommandEvent}; +use std::{sync::Arc, time::Duration}; use tauri_plugin_shell::ShellExt; - +use tokio::sync::Mutex; use tokio::time::sleep; #[derive(Debug)] pub struct CoreManager { - app_handle: Arc>>, - sidecar: Arc>>, - #[allow(unused)] - use_service_mode: Arc>, + running: Arc>, } impl CoreManager { pub fn global() -> &'static CoreManager { static CORE_MANAGER: OnceCell = OnceCell::new(); - CORE_MANAGER.get_or_init(|| CoreManager { - app_handle: Arc::new(Mutex::new(None)), - sidecar: Arc::new(Mutex::new(None)), - use_service_mode: Arc::new(Mutex::new(false)), + running: Arc::new(Mutex::new(false)), }) } - pub fn init(&self, app_handle: &AppHandle) -> Result<()> { - *self.app_handle.lock() = Some(app_handle.clone()); - tauri::async_runtime::spawn(async { - log::trace!("run core start"); - // 启动clash - log_err!(Self::global().run_core().await); - log::trace!("run core end"); - }); - + pub async fn init(&self) -> Result<()> { + log::trace!("run core start"); + // 启动clash + log_err!(Self::global().start_core().await); + log::trace!("run core end"); Ok(()) } @@ -51,241 +37,86 @@ impl CoreManager { let config_path = dirs::path_to_str(&config_path)?; let clash_core = { Config::verge().latest().clash_core.clone() }; - let mut clash_core = clash_core.unwrap_or("verge-mihomo".into()); - - // compatibility - if clash_core.contains("clash") { - clash_core = "verge-mihomo".to_string(); - Config::verge().draft().patch_config(IVerge { - clash_core: Some("verge-mihomo".to_string()), - ..IVerge::default() - }); - Config::verge().apply(); - match Config::verge().data().save_file() { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - } + let clash_core = clash_core.unwrap_or("verge-mihomo".into()); let test_dir = dirs::app_home_dir()?.join("test"); let test_dir = dirs::path_to_str(&test_dir)?; - let app_handle_option = { - let lock = self.app_handle.lock(); - lock.as_ref().cloned() - }; + let app_handle = handle::Handle::global().app_handle().unwrap(); - if let Some(app_handle) = app_handle_option { - let output = app_handle - .shell() - .sidecar(clash_core)? - .args(["-t", "-d", test_dir, "-f", config_path]) - .output() - .await?; + let output = app_handle + .shell() + .sidecar(clash_core)? + .args(["-t", "-d", test_dir, "-f", config_path]) + .output() + .await?; - if !output.status.success() { - let stdout = String::from_utf8(output.stdout).unwrap_or_default(); - let error = clash_api::parse_check_output(stdout.clone()); - let error = match !error.is_empty() { - true => error, - false => stdout.clone(), - }; - Logger::global().set_log(stdout.clone()); - bail!("{error}"); - } + if !output.status.success() { + let stdout = String::from_utf8(output.stdout).unwrap_or_default(); + let error = clash_api::parse_check_output(stdout.clone()); + let error = match !error.is_empty() { + true => error, + false => stdout.clone(), + }; + Logger::global().set_log(stdout.clone()); + bail!("{error}"); } Ok(()) } - /// 启动核心 - pub async fn run_core(&self) -> Result<()> { - let config_path = Config::generate_file(ConfigType::Run)?; - - // 关闭tun模式 - let mut disable = Mapping::new(); - let mut tun = Mapping::new(); - tun.insert("enable".into(), false.into()); - disable.insert("tun".into(), tun.into()); - log::debug!(target: "app", "disable tun mode"); - let _ = clash_api::patch_configs(&disable).await; - - if *self.use_service_mode.lock() { - log::debug!(target: "app", "stop the core by service"); - log_err!(service::stop_core_by_service().await); - } else { - let system = System::new_with_specifics( - RefreshKind::new().with_processes(ProcessRefreshKind::everything()), - ); - let procs = system.processes_by_name("verge-mihomo"); - - for proc in procs { - log::debug!(target: "app", "kill all clash process"); - proc.kill(); - } - } - - // 服务模式 - let enable = { Config::verge().latest().enable_service_mode }; - let enable = enable.unwrap_or(false); - - *self.use_service_mode.lock() = enable; - - if enable { - // 服务模式启动失败就直接运行sidecar - log::debug!(target: "app", "try to run core in service mode"); - - let res = async { - service::check_service().await?; - service::run_core_by_service(&config_path).await - } - .await; - match res { - Ok(_) => return Ok(()), - Err(err) => { - // 修改这个值,免得stop出错 - *self.use_service_mode.lock() = false; - log::error!(target: "app", "{err}"); - } - } - } - - let app_dir = dirs::app_home_dir()?; - let app_dir = dirs::path_to_str(&app_dir)?; - - let clash_core = { Config::verge().latest().clash_core.clone() }; - let mut clash_core = clash_core.unwrap_or("verge-mihomo".into()); - - // compatibility - if clash_core.contains("clash") { - clash_core = "verge-mihomo".to_string(); - Config::verge().draft().patch_config(IVerge { - clash_core: Some("verge-mihomo".to_string()), - ..IVerge::default() - }); - Config::verge().apply(); - match Config::verge().data().save_file() { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - } - - let config_path = dirs::path_to_str(&config_path)?; - - let args = vec!["-d", app_dir, "-f", config_path]; - - let app_handle = self.app_handle.lock(); - - if let Some(app_handle) = app_handle.as_ref() { - let cmd = app_handle.shell().sidecar(clash_core)?; - let (mut rx, cmd_child) = cmd.args(args).spawn()?; - - // 将pid写入文件中 - crate::log_err!((|| { - let pid = cmd_child.pid(); - let path = dirs::clash_pid_path()?; - fs::File::create(path) - .context("failed to create the pid file")? - .write(format!("{pid}").as_bytes()) - .context("failed to write pid to the file")?; - >::Ok(()) - })()); - - let mut sidecar = self.sidecar.lock(); - *sidecar = Some(cmd_child); - drop(sidecar); - - tauri::async_runtime::spawn(async move { - while let Some(event) = rx.recv().await { - match event { - CommandEvent::Stdout(line) => { - let line = String::from_utf8(line).unwrap_or_default(); - log::info!(target: "app", "[mihomo]: {line}"); - Logger::global().set_log(line); - } - CommandEvent::Stderr(err) => { - let err = String::from_utf8(err).unwrap_or_default(); - log::error!(target: "app", "[mihomo]: {err}"); - Logger::global().set_log(err); - } - CommandEvent::Error(err) => { - log::error!(target: "app", "[mihomo]: {err}"); - Logger::global().set_log(err); - } - CommandEvent::Terminated(_) => { - log::info!(target: "app", "mihomo core terminated"); - let _ = CoreManager::global().recover_core(); - break; - } - _ => {} - } - } - }); - } - - Ok(()) - } - - /// 重启内核 - pub fn recover_core(&'static self) -> Result<()> { - // 服务模式不管 - if *self.use_service_mode.lock() { - return Ok(()); - } - - // 清空原来的sidecar值 - let _ = self.sidecar.lock().take(); - - tauri::async_runtime::spawn(async move { - // 6秒之后再查看服务是否正常 (时间随便搞的) - // terminated 可能是切换内核 (切换内核已经有500ms的延迟) - sleep(Duration::from_millis(6666)).await; - - if self.sidecar.lock().is_none() { - log::info!(target: "app", "recover clash core"); - - // 重新启动app - if let Err(err) = self.run_core().await { - log::error!(target: "app", "failed to recover clash core"); - log::error!(target: "app", "{err}"); - - let _ = self.recover_core(); - } - } - }); - - Ok(()) - } - /// 停止核心运行 pub async fn stop_core(&self) -> Result<()> { + let mut running = self.running.lock().await; + + if !*running { + log::debug!("core is not running"); + return Ok(()); + } + // 关闭tun模式 let mut disable = Mapping::new(); let mut tun = Mapping::new(); tun.insert("enable".into(), false.into()); disable.insert("tun".into(), tun.into()); log::debug!(target: "app", "disable tun mode"); - let _ = clash_api::patch_configs(&disable).await; + log_err!(clash_api::patch_configs(&disable).await); - if *self.use_service_mode.lock() { - log::debug!(target: "app", "stop the core by service"); - log_err!(service::stop_core_by_service().await); + // 服务模式 + if service::check_service().await.is_ok() { + log::info!(target: "app", "stop the core by service"); + service::stop_core_by_service().await?; + } + *running = false; + Ok(()) + } + + /// 启动核心 + pub async fn start_core(&self) -> Result<()> { + let mut running = self.running.lock().await; + if *running { + log::info!("core is running"); return Ok(()); } - let mut sidecar = self.sidecar.lock(); - let _ = sidecar.take(); + let config_path = Config::generate_file(ConfigType::Run)?; - let system = System::new_with_specifics( - RefreshKind::new().with_processes(ProcessRefreshKind::everything()), - ); - let procs = system.processes_by_name("verge-mihomo"); - for proc in procs { - log::debug!(target: "app", "kill all clash process"); - proc.kill(); + // 服务模式 + if service::check_service().await.is_ok() { + log::info!(target: "app", "try to run core in service mode"); + service::run_core_by_service(&config_path).await?; + *running = true; } Ok(()) } + /// 重启内核 + pub async fn restart_core(&self) -> Result<()> { + // 重新启动app + self.stop_core().await?; + self.start_core().await?; + Ok(()) + } + /// 切换核心 pub async fn change_core(&self, clash_core: Option) -> Result<()> { let clash_core = clash_core.ok_or(anyhow::anyhow!("clash core is null"))?; @@ -295,7 +126,7 @@ impl CoreManager { bail!("invalid clash core name \"{clash_core}\""); } - log::debug!(target: "app", "change core to `{clash_core}`"); + log::info!(target: "app", "change core to `{clash_core}`"); Config::verge().draft().clash_core = Some(clash_core); @@ -307,7 +138,7 @@ impl CoreManager { // 清掉旧日志 Logger::global().clear_log(); - match self.run_core().await { + match self.restart_core().await { Ok(_) => { Config::verge().apply(); Config::runtime().apply(); diff --git a/clash-verge-rev/src-tauri/src/core/handle.rs b/clash-verge-rev/src-tauri/src/core/handle.rs index 614356cc10..19eed0ee96 100644 --- a/clash-verge-rev/src-tauri/src/core/handle.rs +++ b/clash-verge-rev/src-tauri/src/core/handle.rs @@ -1,14 +1,14 @@ use super::tray::Tray; use crate::log_err; -use anyhow::{bail, Result}; +use anyhow::Result; use once_cell::sync::OnceCell; -use parking_lot::Mutex; +use parking_lot::RwLock; use std::sync::Arc; -use tauri::{AppHandle, WebviewWindow, Manager, Emitter}; +use tauri::{AppHandle, Emitter, Manager, WebviewWindow}; #[derive(Debug, Default, Clone)] pub struct Handle { - pub app_handle: Arc>>, + pub app_handle: Arc>>, } impl Handle { @@ -16,17 +16,21 @@ impl Handle { static HANDLE: OnceCell = OnceCell::new(); HANDLE.get_or_init(|| Handle { - app_handle: Arc::new(Mutex::new(None)), + app_handle: Arc::new(RwLock::new(None)), }) } pub fn init(&self, app_handle: &AppHandle) { - *self.app_handle.lock() = Some(app_handle.clone()); + let mut handle = self.app_handle.write(); + *handle = Some(app_handle.clone()); + } + + pub fn app_handle(&self) -> Option { + self.app_handle.read().clone() } pub fn get_window(&self) -> Option { - self.app_handle - .lock() + self.app_handle() .as_ref() .and_then(|a| a.get_webview_window("main")) } @@ -56,22 +60,9 @@ impl Handle { } } - pub fn update_systray() -> Result<()> { - let app_handle = Self::global().app_handle.lock(); - if app_handle.is_none() { - bail!("update_systray unhandled error"); - } - Tray::update_systray(app_handle.as_ref().unwrap())?; - Ok(()) - } - /// update the system tray state pub fn update_systray_part() -> Result<()> { - let app_handle = Self::global().app_handle.lock(); - if app_handle.is_none() { - bail!("update_systray unhandled error"); - } - Tray::update_part(app_handle.as_ref().unwrap())?; + Tray::update_part()?; Ok(()) } } diff --git a/clash-verge-rev/src-tauri/src/core/hotkey.rs b/clash-verge-rev/src-tauri/src/core/hotkey.rs old mode 100644 new mode 100755 index e53fdffcaa..a51af840ac --- a/clash-verge-rev/src-tauri/src/core/hotkey.rs +++ b/clash-verge-rev/src-tauri/src/core/hotkey.rs @@ -1,14 +1,13 @@ +use crate::core::handle; use crate::{config::Config, feat, log_err}; use anyhow::{bail, Result}; use once_cell::sync::OnceCell; use parking_lot::Mutex; use std::{collections::HashMap, sync::Arc}; -use tauri::AppHandle; -use tauri_plugin_global_shortcut::GlobalShortcutExt; - +use tauri::Manager; +use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, ShortcutState}; pub struct Hotkey { current: Arc>>, // 保存当前的热键设置 - app_handle: Arc>>, } impl Hotkey { @@ -17,12 +16,10 @@ impl Hotkey { HOTKEY.get_or_init(|| Hotkey { current: Arc::new(Mutex::new(Vec::new())), - app_handle: Arc::new(Mutex::new(None)), }) } - pub fn init(&self, app_handle: &AppHandle) -> Result<()> { - *self.app_handle.lock() = Some(app_handle.clone()); + pub fn init(&self) -> Result<()> { let verge = Config::verge(); if let Some(hotkeys) = verge.latest().hotkeys.as_ref() { @@ -48,12 +45,9 @@ impl Hotkey { Ok(()) } - fn register(&self, hotkey: &str, func: &str) -> Result<()> { - let app_handle = self.app_handle.lock(); - if app_handle.is_none() { - bail!("failed to get the hotkey manager"); - } - let manager = app_handle.as_ref().unwrap().global_shortcut(); + pub fn register(&self, hotkey: &str, func: &str) -> Result<()> { + let app_handle = handle::Handle::global().app_handle().unwrap(); + let manager = app_handle.global_shortcut(); if manager.is_registered(hotkey) { manager.unregister(hotkey)?; @@ -66,20 +60,32 @@ impl Hotkey { "clash_mode_direct" => || feat::change_clash_mode("direct".into()), "toggle_system_proxy" => feat::toggle_system_proxy, "toggle_tun_mode" => feat::toggle_tun_mode, + "quit" => || feat::quit(Some(0)), + _ => bail!("invalid function \"{func}\""), }; - let _ = manager.on_shortcut(hotkey, move |_, _, _| f()); + let _ = manager.on_shortcut(hotkey, move |app_handle, hotkey, event| { + if event.state == ShortcutState::Pressed { + if hotkey.key == Code::KeyQ { + if let Some(window) = app_handle.get_webview_window("main") { + if window.is_focused().unwrap_or(false) { + f(); + } + } + } else { + f(); + } + } + }); + log::info!(target: "app", "register hotkey {hotkey} {func}"); Ok(()) } - fn unregister(&self, hotkey: &str) -> Result<()> { - let app_handle = self.app_handle.lock(); - if app_handle.is_none() { - bail!("failed to get the hotkey manager"); - } - let manager = app_handle.as_ref().unwrap().global_shortcut(); + pub fn unregister(&self, hotkey: &str) -> Result<()> { + let app_handle = handle::Handle::global().app_handle().unwrap(); + let manager = app_handle.global_shortcut(); manager.unregister(hotkey)?; log::info!(target: "app", "unregister hotkey {hotkey}"); @@ -105,7 +111,7 @@ impl Hotkey { Ok(()) } - fn get_map_from_vec(hotkeys: &Vec) -> HashMap<&str, &str> { + fn get_map_from_vec(hotkeys: &[String]) -> HashMap<&str, &str> { let mut map = HashMap::new(); hotkeys.iter().for_each(|hotkey| { @@ -153,10 +159,9 @@ impl Hotkey { impl Drop for Hotkey { fn drop(&mut self) { - if let Some(app_handle) = self.app_handle.lock().as_ref() { - if let Err(e) = app_handle.global_shortcut().unregister_all() { - log::error!("Error unregistering all hotkeys: {:?}", e); - } + let app_handle = handle::Handle::global().app_handle().unwrap(); + if let Err(e) = app_handle.global_shortcut().unregister_all() { + log::error!(target:"app", "Error unregistering all hotkeys: {:?}", e); } } } diff --git a/clash-verge-rev/src-tauri/src/core/service.rs b/clash-verge-rev/src-tauri/src/core/service.rs index 3a06648f96..66dd1936ab 100644 --- a/clash-verge-rev/src-tauri/src/core/service.rs +++ b/clash-verge-rev/src-tauri/src/core/service.rs @@ -1,13 +1,11 @@ -use crate::config::{Config, IVerge}; -use crate::core::handle; +use crate::config::Config; use crate::utils::dirs; use anyhow::{bail, Context, Result}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; -use std::time::Duration; use std::{env::current_exe, process::Command as StdCommand}; -use tokio::time::sleep; +use tokio::time::Duration; // Windows only @@ -28,32 +26,34 @@ pub struct JsonResponse { pub data: Option, } -#[cfg(not(target_os = "windows"))] -pub fn sudo(passwd: &String, cmd: String) -> StdCommand { - let shell = format!("echo \"{}\" | sudo -S {}", passwd, cmd); - let mut command = StdCommand::new("bash"); - command.arg("-c").arg(shell); - command -} - -/// Install the Clash Verge Service -/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程 -/// #[cfg(target_os = "windows")] -pub async fn install_service(_passwd: String) -> Result<()> { +pub async fn reinstall_service() -> Result<()> { + log::info!(target:"app", "reinstall service"); + use deelevate::{PrivilegeLevel, Token}; use runas::Command as RunasCommand; use std::os::windows::process::CommandExt; let binary_path = dirs::service_path()?; let install_path = binary_path.with_file_name("install-service.exe"); + let uninstall_path = binary_path.with_file_name("uninstall-service.exe"); if !install_path.exists() { - bail!("installer exe not found"); + bail!(format!("installer not found: {install_path:?}")); + } + + if !uninstall_path.exists() { + bail!(format!("uninstaller not found: {uninstall_path:?}")); } let token = Token::with_current_process()?; let level = token.privilege_level()?; + let _ = match level { + PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).show(false).status()?, + _ => StdCommand::new(uninstall_path) + .creation_flags(0x08000000) + .status()?, + }; let status = match level { PrivilegeLevel::NotPrivileged => RunasCommand::new(install_path).show(false).status()?, @@ -73,111 +73,48 @@ pub async fn install_service(_passwd: String) -> Result<()> { } #[cfg(target_os = "linux")] -pub async fn install_service(passwd: String) -> Result<()> { +pub async fn reinstall_service() -> Result<()> { + log::info!(target:"app", "reinstall service"); use users::get_effective_uid; - let binary_path = dirs::service_path()?; - let installer_path = binary_path.with_file_name("install-service"); - if !installer_path.exists() { - bail!("installer not found"); + let install_path = tauri::utils::platform::current_exe()?.with_file_name("install-service"); + + let uninstall_path = tauri::utils::platform::current_exe()?.with_file_name("uninstall-service"); + + if !install_path.exists() { + bail!(format!("installer not found: {install_path:?}")); } - let output = match get_effective_uid() { - 0 => { - StdCommand::new("chmod") - .arg("+x") - .arg(installer_path.clone()) - .output()?; - StdCommand::new("chmod") - .arg("+x") - .arg(binary_path) - .output()?; - StdCommand::new(installer_path.clone()).output()? - } - _ => { - sudo( - &passwd, - format!("chmod +x {}", installer_path.to_string_lossy()), - ) - .output()?; - sudo( - &passwd, - format!("chmod +x {}", binary_path.to_string_lossy()), - ) - .output()?; - sudo(&passwd, format!("{}", installer_path.to_string_lossy())).output()? - } - }; - if !output.status.success() { - bail!( - "failed to install service with error: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - - Ok(()) -} - -#[cfg(target_os = "macos")] -pub async fn install_service(passwd: String) -> Result<()> { - let binary_path = dirs::service_path()?; - let installer_path = binary_path.with_file_name("install-service"); - - if !installer_path.exists() { - bail!("installer not found"); - } - - sudo( - &passwd, - format!( - "chmod +x {}", - installer_path.to_string_lossy().replace(" ", "\\ ") - ), - ) - .output()?; - let output = sudo( - &passwd, - format!("{}", installer_path.to_string_lossy().replace(" ", "\\ ")), - ) - .output()?; - - if !output.status.success() { - bail!( - "failed to install service with error: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - - Ok(()) -} -/// Uninstall the Clash Verge Service -/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程 -#[cfg(target_os = "windows")] -pub async fn uninstall_service(_passwd: String) -> Result<()> { - use deelevate::{PrivilegeLevel, Token}; - use runas::Command as RunasCommand; - use std::os::windows::process::CommandExt; - - let binary_path = dirs::service_path()?; - let uninstall_path = binary_path.with_file_name("uninstall-service.exe"); - if !uninstall_path.exists() { - bail!("uninstaller exe not found"); + bail!(format!("uninstaller not found: {uninstall_path:?}")); } - let token = Token::with_current_process()?; - let level = token.privilege_level()?; + let install_shell: String = install_path.to_string_lossy().replace(" ", "\\ "); + let uninstall_shell: String = uninstall_path.to_string_lossy().replace(" ", "\\ "); - let status = match level { - PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).show(false).status()?, - _ => StdCommand::new(uninstall_path) - .creation_flags(0x08000000) + let elevator = crate::utils::help::linux_elevator(); + let status = match get_effective_uid() { + 0 => StdCommand::new(uninstall_shell).status()?, + _ => StdCommand::new(elevator.clone()) + .arg("sh") + .arg("-c") + .arg(uninstall_shell) + .status()?, + }; + log::info!(target:"app", "status code:{}", status.code().unwrap()); + + let status = match get_effective_uid() { + 0 => StdCommand::new(install_shell).status()?, + _ => StdCommand::new(elevator.clone()) + .arg("sh") + .arg("-c") + .arg(install_shell) .status()?, }; if !status.success() { bail!( - "failed to uninstall service with status {}", + "failed to install service with status {}", status.code().unwrap() ); } @@ -185,76 +122,38 @@ pub async fn uninstall_service(_passwd: String) -> Result<()> { Ok(()) } -#[cfg(target_os = "linux")] -pub async fn uninstall_service(passwd: String) -> Result<()> { - use users::get_effective_uid; - - let binary_path = dirs::service_path()?; - let uninstaller_path = binary_path.with_file_name("uninstall-service"); - - if !uninstaller_path.exists() { - bail!("uninstaller not found"); - } - - let output = match get_effective_uid() { - 0 => { - StdCommand::new("chmod") - .arg("+x") - .arg(uninstaller_path.clone()) - .output()?; - StdCommand::new(uninstaller_path.clone()).output()? - } - _ => { - sudo( - &passwd, - format!("chmod +x {}", uninstaller_path.to_string_lossy()), - ) - .output()?; - - sudo(&passwd, format!("{}", uninstaller_path.to_string_lossy())).output()? - } - }; - - if !output.status.success() { - bail!( - "failed to install service with error: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - - Ok(()) -} - #[cfg(target_os = "macos")] -pub async fn uninstall_service(passwd: String) -> Result<()> { - let binary_path = dirs::service_path()?; - let uninstaller_path = binary_path.with_file_name("uninstall-service"); +pub async fn reinstall_service() -> Result<()> { + log::info!(target:"app", "reinstall service"); - if !uninstaller_path.exists() { - bail!("uninstaller not found"); + let binary_path = dirs::service_path()?; + let install_path = binary_path.with_file_name("install-service"); + let uninstall_path = binary_path.with_file_name("uninstall-service"); + + if !install_path.exists() { + bail!(format!("installer not found: {install_path:?}")); } - sudo( - &passwd, - format!( - "chmod +x {}", - uninstaller_path.to_string_lossy().replace(" ", "\\ ") - ), - ) - .output()?; - let output = sudo( - &passwd, - format!("{}", uninstaller_path.to_string_lossy().replace(" ", "\\ ")), - ) - .output()?; + if !uninstall_path.exists() { + bail!(format!("uninstaller not found: {uninstall_path:?}")); + } - if !output.status.success() { + let install_shell: String = install_path.to_string_lossy().replace(" ", "\\ "); + let uninstall_shell: String = uninstall_path.to_string_lossy().replace(" ", "\\ "); + let command = format!( + r#"do shell script "sudo {uninstall_shell} && sudo {install_shell}" with administrator privileges"# + ); + + let status = StdCommand::new("osascript") + .args(vec!["-e", &command]) + .status()?; + + if !status.success() { bail!( - "failed to uninstall service with error: {}", - String::from_utf8_lossy(&output.stderr) + "failed to install service with status {}", + status.code().unwrap() ); } - Ok(()) } @@ -263,6 +162,7 @@ pub async fn check_service() -> Result { let url = format!("{SERVICE_URL}/get_clash"); let response = reqwest::ClientBuilder::new() .no_proxy() + .timeout(Duration::from_secs(3)) .build()? .get(url) .send() @@ -277,29 +177,8 @@ pub async fn check_service() -> Result { /// start the clash by service pub(super) async fn run_core_by_service(config_file: &PathBuf) -> Result<()> { - let status = check_service().await?; - - if status.code == 0 { - stop_core_by_service().await?; - sleep(Duration::from_secs(1)).await; - } - let clash_core = { Config::verge().latest().clash_core.clone() }; - let mut clash_core = clash_core.unwrap_or("verge-mihomo".into()); - - // compatibility - if clash_core.contains("clash") { - clash_core = "verge-mihomo".to_string(); - Config::verge().draft().patch_config(IVerge { - clash_core: Some("verge-mihomo".to_string()), - ..IVerge::default() - }); - Config::verge().apply(); - match Config::verge().data().save_file() { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - } + let clash_core = clash_core.unwrap_or("verge-mihomo".into()); let bin_ext = if cfg!(windows) { ".exe" } else { "" }; let clash_bin = format!("{clash_core}{bin_ext}"); @@ -321,81 +200,31 @@ pub(super) async fn run_core_by_service(config_file: &PathBuf) -> Result<()> { map.insert("config_file", config_file); map.insert("log_file", log_path); + log::info!(target:"app", "start service: {:?}", map.clone()); + let url = format!("{SERVICE_URL}/start_clash"); - let res = reqwest::ClientBuilder::new() + let _ = reqwest::ClientBuilder::new() .no_proxy() .build()? .post(url) .json(&map) .send() - .await? - .json::() .await .context("failed to connect to the Clash Verge Service")?; - if res.code != 0 { - bail!(res.msg); - } - Ok(()) } /// stop the clash by service pub(super) async fn stop_core_by_service() -> Result<()> { let url = format!("{SERVICE_URL}/stop_clash"); - let res = reqwest::ClientBuilder::new() + let _ = reqwest::ClientBuilder::new() .no_proxy() .build()? .post(url) .send() - .await? - .json::() .await .context("failed to connect to the Clash Verge Service")?; - if res.code != 0 { - bail!(res.msg); - } - - Ok(()) -} - -/// set dns by service -pub async fn set_dns_by_service() -> Result<()> { - let url = format!("{SERVICE_URL}/set_dns"); - let res = reqwest::ClientBuilder::new() - .no_proxy() - .build()? - .post(url) - .send() - .await? - .json::() - .await - .context("failed to connect to the Clash Verge Service")?; - - if res.code != 0 { - bail!(res.msg); - } - - Ok(()) -} - -/// unset dns by service -pub async fn unset_dns_by_service() -> Result<()> { - let url = format!("{SERVICE_URL}/unset_dns"); - let res = reqwest::ClientBuilder::new() - .no_proxy() - .build()? - .post(url) - .send() - .await? - .json::() - .await - .context("failed to connect to the Clash Verge Service")?; - - if res.code != 0 { - bail!(res.msg); - } - Ok(()) } diff --git a/clash-verge-rev/src-tauri/src/core/sysopt.rs b/clash-verge-rev/src-tauri/src/core/sysopt.rs index 35ed33a81c..0674d5b45b 100644 --- a/clash-verge-rev/src-tauri/src/core/sysopt.rs +++ b/clash-verge-rev/src-tauri/src/core/sysopt.rs @@ -10,27 +10,15 @@ use std::env::current_exe; use std::sync::Arc; use sysproxy::{Autoproxy, Sysproxy}; use tauri::async_runtime::Mutex as TokioMutex; +use tokio::time::{sleep, Duration}; pub struct Sysopt { - /// current system proxy setting - cur_sysproxy: Arc>>, - - /// record the original system proxy - /// recover it when exit - old_sysproxy: Arc>>, - - /// current auto proxy setting - cur_autoproxy: Arc>>, - - /// record the original auto proxy - /// recover it when exit - old_autoproxy: Arc>>, - + update_sysproxy: Arc>, + reset_sysproxy: Arc>, /// helps to auto launch the app auto_launch: Arc>>, - /// record whether the guard async is running or not - guard_state: Arc>, + guard_state: Arc>, } #[cfg(target_os = "windows")] @@ -42,7 +30,6 @@ static DEFAULT_BYPASS: &str = "127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,localhost,*.local,*.crashlytics.com,"; fn get_bypass() -> String { - // let bypass = DEFAULT_BYPASS.to_string(); let use_default = Config::verge().latest().use_default_bypass.unwrap_or(true); let res = { let verge = Config::verge(); @@ -53,125 +40,35 @@ fn get_bypass() -> String { Some(bypass) => bypass, None => "".to_string(), }; - #[cfg(target_os = "windows")] - let bypass = if custom_bypass.is_empty() { - DEFAULT_BYPASS.to_string() - } else { - if use_default { - format!("{};{}", DEFAULT_BYPASS, custom_bypass) - } else { - custom_bypass - } - }; - #[cfg(not(target_os = "windows"))] - let bypass = if custom_bypass.is_empty() { - DEFAULT_BYPASS.to_string() - } else { - if use_default { - format!("{},{}", DEFAULT_BYPASS, custom_bypass) - } else { - custom_bypass - } - }; - bypass + if custom_bypass.is_empty() { + DEFAULT_BYPASS.to_string() + } else if use_default { + format!("{},{}", DEFAULT_BYPASS, custom_bypass) + } else { + custom_bypass + } } impl Sysopt { pub fn global() -> &'static Sysopt { static SYSOPT: OnceCell = OnceCell::new(); - SYSOPT.get_or_init(|| Sysopt { - cur_sysproxy: Arc::new(Mutex::new(None)), - old_sysproxy: Arc::new(Mutex::new(None)), - cur_autoproxy: Arc::new(Mutex::new(None)), - old_autoproxy: Arc::new(Mutex::new(None)), + update_sysproxy: Arc::new(TokioMutex::new(false)), + reset_sysproxy: Arc::new(TokioMutex::new(false)), auto_launch: Arc::new(Mutex::new(None)), - guard_state: Arc::new(TokioMutex::new(false)), + guard_state: Arc::new(false.into()), }) } - /// init the sysproxy - pub fn init_sysproxy(&self) -> Result<()> { - let port = Config::verge() - .latest() - .verge_mixed_port - .unwrap_or(Config::clash().data().get_mixed_port()); - let pac_port = IVerge::get_singleton_port(); - - let (enable, pac) = { - let verge = Config::verge(); - let verge = verge.latest(); - ( - verge.enable_system_proxy.unwrap_or(false), - verge.proxy_auto_config.unwrap_or(false), - ) - }; - let mut sys = Sysproxy { - enable, - host: String::from("127.0.0.1"), - port, - bypass: get_bypass(), - }; - let mut auto = Autoproxy { - enable, - url: format!("http://127.0.0.1:{pac_port}/commands/pac"), - }; - if pac { - sys.enable = false; - let old = Sysproxy::get_system_proxy().ok(); - sys.set_system_proxy()?; - *self.old_sysproxy.lock() = old; - *self.cur_sysproxy.lock() = Some(sys); - - let old = Autoproxy::get_auto_proxy().ok(); - auto.set_auto_proxy()?; - *self.old_autoproxy.lock() = old; - *self.cur_autoproxy.lock() = Some(auto); - } else { - auto.enable = false; - let old = Autoproxy::get_auto_proxy().ok(); - auto.set_auto_proxy()?; - *self.old_autoproxy.lock() = old; - *self.cur_autoproxy.lock() = Some(auto); - - let old = Sysproxy::get_system_proxy().ok(); - sys.set_system_proxy()?; - *self.old_sysproxy.lock() = old; - *self.cur_sysproxy.lock() = Some(sys); - } - - // run the system proxy guard + pub fn init_guard_sysproxy(&self) -> Result<()> { self.guard_proxy(); Ok(()) } - /// update the system proxy - pub fn update_sysproxy(&self) -> Result<()> { - let mut cur_sysproxy = self.cur_sysproxy.lock(); - let old_sysproxy = self.old_sysproxy.lock(); - let mut cur_autoproxy = self.cur_autoproxy.lock(); - let old_autoproxy = self.old_autoproxy.lock(); - - let (enable, pac) = { - let verge = Config::verge(); - let verge = verge.latest(); - ( - verge.enable_system_proxy.unwrap_or(false), - verge.proxy_auto_config.unwrap_or(false), - ) - }; - if pac && (cur_autoproxy.is_none() || old_autoproxy.is_none()) { - drop(cur_autoproxy); - drop(old_autoproxy); - return self.init_sysproxy(); - } - - if !pac && (cur_sysproxy.is_none() || old_sysproxy.is_none()) { - drop(cur_sysproxy); - drop(old_sysproxy); - return self.init_sysproxy(); - } + /// init the sysproxy + pub async fn update_sysproxy(&self) -> Result<()> { + let _lock = self.update_sysproxy.lock().await; let port = Config::verge() .latest() @@ -179,84 +76,139 @@ impl Sysopt { .unwrap_or(Config::clash().data().get_mixed_port()); let pac_port = IVerge::get_singleton_port(); - let mut sysproxy = cur_sysproxy.take().unwrap(); - sysproxy.bypass = get_bypass(); - sysproxy.port = port; + let (sys_enable, pac_enable) = { + let verge = Config::verge(); + let verge = verge.latest(); + ( + verge.enable_system_proxy.unwrap_or(false), + verge.proxy_auto_config.unwrap_or(false), + ) + }; - let mut autoproxy = cur_autoproxy.take().unwrap(); - autoproxy.url = format!("http://127.0.0.1:{pac_port}/commands/pac"); + #[cfg(not(target_os = "windows"))] + { + let mut sys = Sysproxy { + enable: false, + host: String::from("127.0.0.1"), + port, + bypass: get_bypass(), + }; + let mut auto = Autoproxy { + enable: false, + url: format!("http://127.0.0.1:{pac_port}/commands/pac"), + }; - if pac { - sysproxy.enable = false; - sysproxy.set_system_proxy()?; - *cur_sysproxy = Some(sysproxy); - autoproxy.enable = enable; - autoproxy.set_auto_proxy()?; - *cur_autoproxy = Some(autoproxy); - } else { - autoproxy.enable = false; - autoproxy.set_auto_proxy()?; - *cur_autoproxy = Some(autoproxy); - sysproxy.enable = enable; - sysproxy.set_system_proxy()?; - *cur_sysproxy = Some(sysproxy); + if !sys_enable { + sys.set_system_proxy()?; + auto.set_auto_proxy()?; + return Ok(()); + } + + if pac_enable { + sys.enable = false; + auto.enable = true; + sys.set_system_proxy()?; + auto.set_auto_proxy()?; + return Ok(()); + } + + if sys_enable { + auto.enable = false; + sys.enable = true; + auto.set_auto_proxy()?; + sys.set_system_proxy()?; + return Ok(()); + } + } + #[cfg(target_os = "windows")] + { + if !sys_enable { + return self.reset_sysproxy().await; + } + use crate::core::handle::Handle; + use crate::utils::dirs; + use anyhow::bail; + use tauri_plugin_shell::ShellExt; + + let app_handle = Handle::global().app_handle().unwrap(); + + let binary_path = dirs::service_path()?; + let sysproxy_exe = binary_path.with_file_name("sysproxy.exe"); + if !sysproxy_exe.exists() { + bail!("sysproxy.exe not found"); + } + + let shell = app_handle.shell(); + let output = if pac_enable { + let address = format!("http://{}:{}/commands/pac", "127.0.0.1", pac_port); + let output = shell + .command(sysproxy_exe.as_path().to_str().unwrap()) + .args(["pac", address.as_str()]) + .output() + .await + .unwrap(); + output + } else { + let address = format!("{}:{}", "127.0.0.1", port); + let bypass = get_bypass(); + let output = shell + .command(sysproxy_exe.as_path().to_str().unwrap()) + .args(["global", address.as_str(), bypass.as_ref()]) + .output() + .await + .unwrap(); + output + }; + + if !output.status.success() { + bail!("sysproxy exe run failed"); + } } Ok(()) } /// reset the sysproxy - pub fn reset_sysproxy(&self) -> Result<()> { - let mut cur_sysproxy = self.cur_sysproxy.lock(); - let mut old_sysproxy = self.old_sysproxy.lock(); - let mut cur_autoproxy = self.cur_autoproxy.lock(); - let mut old_autoproxy = self.old_autoproxy.lock(); - - let cur_sysproxy = cur_sysproxy.take(); - let cur_autoproxy = cur_autoproxy.take(); - - if let Some(mut old) = old_sysproxy.take() { - // 如果原代理和当前代理 端口一致,就disable关闭,否则就恢复原代理设置 - // 当前没有设置代理的时候,不确定旧设置是否和当前一致,全关了 - let port_same = cur_sysproxy.map_or(true, |cur| old.port == cur.port); - - if old.enable && port_same { - old.enable = false; - log::info!(target: "app", "reset proxy by disabling the original proxy"); - } else { - log::info!(target: "app", "reset proxy to the original proxy"); - } - - old.set_system_proxy()?; - } else if let Some(mut cur @ Sysproxy { enable: true, .. }) = cur_sysproxy { - // 没有原代理,就按现在的代理设置disable即可 - log::info!(target: "app", "reset proxy by disabling the current proxy"); - cur.enable = false; - cur.set_system_proxy()?; - } else { - log::info!(target: "app", "reset proxy with no action"); + pub async fn reset_sysproxy(&self) -> Result<()> { + let _lock = self.reset_sysproxy.lock().await; + //直接关闭所有代理 + #[cfg(not(target_os = "windows"))] + { + let mut sysproxy: Sysproxy = Sysproxy::get_system_proxy()?; + let mut autoproxy = Autoproxy::get_auto_proxy()?; + sysproxy.enable = false; + autoproxy.enable = false; + autoproxy.set_auto_proxy()?; + sysproxy.set_system_proxy()?; } - if let Some(mut old) = old_autoproxy.take() { - // 如果原代理和当前代理 URL一致,就disable关闭,否则就恢复原代理设置 - // 当前没有设置代理的时候,不确定旧设置是否和当前一致,全关了 - let url_same = cur_autoproxy.map_or(true, |cur| old.url == cur.url); + #[cfg(target_os = "windows")] + { + use crate::core::handle::Handle; + use crate::utils::dirs; + use anyhow::bail; + use tauri_plugin_shell::ShellExt; - if old.enable && url_same { - old.enable = false; - log::info!(target: "app", "reset proxy by disabling the original proxy"); - } else { - log::info!(target: "app", "reset proxy to the original proxy"); + let app_handle = Handle::global().app_handle().unwrap(); + + let binary_path = dirs::service_path()?; + let sysproxy_exe = binary_path.with_file_name("sysproxy.exe"); + + if !sysproxy_exe.exists() { + bail!("sysproxy.exe not found"); } - old.set_auto_proxy()?; - } else if let Some(mut cur @ Autoproxy { enable: true, .. }) = cur_autoproxy { - // 没有原代理,就按现在的代理设置disable即可 - log::info!(target: "app", "reset proxy by disabling the current proxy"); - cur.enable = false; - cur.set_auto_proxy()?; - } else { - log::info!(target: "app", "reset proxy with no action"); + let shell = app_handle.shell(); + let output = shell + .command(sysproxy_exe.as_path().to_str().unwrap()) + .args(["set", "1"]) + .output() + .await + .unwrap(); + + if !output.status.success() { + bail!("sysproxy exe run failed"); + } } Ok(()) @@ -294,14 +246,13 @@ impl Sysopt { })() .unwrap_or(app_path); - // fix #403 #[cfg(target_os = "linux")] let app_path = { use crate::core::handle::Handle; use tauri::Manager; - let handle = Handle::global(); - match handle.app_handle.lock().as_ref() { + let app_handle = Handle::global().app_handle(); + match app_handle { Some(app_handle) => { let appimage = app_handle.env().appimage; appimage @@ -326,10 +277,6 @@ impl Sysopt { pub fn update_launch(&self) -> Result<()> { let auto_launch = self.auto_launch.lock(); - if auto_launch.is_none() { - drop(auto_launch); - return self.init_launch(); - } let enable = { Config::verge().latest().enable_auto_launch }; let enable = enable.unwrap_or(false); let auto_launch = auto_launch.as_ref().unwrap(); @@ -342,22 +289,10 @@ impl Sysopt { Ok(()) } - /// launch a system proxy guard - /// read config from file directly - pub fn guard_proxy(&self) { - use tokio::time::{sleep, Duration}; - - let guard_state = self.guard_state.clone(); + fn guard_proxy(&self) { + let _lock = self.guard_state.lock(); tauri::async_runtime::spawn(async move { - // if it is running, exit - let mut state = guard_state.lock().await; - if *state { - return; - } - *state = true; - drop(state); - // default duration is 10s let mut wait_secs = 10u64; @@ -377,7 +312,7 @@ impl Sysopt { // stop loop if !enable || !guard { - break; + continue; } // update duration @@ -385,6 +320,20 @@ impl Sysopt { log::debug!(target: "app", "try to guard the system proxy"); + let sysproxy = Sysproxy::get_system_proxy(); + let autoproxy = Autoproxy::get_auto_proxy(); + if sysproxy.is_err() || autoproxy.is_err() { + log::error!(target: "app", "failed to get the system proxy"); + continue; + } + + let sysproxy_enable = sysproxy.ok().map(|s| s.enable).unwrap_or(false); + let autoproxy_enable = autoproxy.ok().map(|s| s.enable).unwrap_or(false); + + if sysproxy_enable || autoproxy_enable { + continue; + } + let port = { Config::verge() .latest() @@ -392,27 +341,66 @@ impl Sysopt { .unwrap_or(Config::clash().data().get_mixed_port()) }; let pac_port = IVerge::get_singleton_port(); - if pac { - let autoproxy = Autoproxy { - enable: true, - url: format!("http://127.0.0.1:{pac_port}/commands/pac"), - }; - log_err!(autoproxy.set_auto_proxy()); - } else { - let sysproxy = Sysproxy { - enable: true, - host: "127.0.0.1".into(), - port, - bypass: get_bypass(), - }; + #[cfg(not(target_os = "windows"))] + { + if pac { + let autoproxy = Autoproxy { + enable: true, + url: format!("http://127.0.0.1:{pac_port}/commands/pac"), + }; + log_err!(autoproxy.set_auto_proxy()); + } else { + let sysproxy = Sysproxy { + enable: true, + host: "127.0.0.1".into(), + port, + bypass: get_bypass(), + }; - log_err!(sysproxy.set_system_proxy()); + log_err!(sysproxy.set_system_proxy()); + } } - } - let mut state = guard_state.lock().await; - *state = false; - drop(state); + #[cfg(target_os = "windows")] + { + use crate::core::handle::Handle; + use crate::utils::dirs; + use tauri_plugin_shell::ShellExt; + + let app_handle = Handle::global().app_handle().unwrap(); + + let binary_path = dirs::service_path().unwrap(); + let sysproxy_exe = binary_path.with_file_name("sysproxy.exe"); + if !sysproxy_exe.exists() { + break; + } + + let shell = app_handle.shell(); + let output = if pac { + let address = format!("http://{}:{}/commands/pac", "127.0.0.1", pac_port); + + shell + .command(sysproxy_exe.as_path().to_str().unwrap()) + .args(["pac", address.as_str()]) + .output() + .await + .unwrap() + } else { + let address = format!("{}:{}", "127.0.0.1", port); + let bypass = get_bypass(); + + shell + .command(sysproxy_exe.as_path().to_str().unwrap()) + .args(["global", address.as_str(), bypass.as_ref()]) + .output() + .await + .unwrap() + }; + if !output.status.success() { + break; + } + }; + } }); } } diff --git a/clash-verge-rev/src-tauri/src/core/tray.rs b/clash-verge-rev/src-tauri/src/core/tray.rs index 633babf384..f1602c5658 100644 --- a/clash-verge-rev/src-tauri/src/core/tray.rs +++ b/clash-verge-rev/src-tauri/src/core/tray.rs @@ -8,41 +8,65 @@ use crate::{ }, }; use anyhow::Result; -use tauri::tray::{MouseButton, MouseButtonState, TrayIconEvent}; +use tauri::{ + menu::CheckMenuItem, + tray::{MouseButton, MouseButtonState, TrayIconEvent, TrayIconId}, +}; use tauri::{ menu::{MenuEvent, MenuItem, PredefinedMenuItem, Submenu}, Wry, }; use tauri::{AppHandle, Manager}; + +use super::handle; pub struct Tray {} impl Tray { - pub fn update_systray(app_handle: &AppHandle) -> Result<()> { - let tray = app_handle.tray_by_id("main").unwrap(); - tray.on_tray_icon_event(|tray, event| { + pub fn create_systray() -> Result<()> { + let app_handle = handle::Handle::global().app_handle().unwrap(); + let tray_incon_id = TrayIconId::new("main"); + let tray = app_handle.tray_by_id(&tray_incon_id).unwrap(); + + tray.on_tray_icon_event(|_, event| { let tray_event = { Config::verge().latest().tray_event.clone() }; let tray_event: String = tray_event.unwrap_or("main_window".into()); + + #[cfg(target_os = "macos")] if let TrayIconEvent::Click { - button: MouseButton::Left, - button_state: MouseButtonState::Up, + button: MouseButton::Right, + button_state: MouseButtonState::Down, .. } = event { - let app = tray.app_handle(); match tray_event.as_str() { "system_proxy" => feat::toggle_system_proxy(), "tun_mode" => feat::toggle_tun_mode(), - "main_window" => resolve::create_window(app), + "main_window" => resolve::create_window(), + _ => {} + } + } + + #[cfg(not(target_os = "macos"))] + if let TrayIconEvent::Click { + button: MouseButton::Left, + button_state: MouseButtonState::Down, + .. + } = event + { + match tray_event.as_str() { + "system_proxy" => feat::toggle_system_proxy(), + "tun_mode" => feat::toggle_tun_mode(), + "main_window" => resolve::create_window(), _ => {} } } }); tray.on_menu_event(on_menu_event); - Ok(()) } - pub fn update_part(app_handle: &AppHandle) -> Result<()> { + pub fn update_part() -> Result<()> { + let app_handle = handle::Handle::global().app_handle().unwrap(); let use_zh = { Config::verge().latest().language == Some("zh".into()) }; let version = VERSION.get().unwrap(); let mode = { @@ -66,7 +90,7 @@ impl Tray { let tray = app_handle.tray_by_id("main").unwrap(); let _ = tray.set_menu(Some(create_tray_menu( - app_handle, + &app_handle, Some(mode.as_str()), *system_proxy, *tun_mode, @@ -191,40 +215,113 @@ fn create_tray_menu( let use_zh = { Config::verge().latest().language == Some("zh".into()) }; let version = VERSION.get().unwrap(); - let rule_mode_text = if mode == "rule" { - "✓ 规则模式" - } else { - "规则模式" - }; + let open_window = &MenuItem::with_id( + app_handle, + "open_window", + t!("Dashboard", "打开面板", use_zh), + true, + None::<&str>, + ) + .unwrap(); - let global_mode_text = if mode == "global" { - "✓ 全局模式" - } else { - "全局模式" - }; + let rule_mode = &CheckMenuItem::with_id( + app_handle, + "rule_mode", + t!("Rule Mode", "规则模式", use_zh), + true, + mode == "rule", + None::<&str>, + ) + .unwrap(); - let direct_mode_text = if mode == "direct" { - "✓ 直连模式" - } else { - "直连模式" - }; + let global_mode = &CheckMenuItem::with_id( + app_handle, + "global_mode", + t!("Global Mode", "全局模式", use_zh), + true, + mode == "global", + None::<&str>, + ) + .unwrap(); - let system_proxy_text = if system_proxy_enabled { - "✓ 系统代理" - } else { - "系统代理" - }; + let direct_mode = &CheckMenuItem::with_id( + app_handle, + "direct_mode", + t!("Direct Mode", "直连模式", use_zh), + true, + mode == "direct", + None::<&str>, + ) + .unwrap(); - let tun_mode_text = if tun_mode_enabled { - "✓ Tun 模式" - } else { - "Tun 模式" - }; + let system_proxy = &CheckMenuItem::with_id( + app_handle, + "system_proxy", + t!("System Proxy", "系统代理", use_zh), + true, + system_proxy_enabled, + None::<&str>, + ) + .unwrap(); + + let tun_mode = &CheckMenuItem::with_id( + app_handle, + "tun_mode", + t!("TUN Mode", "Tun模式", use_zh), + true, + tun_mode_enabled, + None::<&str>, + ) + .unwrap(); + + let copy_env = &MenuItem::with_id( + app_handle, + "copy_env", + t!("Copy Env", "复制环境变量", use_zh), + true, + None::<&str>, + ) + .unwrap(); + + let open_app_dir = &MenuItem::with_id( + app_handle, + "open_app_dir", + t!("Conf Dir", "配置目录", use_zh), + true, + None::<&str>, + ) + .unwrap(); + + let open_core_dir = &MenuItem::with_id( + app_handle, + "open_core_dir", + t!("Core Dir", "内核目录", use_zh), + true, + None::<&str>, + ) + .unwrap(); + + let open_logs_dir = &MenuItem::with_id( + app_handle, + "open_logs_dir", + t!("Logs Dir", "日志目录", use_zh), + true, + None::<&str>, + ) + .unwrap(); + let open_dir = &Submenu::with_id_and_items( + app_handle, + "open_dir", + t!("Open Dir", "打开目录", use_zh), + true, + &[open_app_dir, open_core_dir, open_logs_dir], + ) + .unwrap(); let restart_clash = &MenuItem::with_id( app_handle, "restart_clash", - t!("Restart App", "重启 Clash", use_zh), + t!("Restart Clash Core", "重启Clash内核", use_zh), true, None::<&str>, ) @@ -233,7 +330,7 @@ fn create_tray_menu( let restart_app = &MenuItem::with_id( app_handle, "restart_app", - t!("Restart App", "重启应用", use_zh), + t!("Restart App", "重启Verge", use_zh), true, None::<&str>, ) @@ -248,113 +345,44 @@ fn create_tray_menu( ) .unwrap(); + let more = &Submenu::with_id_and_items( + app_handle, + "more", + t!("More", "更多", use_zh), + true, + &[restart_clash, restart_app, app_version], + ) + .unwrap(); + + let quit = &MenuItem::with_id( + app_handle, + "quit", + t!("Quit", "退出", use_zh), + true, + Some("CmdOrControl+Q"), + ) + .unwrap(); + + let separator = &PredefinedMenuItem::separator(app_handle).unwrap(); + let menu = tauri::menu::MenuBuilder::new(app_handle) - .item( - &MenuItem::with_id( - app_handle, - "open_window", - t!("Dashboard", "打开面板", use_zh), - true, - None::<&str>, - ) - .unwrap(), - ) - .item(&PredefinedMenuItem::separator(app_handle).unwrap()) - .item( - &MenuItem::with_id( - app_handle, - "rule_mode", - t!("Rule Mode", rule_mode_text, use_zh), - true, - None::<&str>, - ) - .unwrap(), - ) - .item( - &MenuItem::with_id( - app_handle, - "global_mode", - t!("Global Mode", global_mode_text, use_zh), - true, - None::<&str>, - ) - .unwrap(), - ) - .item( - &MenuItem::with_id( - app_handle, - "direct_mode", - t!("Direct Mode", direct_mode_text, use_zh), - true, - None::<&str>, - ) - .unwrap(), - ) - .item(&PredefinedMenuItem::separator(app_handle).unwrap()) - .item( - &MenuItem::with_id( - app_handle, - "system_proxy", - t!("System Proxy", system_proxy_text, use_zh), - true, - None::<&str>, - ) - .unwrap(), - ) - .item( - &MenuItem::with_id( - app_handle, - "tun_mode", - t!("TUN Mode", tun_mode_text, use_zh), - true, - None::<&str>, - ) - .unwrap(), - ) - .item( - &MenuItem::with_id( - app_handle, - "copy_env", - t!("Copy Env", "复制环境变量", use_zh), - true, - None::<&str>, - ) - .unwrap(), - ) - .item( - &MenuItem::with_id( - app_handle, - "open_dir", - t!("Open Dir", "打开目录", use_zh), - true, - None::<&str>, - ) - .unwrap(), - ) - .item( - &Submenu::with_id_and_items( - app_handle, - "more", - t!("More", "更多", use_zh), - true, - &[restart_clash, restart_app, app_version], - ) - .unwrap(), - ) - .item(&PredefinedMenuItem::separator(app_handle).unwrap()) - .item( - &MenuItem::with_id( - app_handle, - "quit", - t!("Quit", "退出", use_zh), - true, - Some("CmdOrControl+Q"), - ) - .unwrap(), - ) + .items(&[ + open_window, + separator, + rule_mode, + global_mode, + direct_mode, + separator, + system_proxy, + tun_mode, + copy_env, + open_dir, + more, + separator, + quit, + ]) .build() .unwrap(); - Ok(menu) } @@ -365,14 +393,19 @@ fn on_menu_event(app_handle: &AppHandle, event: MenuEvent) { println!("change mode to: {}", mode); feat::change_clash_mode(mode.into()); } - "open_window" => resolve::create_window(app_handle), + "open_window" => resolve::create_window(), "system_proxy" => feat::toggle_system_proxy(), "tun_mode" => feat::toggle_tun_mode(), - "copy_env" => feat::copy_clash_env(app_handle), - "open_dir" => crate::log_err!(cmds::open_app_dir()), + "copy_env" => feat::copy_clash_env(), + "open_app_dir" => crate::log_err!(cmds::open_app_dir()), + "open_core_dir" => crate::log_err!(cmds::open_core_dir()), + "open_logs_dir" => crate::log_err!(cmds::open_logs_dir()), "restart_clash" => feat::restart_clash_core(), "restart_app" => tauri::process::restart(&app_handle.env()), - "quit" => cmds::exit_app(app_handle.clone()), + "quit" => { + println!("quit"); + feat::quit(Some(0)); + } _ => {} } } diff --git a/clash-verge-rev/src-tauri/src/enhance/merge.rs b/clash-verge-rev/src-tauri/src/enhance/merge.rs index dccd65cb1d..0aa81e7e90 100644 --- a/clash-verge-rev/src-tauri/src/enhance/merge.rs +++ b/clash-verge-rev/src-tauri/src/enhance/merge.rs @@ -54,9 +54,7 @@ fn test_merge() -> anyhow::Result<()> { let merge = serde_yaml::from_str::(merge)?; let config = serde_yaml::from_str::(config)?; - let result = serde_yaml::to_string(&use_merge(merge, config))?; - - println!("{result}"); + let _ = serde_yaml::to_string(&use_merge(merge, config))?; Ok(()) } diff --git a/clash-verge-rev/src-tauri/src/enhance/mod.rs b/clash-verge-rev/src-tauri/src/enhance/mod.rs index 11355e8740..6da1b537b2 100644 --- a/clash-verge-rev/src-tauri/src/enhance/mod.rs +++ b/clash-verge-rev/src-tauri/src/enhance/mod.rs @@ -259,7 +259,9 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { }); } - config = use_tun(config, enable_tun).await; + if enable_tun { + config = use_tun(config).await; + } config = use_sort(config); let mut exists_set = HashSet::new(); diff --git a/clash-verge-rev/src-tauri/src/enhance/script.rs b/clash-verge-rev/src-tauri/src/enhance/script.rs index e2465097e7..22ad0cef64 100644 --- a/clash-verge-rev/src-tauri/src/enhance/script.rs +++ b/clash-verge-rev/src-tauri/src/enhance/script.rs @@ -103,9 +103,7 @@ fn test_script() { let config = serde_yaml::from_str(config).unwrap(); let (config, results) = use_script(script.into(), config, "".to_string()).unwrap(); - let config_str = serde_yaml::to_string(&config).unwrap(); - - println!("{config_str}"); + let _ = serde_yaml::to_string(&config).unwrap(); dbg!(results); } diff --git a/clash-verge-rev/src-tauri/src/enhance/seq.rs b/clash-verge-rev/src-tauri/src/enhance/seq.rs index c253b1e6ff..81e722b571 100644 --- a/clash-verge-rev/src-tauri/src/enhance/seq.rs +++ b/clash-verge-rev/src-tauri/src/enhance/seq.rs @@ -12,7 +12,7 @@ pub fn use_seq(seq_map: SeqMap, config: Mapping, name: &str) -> Mapping { let append = seq_map.append; let delete = seq_map.delete; - let origin_seq = config.get(&name).map_or(Sequence::default(), |val| { + let origin_seq = config.get(name).map_or(Sequence::default(), |val| { val.as_sequence().unwrap_or(&Sequence::default()).clone() }); let mut seq = origin_seq.clone(); @@ -23,7 +23,7 @@ pub fn use_seq(seq_map: SeqMap, config: Mapping, name: &str) -> Mapping { if let Some(name) = if item.is_string() { Some(item) } else { - item.get("name").map(|y| y.clone()) + item.get("name").cloned() } { delete_names.push(name.clone()); } @@ -34,7 +34,7 @@ pub fn use_seq(seq_map: SeqMap, config: Mapping, name: &str) -> Mapping { } else { x.get("name") } { - !delete_names.contains(&x_name) + !delete_names.contains(x_name) } else { true } @@ -51,5 +51,5 @@ pub fn use_seq(seq_map: SeqMap, config: Mapping, name: &str) -> Mapping { let mut config = config.clone(); config.insert(Value::from(name), Value::from(seq)); - return config; + config } diff --git a/clash-verge-rev/src-tauri/src/enhance/tun.rs b/clash-verge-rev/src-tauri/src/enhance/tun.rs index 2e9de2595b..b532f91fab 100644 --- a/clash-verge-rev/src-tauri/src/enhance/tun.rs +++ b/clash-verge-rev/src-tauri/src/enhance/tun.rs @@ -1,4 +1,3 @@ -use crate::{core::service, log_err}; use serde_yaml::{Mapping, Value}; macro_rules! revise { @@ -9,6 +8,7 @@ macro_rules! revise { } // if key not exists then append value +#[allow(unused_macros)] macro_rules! append { ($map: expr, $key: expr, $val: expr) => { let ret_key = Value::String($key.into()); @@ -18,61 +18,13 @@ macro_rules! append { }; } -pub async fn use_tun(mut config: Mapping, enable: bool) -> Mapping { +pub async fn use_tun(mut config: Mapping) -> Mapping { let tun_key = Value::from("tun"); let tun_val = config.get(&tun_key); - - if !enable && tun_val.is_none() { - return config; - } - let mut tun_val = tun_val.map_or(Mapping::new(), |val| { val.as_mapping().cloned().unwrap_or(Mapping::new()) }); - - revise!(tun_val, "enable", enable); - + revise!(tun_val, "enable", true); revise!(config, "tun", tun_val); - - if enable { - log_err!(service::set_dns_by_service().await); - use_dns_for_tun(config) - } else { - log_err!(service::unset_dns_by_service().await); - config - } -} - -fn use_dns_for_tun(mut config: Mapping) -> Mapping { - let dns_key = Value::from("dns"); - let dns_val = config.get(&dns_key); - - let mut dns_val = dns_val.map_or(Mapping::new(), |val| { - val.as_mapping().cloned().unwrap_or(Mapping::new()) - }); - - // 开启tun将同时开启dns - revise!(dns_val, "enable", true); - - append!(dns_val, "enhanced-mode", "fake-ip"); - append!(dns_val, "fake-ip-range", "198.18.0.1/16"); - append!( - dns_val, - "nameserver", - vec!["114.114.114.114", "223.5.5.5", "8.8.8.8"] - ); - append!(dns_val, "fallback", vec![] as Vec<&str>); - - #[cfg(target_os = "windows")] - append!( - dns_val, - "fake-ip-filter", - vec![ - "dns.msftncsi.com", - "www.msftncsi.com", - "www.msftconnecttest.com" - ] - ); - revise!(config, "dns", dns_val); config } diff --git a/clash-verge-rev/src-tauri/src/feat.rs b/clash-verge-rev/src-tauri/src/feat.rs index 0260e5d062..32023ee735 100644 --- a/clash-verge-rev/src-tauri/src/feat.rs +++ b/clash-verge-rev/src-tauri/src/feat.rs @@ -10,28 +10,23 @@ use crate::log_err; use crate::utils::resolve; use anyhow::{bail, Result}; use serde_yaml::{Mapping, Value}; -use tauri::{AppHandle, Manager}; use tauri_plugin_clipboard_manager::ClipboardExt; // 打开面板 pub fn open_or_close_dashboard() { - let handle = handle::Handle::global(); - let app_handle = handle.app_handle.lock(); - if let Some(app_handle) = app_handle.as_ref() { - if let Some(window) = app_handle.get_webview_window("main") { - if let Ok(true) = window.is_focused() { - let _ = window.close(); - return; - } + if let Some(window) = handle::Handle::global().get_window() { + if let Ok(true) = window.is_focused() { + let _ = window.minimize(); + return; } - resolve::create_window(app_handle); } + resolve::create_window(); } // 重启clash pub fn restart_clash_core() { tauri::async_runtime::spawn(async { - match CoreManager::global().run_core().await { + match CoreManager::global().restart_core().await { Ok(_) => { handle::Handle::refresh_clash(); handle::Handle::notice_message("set_config::ok", "ok"); @@ -103,6 +98,12 @@ pub fn toggle_tun_mode() { }); } +pub fn quit(code: Option) { + let app_handle = handle::Handle::global().app_handle().unwrap(); + resolve::resolve_reset(); + app_handle.exit(code.unwrap_or(0)); +} + /// 修改clash的订阅 pub async fn patch_clash(patch: Mapping) -> Result<()> { Config::clash().draft().patch_config(patch.clone()); @@ -111,7 +112,7 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> { // 激活订阅 if patch.get("secret").is_some() || patch.get("external-controller").is_some() { Config::generate().await?; - CoreManager::global().run_core().await?; + CoreManager::global().restart_core().await?; handle::Handle::refresh_clash(); } @@ -140,6 +141,7 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> { /// 一般都是一个个的修改 pub async fn patch_verge(patch: IVerge) -> Result<()> { Config::verge().draft().patch_config(patch.clone()); + let tun_mode = patch.enable_tun_mode; let auto_launch = patch.enable_auto_launch; let system_proxy = patch.enable_system_proxy; @@ -150,6 +152,8 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { let mixed_port = patch.verge_mixed_port; #[cfg(target_os = "macos")] let tray_icon = patch.tray_icon; + #[cfg(not(target_os = "macos"))] + let tray_icon: Option = None; let common_tray_icon = patch.common_tray_icon; let sysproxy_tray_icon = patch.sysproxy_tray_icon; let tun_tray_icon = patch.tun_tray_icon; @@ -165,34 +169,26 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { let socks_port = patch.verge_socks_port; let http_enabled = patch.verge_http_enabled; let http_port = patch.verge_port; - let res = { - let service_mode = patch.enable_service_mode; - let mut generated = false; - if service_mode.is_some() { - log::debug!(target: "app", "change service mode to {}", service_mode.unwrap()); - if !generated { - Config::generate().await?; - CoreManager::global().run_core().await?; - generated = true; - } - } else if tun_mode.is_some() { - update_core_config().await?; + + let res: std::result::Result<(), anyhow::Error> = { + let mut should_restart_core = false; + let mut should_update_clash_config = false; + let mut should_update_launch = false; + let mut should_update_sysproxy = false; + let mut should_update_systray_part = false; + + if tun_mode.is_some() { + should_update_clash_config = true; } + #[cfg(not(target_os = "windows"))] if redir_enabled.is_some() || redir_port.is_some() { - if !generated { - Config::generate().await?; - CoreManager::global().run_core().await?; - generated = true; - } + should_restart_core = true; } + #[cfg(target_os = "linux")] if tproxy_enabled.is_some() || tproxy_port.is_some() { - if !generated { - Config::generate().await?; - CoreManager::global().run_core().await?; - generated = true; - } + should_restart_core = true; } if socks_enabled.is_some() || http_enabled.is_some() @@ -200,13 +196,10 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { || http_port.is_some() || mixed_port.is_some() { - if !generated { - Config::generate().await?; - CoreManager::global().run_core().await?; - } + should_restart_core = true; } if auto_launch.is_some() { - sysopt::Sysopt::global().update_launch()?; + should_update_launch = true; } if system_proxy.is_some() || proxy_bypass.is_some() @@ -214,30 +207,39 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { || pac.is_some() || pac_content.is_some() { - sysopt::Sysopt::global().update_sysproxy()?; - sysopt::Sysopt::global().guard_proxy(); + should_update_sysproxy = true; } - if let Some(true) = patch.enable_proxy_guard { - sysopt::Sysopt::global().guard_proxy(); + if language.is_some() + || system_proxy.is_some() + || tun_mode.is_some() + || common_tray_icon.is_some() + || sysproxy_tray_icon.is_some() + || tun_tray_icon.is_some() + || tray_icon.is_some() + { + should_update_systray_part = true; + } + if should_restart_core { + Config::generate().await?; + CoreManager::global().restart_core().await?; + } + if should_update_clash_config { + update_core_config(false).await?; + } + if should_update_launch { + sysopt::Sysopt::global().update_launch()?; + } + + if should_update_sysproxy { + sysopt::Sysopt::global().update_sysproxy().await?; } if let Some(hotkeys) = patch.hotkeys { hotkey::Hotkey::global().update(hotkeys)?; } - if language.is_some() { - handle::Handle::update_systray()?; - } else if system_proxy.is_some() - || tun_mode.is_some() - || common_tray_icon.is_some() - || sysproxy_tray_icon.is_some() - || tun_tray_icon.is_some() - { - handle::Handle::update_systray_part()?; - } - #[cfg(target_os = "macos")] - if tray_icon.is_some() { + if should_update_systray_part { handle::Handle::update_systray_part()?; } @@ -247,6 +249,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { Ok(()) => { Config::verge().apply(); Config::verge().data().save_file()?; + Ok(()) } Err(err) => { @@ -288,29 +291,34 @@ pub async fn update_profile(uid: String, option: Option) -> Result<() }; if should_update { - update_core_config().await?; + update_core_config(true).await?; } Ok(()) } /// 更新订阅 -async fn update_core_config() -> Result<()> { +async fn update_core_config(notice: bool) -> Result<()> { match CoreManager::global().update_config().await { Ok(_) => { handle::Handle::refresh_clash(); - handle::Handle::notice_message("set_config::ok", "ok"); + if notice { + handle::Handle::notice_message("set_config::ok", "ok"); + } Ok(()) } Err(err) => { - handle::Handle::notice_message("set_config::error", format!("{err}")); + if notice { + handle::Handle::notice_message("set_config::error", format!("{err}")); + } Err(err) } } } /// copy env variable -pub fn copy_clash_env(app_handle: &AppHandle) { +pub fn copy_clash_env() { + let app_handle = handle::Handle::global().app_handle().unwrap(); let port = { Config::verge().latest().verge_mixed_port.unwrap_or(7897) }; let http_proxy = format!("http://127.0.0.1:{}", port); let socks5_proxy = format!("socks5://127.0.0.1:{}", port); diff --git a/clash-verge-rev/src-tauri/src/lib.rs b/clash-verge-rev/src-tauri/src/lib.rs new file mode 100644 index 0000000000..d73b20fabd --- /dev/null +++ b/clash-verge-rev/src-tauri/src/lib.rs @@ -0,0 +1,179 @@ +mod cmds; +mod config; +mod core; +mod enhance; +mod feat; +mod utils; + +use crate::core::hotkey; +use crate::utils::{resolve, resolve::resolve_scheme, server}; +#[cfg(target_os = "macos")] +use tauri::Listener; + +pub fn run() { + // 单例检测 + let app_exists: bool = tauri::async_runtime::block_on(async move { + if server::check_singleton().await.is_err() { + println!("app exists"); + true + } else { + false + } + }); + if app_exists { + return; + } + + #[cfg(target_os = "linux")] + std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); + + #[cfg(debug_assertions)] + let devtools = tauri_plugin_devtools::init(); + + #[allow(unused_mut)] + let mut builder = tauri::Builder::default() + .plugin(tauri_plugin_updater::Builder::new().build()) + .plugin(tauri_plugin_clipboard_manager::init()) + .plugin(tauri_plugin_process::init()) + .plugin(tauri_plugin_global_shortcut::Builder::new().build()) + .plugin(tauri_plugin_notification::init()) + .plugin(tauri_plugin_fs::init()) + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_deep_link::init()) + .setup(|app| { + #[cfg(target_os = "linux")] + { + use tauri_plugin_deep_link::DeepLinkExt; + app.deep_link().register_all()?; + } + #[cfg(target_os = "macos")] + { + app.listen("deep-link://new-url", |event| { + tauri::async_runtime::spawn(async move { + let payload = event.payload(); + log_err!(resolve_scheme(payload.to_owned()).await); + }); + }); + } + tauri::async_runtime::block_on(async move { + resolve::resolve_setup(app).await; + + #[cfg(not(target_os = "macos"))] + { + let argvs: Vec = std::env::args().collect(); + if argvs.len() > 1 { + log_err!(resolve_scheme(argvs[1].to_owned()).await); + } + } + }); + + Ok(()) + }) + .invoke_handler(tauri::generate_handler![ + // common + cmds::get_sys_proxy, + cmds::get_auto_proxy, + cmds::open_app_dir, + cmds::open_logs_dir, + cmds::open_web_url, + cmds::open_core_dir, + cmds::get_portable_flag, + cmds::get_network_interfaces, + // cmds::kill_sidecar, + cmds::restart_sidecar, + // clash + cmds::get_clash_info, + cmds::get_clash_logs, + cmds::patch_clash_config, + cmds::change_clash_core, + cmds::get_runtime_config, + cmds::get_runtime_yaml, + cmds::get_runtime_exists, + cmds::get_runtime_logs, + cmds::uwp::invoke_uwp_tool, + cmds::copy_clash_env, + // verge + cmds::get_verge_config, + cmds::patch_verge_config, + cmds::test_delay, + cmds::get_app_dir, + cmds::copy_icon_file, + cmds::download_icon_cache, + cmds::open_devtools, + cmds::exit_app, + cmds::get_network_interfaces_info, + // cmds::update_hotkeys, + // profile + cmds::get_profiles, + cmds::enhance_profiles, + cmds::patch_profiles_config, + cmds::view_profile, + cmds::patch_profile, + cmds::create_profile, + cmds::import_profile, + cmds::reorder_profile, + cmds::update_profile, + cmds::delete_profile, + cmds::read_profile_file, + cmds::save_profile_file, + // service mode + cmds::service::check_service, + // clash api + cmds::clash_api_get_proxy_delay + ]); + + #[cfg(debug_assertions)] + { + builder = builder.plugin(devtools); + } + + let app = builder + .build(tauri::generate_context!()) + .expect("error while running tauri application"); + + app.run(|_, e| match e { + tauri::RunEvent::ExitRequested { api, code, .. } => { + if code.is_none() { + api.prevent_exit(); + } + } + tauri::RunEvent::WindowEvent { label, event, .. } => { + if label == "main" { + match event { + tauri::WindowEvent::CloseRequested { .. } => { + println!("closing window..."); + let _ = resolve::save_window_size_position(true); + } + tauri::WindowEvent::Moved(_) | tauri::WindowEvent::Resized(_) => { + let _ = resolve::save_window_size_position(false); + } + tauri::WindowEvent::Focused(true) => { + #[cfg(target_os = "macos")] + { + log_err!(hotkey::Hotkey::global().register("CMD+Q", "quit")); + } + + #[cfg(not(target_os = "macos"))] + { + log_err!(hotkey::Hotkey::global().register("Control+Q", "quit")); + }; + } + tauri::WindowEvent::Destroyed => { + #[cfg(target_os = "macos")] + { + log_err!(hotkey::Hotkey::global().unregister("CMD+Q")); + } + + #[cfg(not(target_os = "macos"))] + { + log_err!(hotkey::Hotkey::global().unregister("Control+Q")); + }; + } + _ => {} + } + } + } + _ => {} + }); +} diff --git a/clash-verge-rev/src-tauri/src/main.rs b/clash-verge-rev/src-tauri/src/main.rs old mode 100644 new mode 100755 index fe0fb9c9c2..293b1b22a0 --- a/clash-verge-rev/src-tauri/src/main.rs +++ b/clash-verge-rev/src-tauri/src/main.rs @@ -1,139 +1,4 @@ -#![cfg_attr( - all(not(debug_assertions), target_os = "windows"), - windows_subsystem = "windows" -)] - -mod cmds; -mod config; -mod core; -mod enhance; -mod feat; -mod utils; - -use crate::utils::{resolve, server}; - -fn main() -> std::io::Result<()> { - // 单例检测 - let app_exists: bool = tauri::async_runtime::block_on(async move { - if server::check_singleton().await.is_err() { - println!("app exists"); - true - } else { - false - } - }); - if app_exists { - return Ok(()); - } - - #[cfg(target_os = "linux")] - std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); - - #[cfg(debug_assertions)] - let devtools = tauri_plugin_devtools::init(); - - #[allow(unused_mut)] - let mut builder = tauri::Builder::default() - .plugin(tauri_plugin_updater::Builder::new().build()) - .plugin(tauri_plugin_clipboard_manager::init()) - .plugin(tauri_plugin_process::init()) - .plugin(tauri_plugin_global_shortcut::Builder::new().build()) - .plugin(tauri_plugin_notification::init()) - .plugin(tauri_plugin_fs::init()) - .plugin(tauri_plugin_dialog::init()) - .plugin(tauri_plugin_shell::init()) - .setup(|app| { - tauri::async_runtime::block_on(async move { - resolve::resolve_setup(app).await; - }); - Ok(()) - }) - .invoke_handler(tauri::generate_handler![ - // common - cmds::get_sys_proxy, - cmds::get_auto_proxy, - cmds::open_app_dir, - cmds::open_logs_dir, - cmds::open_web_url, - cmds::open_core_dir, - cmds::get_portable_flag, - cmds::get_network_interfaces, - // cmds::kill_sidecar, - cmds::restart_sidecar, - // clash - cmds::get_clash_info, - cmds::get_clash_logs, - cmds::patch_clash_config, - cmds::change_clash_core, - cmds::get_runtime_config, - cmds::get_runtime_yaml, - cmds::get_runtime_exists, - cmds::get_runtime_logs, - cmds::uwp::invoke_uwp_tool, - cmds::copy_clash_env, - // verge - cmds::get_verge_config, - cmds::patch_verge_config, - cmds::test_delay, - cmds::get_app_dir, - cmds::copy_icon_file, - cmds::download_icon_cache, - cmds::open_devtools, - cmds::exit_app, - cmds::get_network_interfaces_info, - // cmds::update_hotkeys, - // profile - cmds::get_profiles, - cmds::enhance_profiles, - cmds::patch_profiles_config, - cmds::view_profile, - cmds::patch_profile, - cmds::create_profile, - cmds::import_profile, - cmds::reorder_profile, - cmds::update_profile, - cmds::delete_profile, - cmds::read_profile_file, - cmds::save_profile_file, - // service mode - cmds::service::check_service, - cmds::service::install_service, - cmds::service::uninstall_service, - // clash api - cmds::clash_api_get_proxy_delay - ]); - - #[cfg(debug_assertions)] - { - builder = builder.plugin(devtools); - } - - let app = builder - .build(tauri::generate_context!()) - .expect("error while running tauri application"); - - app.run(|app_handle, e| match e { - tauri::RunEvent::ExitRequested { api, .. } => { - api.prevent_exit(); - } - tauri::RunEvent::WindowEvent { label, event, .. } => { - if label == "main" { - match event { - tauri::WindowEvent::Destroyed => { - let _ = resolve::save_window_size_position(app_handle, true); - } - tauri::WindowEvent::CloseRequested { .. } => { - let _ = resolve::save_window_size_position(app_handle, true); - } - tauri::WindowEvent::Moved(_) | tauri::WindowEvent::Resized(_) => { - let _ = resolve::save_window_size_position(app_handle, false); - } - _ => {} - } - } - } - _ => {} - }); - - Ok(()) +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +fn main() { + app_lib::run(); } diff --git a/clash-verge-rev/src-tauri/src/utils/dirs.rs b/clash-verge-rev/src-tauri/src/utils/dirs.rs index 227e126181..cf0f94420d 100644 --- a/clash-verge-rev/src-tauri/src/utils/dirs.rs +++ b/clash-verge-rev/src-tauri/src/utils/dirs.rs @@ -44,40 +44,27 @@ pub fn app_home_dir() -> Result { .ok_or(anyhow::anyhow!("failed to get the portable app dir"))?; return Ok(PathBuf::from(app_dir).join(".config").join(APP_ID)); } + let app_handle = handle::Handle::global().app_handle().unwrap(); - let handle = handle::Handle::global(); - let app_handle = handle.app_handle.lock(); - - if let Some(app_handle) = app_handle.as_ref() { - match app_handle.path().data_dir() { - Ok(dir) => { - return Ok(dir.join(APP_ID)); - } - Err(e) => { - log::error!("Failed to get the app home directory: {}", e); - return Err(anyhow::anyhow!("Failed to get the app homedirectory")); - } + match app_handle.path().data_dir() { + Ok(dir) => Ok(dir.join(APP_ID)), + Err(e) => { + log::error!(target:"app", "Failed to get the app home directory: {}", e); + Err(anyhow::anyhow!("Failed to get the app homedirectory")) } } - Err(anyhow::anyhow!("failed to get the app home dir")) } /// get the resources dir pub fn app_resources_dir() -> Result { - let handle = handle::Handle::global(); - let app_handle = handle.app_handle.lock(); - if let Some(app_handle) = app_handle.as_ref() { - match app_handle.path().resource_dir() { - Ok(dir) => { - return Ok(dir.join("resources")); - } - Err(e) => { - log::error!("Failed to get the resource directory: {}", e); - return Err(anyhow::anyhow!("Failed to get the resource directory")); - } - }; - }; - Err(anyhow::anyhow!("failed to get the resource dir")) + let app_handle = handle::Handle::global().app_handle().unwrap(); + match app_handle.path().resource_dir() { + Ok(dir) => Ok(dir.join("resources")), + Err(e) => { + log::error!(target:"app", "Failed to get the resource directory: {}", e); + Err(anyhow::anyhow!("Failed to get the resource directory")) + } + } } /// profiles dir @@ -102,11 +89,7 @@ pub fn profiles_path() -> Result { Ok(app_home_dir()?.join(PROFILE_YAML)) } -pub fn clash_pid_path() -> Result { - Ok(app_home_dir()?.join("clash.pid")) -} - -#[cfg(not(target_os = "windows"))] +#[cfg(target_os = "macos")] pub fn service_path() -> Result { Ok(app_resources_dir()?.join("clash-verge-service")) } diff --git a/clash-verge-rev/src-tauri/src/utils/error.rs b/clash-verge-rev/src-tauri/src/utils/error.rs new file mode 100644 index 0000000000..d661b6099c --- /dev/null +++ b/clash-verge-rev/src-tauri/src/utils/error.rs @@ -0,0 +1,40 @@ +use crate::log_err; +use anyhow; +use std::{ + backtrace::{Backtrace, BacktraceStatus}, + thread, +}; + +pub fn redirect_panic_to_log() { + std::panic::set_hook(Box::new(move |panic_info| { + let thread = thread::current(); + let thread_name = thread.name().unwrap_or(""); + let payload = panic_info.payload(); + + let payload = if let Some(s) = payload.downcast_ref::<&str>() { + &**s + } else if let Some(s) = payload.downcast_ref::() { + s + } else { + &format!("{:?}", payload) + }; + + let location = panic_info + .location() + .map(|l| l.to_string()) + .unwrap_or("unknown location".to_string()); + + let backtrace = Backtrace::capture(); + let backtrace = if backtrace.status() == BacktraceStatus::Captured { + &format!("stack backtrace:\n{}", backtrace) + } else { + "note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace" + }; + + let err: Result<(), anyhow::Error> = Err(anyhow::anyhow!(format!( + "thread '{}' panicked at {}:\n{}\n{}", + thread_name, location, payload, backtrace + ))); + log_err!(err); + })); +} diff --git a/clash-verge-rev/src-tauri/src/utils/help.rs b/clash-verge-rev/src-tauri/src/utils/help.rs index 3583540a63..35279187cf 100644 --- a/clash-verge-rev/src-tauri/src/utils/help.rs +++ b/clash-verge-rev/src-tauri/src/utils/help.rs @@ -105,6 +105,26 @@ pub fn open_file(app: tauri::AppHandle, path: PathBuf) -> Result<()> { Ok(()) } +#[cfg(target_os = "linux")] +pub fn linux_elevator() -> String { + use std::process::Command; + match Command::new("which").arg("pkexec").output() { + Ok(output) => { + if !output.stdout.is_empty() { + // Convert the output to a string slice + if let Ok(path) = std::str::from_utf8(&output.stdout) { + path.trim().to_string() + } else { + "sudo".to_string() + } + } else { + "sudo".to_string() + } + } + Err(_) => "sudo".to_string(), + } +} + #[macro_export] macro_rules! error { ($result: expr) => { diff --git a/clash-verge-rev/src-tauri/src/utils/init.rs b/clash-verge-rev/src-tauri/src/utils/init.rs index 621450a0c9..609012af4e 100644 --- a/clash-verge-rev/src-tauri/src/utils/init.rs +++ b/clash-verge-rev/src-tauri/src/utils/init.rs @@ -1,4 +1,5 @@ use crate::config::*; +use crate::core::handle; use crate::utils::{dirs, help}; use anyhow::Result; use chrono::{Local, TimeZone}; @@ -10,7 +11,6 @@ use log4rs::encode::pattern::PatternEncoder; use std::fs::{self, DirEntry}; use std::path::PathBuf; use std::str::FromStr; -use tauri::AppHandle; use tauri_plugin_shell::ShellExt; /// initialize this instance's log file @@ -44,21 +44,9 @@ fn init_log() -> Result<()> { let log_more = log_level == LevelFilter::Trace || log_level == LevelFilter::Debug; - #[cfg(feature = "verge-dev")] - { - logger_builder = logger_builder.appenders(["file", "stdout"]); - if log_more { - root_builder = root_builder.appenders(["file", "stdout"]); - } else { - root_builder = root_builder.appenders(["stdout"]); - } - } - #[cfg(not(feature = "verge-dev"))] - { - logger_builder = logger_builder.appenders(["file"]); - if log_more { - root_builder = root_builder.appenders(["file"]); - } + logger_builder = logger_builder.appenders(["file"]); + if log_more { + root_builder = root_builder.appenders(["file"]); } let (config, _) = log4rs::config::Config::builder() @@ -207,8 +195,10 @@ pub fn init_resources() -> Result<()> { #[cfg(target_os = "windows")] let file_list = ["Country.mmdb", "geoip.dat", "geosite.dat"]; - #[cfg(not(target_os = "windows"))] + #[cfg(target_os = "macos")] let file_list = ["Country.mmdb", "geoip.dat", "geosite.dat"]; + #[cfg(target_os = "linux")] + let file_list: [&str; 0] = []; // copy the resource file // if the source file is newer than the destination file, copy it over @@ -216,12 +206,13 @@ pub fn init_resources() -> Result<()> { let src_path = res_dir.join(file); let dest_path = app_dir.join(file); let test_dest_path = test_dir.join(file); + log::info!(target: "app", "src_path: {src_path:?}, dest_path: {dest_path:?}"); let handle_copy = |dest: &PathBuf| { match fs::copy(&src_path, dest) { Ok(_) => log::debug!(target: "app", "resources copied '{file}'"), Err(err) => { - log::error!(target: "app", "failed to copy resources '{file}', {err}") + log::error!(target: "app", "failed to copy resources '{file}' to '{dest:?}', {err}") } }; }; @@ -297,7 +288,9 @@ pub fn init_scheme() -> Result<()> { Ok(()) } -pub async fn startup_script(app_handle: &AppHandle) -> Result<()> { +pub async fn startup_script() -> Result<()> { + let app_handle = handle::Handle::global().app_handle().unwrap(); + let script_path = { let verge = Config::verge(); let verge = verge.latest(); @@ -330,7 +323,7 @@ pub async fn startup_script(app_handle: &AppHandle) -> Result<()> { app_handle .shell() .command(shell_type) - .current_dir(working_dir.to_path_buf()) + .current_dir(working_dir) .args(&[script_path]) .output() .await?; diff --git a/clash-verge-rev/src-tauri/src/utils/mod.rs b/clash-verge-rev/src-tauri/src/utils/mod.rs index 28eacc3bb3..b5ee04e7fc 100644 --- a/clash-verge-rev/src-tauri/src/utils/mod.rs +++ b/clash-verge-rev/src-tauri/src/utils/mod.rs @@ -1,4 +1,5 @@ pub mod dirs; +pub mod error; pub mod help; pub mod init; pub mod resolve; diff --git a/clash-verge-rev/src-tauri/src/utils/resolve.rs b/clash-verge-rev/src-tauri/src/utils/resolve.rs index 079004e6ea..28b6adc92d 100644 --- a/clash-verge-rev/src-tauri/src/utils/resolve.rs +++ b/clash-verge-rev/src-tauri/src/utils/resolve.rs @@ -1,12 +1,15 @@ -use crate::cmds::import_profile; use crate::config::IVerge; -use crate::{config::Config, core::*, utils::init, utils::server}; -use crate::{log_err, trace_err}; -use anyhow::Result; +use crate::utils::error; +use crate::{config::Config, config::PrfItem, core::*, utils::init, utils::server}; +use crate::{log_err, trace_err, wrap_err}; +use anyhow::{bail, Result}; use once_cell::sync::OnceCell; +use percent_encoding::percent_decode_str; use serde_yaml::Mapping; use std::net::TcpListener; -use tauri::{App, AppHandle, Manager}; +use tauri::{App, Manager}; + +use url::Url; //#[cfg(not(target_os = "linux"))] // use window_shadows::set_shadow; use tauri_plugin_notification::NotificationExt; @@ -32,90 +35,66 @@ pub fn find_unused_port() -> Result { /// handle something when start app pub async fn resolve_setup(app: &mut App) { + error::redirect_panic_to_log(); #[cfg(target_os = "macos")] app.set_activation_policy(tauri::ActivationPolicy::Accessory); let version = app.package_info().version.to_string(); + handle::Handle::global().init(app.app_handle()); VERSION.get_or_init(|| version.clone()); + log_err!(init::init_config()); log_err!(init::init_resources()); log_err!(init::init_scheme()); - log_err!(init::startup_script(app.app_handle()).await); + log_err!(init::startup_script().await); // 处理随机端口 - let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false); - - let mut port = Config::verge() - .latest() - .verge_mixed_port - .unwrap_or(Config::clash().data().get_mixed_port()); - - if enable_random_port { - port = find_unused_port().unwrap_or( - Config::verge() - .latest() - .verge_mixed_port - .unwrap_or(Config::clash().data().get_mixed_port()), - ); - } - - Config::verge().data().patch_config(IVerge { - verge_mixed_port: Some(port), - ..IVerge::default() - }); - let _ = Config::verge().data().save_file(); - let mut mapping = Mapping::new(); - mapping.insert("mixed-port".into(), port.into()); - Config::clash().data().patch_config(mapping); - let _ = Config::clash().data().save_config(); - + log_err!(resolve_random_port_config()); // 启动核心 - log::trace!("init config"); - + log::trace!(target:"app", "init config"); log_err!(Config::init_config().await); - log::trace!("launch core"); - log_err!(CoreManager::global().init(app.app_handle())); + if service::check_service().await.is_err() { + log_err!(service::reinstall_service().await); + std::thread::sleep(std::time::Duration::from_millis(1000)); + } + + log::trace!(target: "app", "launch core"); + log_err!(CoreManager::global().init().await); // setup a simple http server for singleton - log::trace!("launch embed server"); - server::embed_server(app.app_handle()); + log::trace!(target: "app", "launch embed server"); + server::embed_server(); - log::trace!("init system tray"); - log_err!(tray::Tray::update_systray(&app.app_handle())); + log::trace!(target: "app", "init system tray"); + log_err!(tray::Tray::create_systray()); let silent_start = { Config::verge().data().enable_silent_start }; if !silent_start.unwrap_or(false) { - create_window(&app.app_handle()); + create_window(); } log_err!(sysopt::Sysopt::global().init_launch()); - log_err!(sysopt::Sysopt::global().init_sysproxy()); + log_err!(sysopt::Sysopt::global().update_sysproxy().await); + log_err!(sysopt::Sysopt::global().init_guard_sysproxy()); log_err!(handle::Handle::update_systray_part()); - log_err!(hotkey::Hotkey::global().init(app.app_handle())); + log_err!(hotkey::Hotkey::global().init()); log_err!(timer::Timer::global().init()); - - let argvs: Vec = std::env::args().collect(); - if argvs.len() > 1 { - let param = argvs[1].as_str(); - if param.starts_with("clash:") { - log_err!(resolve_scheme(argvs[1].to_owned()).await); - } - } } /// reset system proxy pub fn resolve_reset() { - log_err!(sysopt::Sysopt::global().reset_sysproxy()); tauri::async_runtime::block_on(async move { + log_err!(sysopt::Sysopt::global().reset_sysproxy().await); log_err!(CoreManager::global().stop_core().await); - log_err!(service::unset_dns_by_service().await); }); } /// create main window -pub fn create_window(app_handle: &AppHandle) { - if let Some(window) = app_handle.get_webview_window("main") { +pub fn create_window() { + let app_handle = handle::Handle::global().app_handle().unwrap(); + + if let Some(window) = handle::Handle::global().get_window() { trace_err!(window.unminimize(), "set win unminimize"); trace_err!(window.show(), "set win visible"); trace_err!(window.set_focus(), "set win focus"); @@ -123,7 +102,7 @@ pub fn create_window(app_handle: &AppHandle) { } let mut builder = tauri::WebviewWindowBuilder::new( - app_handle, + &app_handle, "main".to_string(), tauri::WebviewUrl::App("index.html".into()), ) @@ -179,7 +158,7 @@ pub fn create_window(app_handle: &AppHandle) { .latest() .window_is_maximized .unwrap_or(false); - log::trace!("try to calculate the monitor size"); + log::trace!(target:"app", "try to calculate the monitor size"); let center = (|| -> Result { let mut center = false; let monitor = win.current_monitor()?.ok_or(anyhow::anyhow!(""))?; @@ -212,7 +191,8 @@ pub fn create_window(app_handle: &AppHandle) { } /// save window size and position -pub fn save_window_size_position(app_handle: &AppHandle, save_to_file: bool) -> Result<()> { +pub fn save_window_size_position(save_to_file: bool) -> Result<()> { + let app_handle = handle::Handle::global().app_handle().unwrap(); let verge = Config::verge(); let mut verge = verge.latest(); @@ -238,34 +218,103 @@ pub fn save_window_size_position(app_handle: &AppHandle, save_to_file: bool) -> } pub async fn resolve_scheme(param: String) -> Result<()> { - let url = param - .trim_start_matches("clash://install-config/?url=") - .trim_start_matches("clash://install-config?url="); + log::info!(target:"app", "received deep link: {}", param); - let handle = handle::Handle::global(); - let app_handle = handle.app_handle.lock().clone(); - if let Some(app_handle) = app_handle.as_ref() { - match import_profile(url.to_string(), None).await { - Ok(_) => { - app_handle - .notification() - .builder() - .title("Clash Verge") - .body("Import profile success") - .show() - .unwrap(); - } - Err(e) => { - app_handle - .notification() - .builder() - .title("Clash Verge") - .body(format!("Import profile failed: {e}")) - .show() - .unwrap(); - log::error!("Import profile failed: {e}"); + let app_handle = handle::Handle::global().app_handle().unwrap(); + + let param_str = if param.starts_with("[") && param.len() > 4 { + param + .get(2..param.len() - 2) + .ok_or_else(|| anyhow::anyhow!("Invalid string slice boundaries"))? + } else { + param.as_str() + }; + + // 解析 URL + let link_parsed = match Url::parse(param_str) { + Ok(url) => url, + Err(e) => { + bail!("failed to parse deep link: {:?}, param: {:?}", e, param); + } + }; + + if link_parsed.scheme() == "clash" || link_parsed.scheme() == "clash-verge" { + let name = link_parsed + .query_pairs() + .find(|(key, _)| key == "name") + .map(|(_, value)| value.into_owned()); + + let encode_url = link_parsed + .query_pairs() + .find(|(key, _)| key == "url") + .map(|(_, value)| value.into_owned()); + + match encode_url { + Some(url) => { + let url = percent_decode_str(url.as_ref()) + .decode_utf8_lossy() + .to_string(); + + create_window(); + match PrfItem::from_url(url.as_ref(), name, None, None).await { + Ok(item) => { + let uid = item.uid.clone().unwrap(); + let _ = wrap_err!(Config::profiles().data().append_item(item)); + app_handle + .notification() + .builder() + .title("Clash Verge") + .body("Import profile success") + .show() + .unwrap(); + + handle::Handle::notice_message("import_sub_url::ok", uid); + } + Err(e) => { + app_handle + .notification() + .builder() + .title("Clash Verge") + .body(format!("Import profile failed: {e}")) + .show() + .unwrap(); + handle::Handle::notice_message("import_sub_url::error", e.to_string()); + bail!("Failed to add subscriptions: {e}"); + } + } } + None => bail!("failed to get profile url"), } } + + Ok(()) +} + +fn resolve_random_port_config() -> Result<()> { + let verge_config = Config::verge(); + let clash_config = Config::clash(); + let enable_random_port = verge_config.latest().enable_random_port.unwrap_or(false); + + let default_port = verge_config + .latest() + .verge_mixed_port + .unwrap_or(clash_config.data().get_mixed_port()); + + let port = if enable_random_port { + find_unused_port().unwrap_or(default_port) + } else { + default_port + }; + + verge_config.data().patch_config(IVerge { + verge_mixed_port: Some(port), + ..IVerge::default() + }); + verge_config.data().save_file()?; + + let mut mapping = Mapping::new(); + mapping.insert("mixed-port".into(), port.into()); + clash_config.data().patch_config(mapping); + clash_config.data().save_config()?; Ok(()) } diff --git a/clash-verge-rev/src-tauri/src/utils/server.rs b/clash-verge-rev/src-tauri/src/utils/server.rs index 3090da3642..2f2b20bb3d 100644 --- a/clash-verge-rev/src-tauri/src/utils/server.rs +++ b/clash-verge-rev/src-tauri/src/utils/server.rs @@ -2,11 +2,10 @@ extern crate warp; use super::resolve; use crate::config::{Config, IVerge, DEFAULT_PAC}; +use crate::log_err; use anyhow::{bail, Result}; use port_scanner::local_port_available; use std::convert::Infallible; -use tauri::AppHandle; -use warp::http::StatusCode; use warp::Filter; #[derive(serde::Deserialize, Debug)] @@ -17,36 +16,24 @@ struct QueryParam { /// check whether there is already exists pub async fn check_singleton() -> Result<()> { let port = IVerge::get_singleton_port(); - if !local_port_available(port) { - let resp = reqwest::get(format!("http://127.0.0.1:{port}/commands/ping")) - .await? - .text() - .await?; - - if &resp == "ok" { - let argvs: Vec = std::env::args().collect(); - if argvs.len() > 1 { + let argvs: Vec = std::env::args().collect(); + if argvs.len() > 1 { + #[cfg(not(target_os = "macos"))] + { let param = argvs[1].as_str(); if param.starts_with("clash:") { - reqwest::get(format!( + let _ = reqwest::get(format!( "http://127.0.0.1:{port}/commands/scheme?param={param}" )) - .await? - .text() - .await?; + .await; } - } else { - reqwest::get(format!("http://127.0.0.1:{port}/commands/visible")) - .await? - .text() - .await?; } - bail!("app exists"); + } else { + let _ = reqwest::get(format!("http://127.0.0.1:{port}/commands/visible")).await; } - log::error!("failed to setup singleton listen server"); - Ok(()) + bail!("app exists"); } else { Ok(()) } @@ -54,15 +41,12 @@ pub async fn check_singleton() -> Result<()> { /// The embed server only be used to implement singleton process /// maybe it can be used as pac server later -pub fn embed_server(app_handle: &AppHandle) { +pub fn embed_server() { let port = IVerge::get_singleton_port(); - let handle = app_handle.clone(); tauri::async_runtime::spawn(async move { - let ping = warp::path!("commands" / "ping").map(move || "ok"); - let visible = warp::path!("commands" / "visible").map(move || { - resolve::create_window(&handle); + resolve::create_window(); "ok" }); @@ -82,21 +66,15 @@ pub fn embed_server(app_handle: &AppHandle) { .body(content) .unwrap_or_default() }); + async fn scheme_handler(query: QueryParam) -> Result { + log_err!(resolve::resolve_scheme(query.param).await); + Ok("ok") + } + let scheme = warp::path!("commands" / "scheme") .and(warp::query::()) .and_then(scheme_handler); - - async fn scheme_handler(query: QueryParam) -> Result { - let result = resolve::resolve_scheme(query.param).await; - Ok(match result { - Ok(_) => warp::reply::with_status("Ok", StatusCode::OK), - Err(_) => { - warp::reply::with_status("Internal Error", StatusCode::INTERNAL_SERVER_ERROR) - } - }) - } - - let commands = ping.or(visible).or(pac).or(scheme); + let commands = visible.or(scheme).or(pac); warp::serve(commands).run(([127, 0, 0, 1], port)).await; }); } diff --git a/clash-verge-rev/src-tauri/tauri.conf.json b/clash-verge-rev/src-tauri/tauri.conf.json old mode 100644 new mode 100755 index 0876ef18ad..668f19c48b --- a/clash-verge-rev/src-tauri/tauri.conf.json +++ b/clash-verge-rev/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "bundle": { "active": true, - "longDescription": "A Clash Meta GUI based on tauri.", + "longDescription": "Clash Verge Rev", "icon": [ "icons/32x32.png", "icons/128x128.png", @@ -15,7 +15,7 @@ "externalBin": ["sidecar/verge-mihomo", "sidecar/verge-mihomo-alpha"], "copyright": "GNU General Public License v3.0", "category": "DeveloperTool", - "shortDescription": "A Clash Meta GUI based on tauri.", + "shortDescription": "Clash Verge Rev", "createUpdaterArtifacts": "v1Compatible" }, "build": { @@ -25,7 +25,7 @@ "devUrl": "http://localhost:3000/" }, "productName": "Clash Verge", - "version": "2.0.0", + "version": "2.0.0-rc.2", "identifier": "io.github.clash-verge-rev.clash-verge-rev", "plugins": { "updater": { @@ -34,6 +34,11 @@ "https://download.clashverge.dev/https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-proxy.json", "https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update.json" ] + }, + "deep-link": { + "desktop": { + "schemes": ["clash", "clash-verge"] + } } }, "app": { @@ -44,7 +49,6 @@ "enable": true }, "csp": null - }, - "windows": [] + } } } diff --git a/clash-verge-rev/src-tauri/tauri.linux.conf.json b/clash-verge-rev/src-tauri/tauri.linux.conf.json index eb8e2aee72..7493b2704c 100644 --- a/clash-verge-rev/src-tauri/tauri.linux.conf.json +++ b/clash-verge-rev/src-tauri/tauri.linux.conf.json @@ -1,5 +1,6 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", + "identifier": "io.github.clash-verge-rev.clash-verge-rev", "bundle": { "targets": ["deb", "rpm"], "linux": { @@ -17,7 +18,14 @@ "conflicts": ["clash-verge"], "obsoletes": ["clash-verge"] } - } + }, + "externalBin": [ + "./resources/clash-verge-service", + "./resources/install-service", + "./resources/uninstall-service", + "./sidecar/verge-mihomo", + "./sidecar/verge-mihomo-alpha" + ] }, "app": { "trayIcon": { diff --git a/clash-verge-rev/src-tauri/tauri.macos.conf.json b/clash-verge-rev/src-tauri/tauri.macos.conf.json index 21748a571c..95dc299afc 100644 --- a/clash-verge-rev/src-tauri/tauri.macos.conf.json +++ b/clash-verge-rev/src-tauri/tauri.macos.conf.json @@ -1,5 +1,6 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", + "identifier": "io.github.clash-verge-rev.clash-verge-rev", "bundle": { "targets": ["app", "dmg"], "macOS": { diff --git a/clash-verge-rev/src-tauri/tauri.windows.conf.json b/clash-verge-rev/src-tauri/tauri.windows.conf.json index f3a7d6adec..84047f1bf7 100644 --- a/clash-verge-rev/src-tauri/tauri.windows.conf.json +++ b/clash-verge-rev/src-tauri/tauri.windows.conf.json @@ -1,5 +1,6 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", + "identifier": "io.github.clash-verge-rev.clash-verge-rev", "bundle": { "targets": ["nsis"], "windows": { @@ -23,6 +24,7 @@ "trayIcon": { "iconPath": "icons/tray-icon.ico", "iconAsTemplate": true - } + }, + "windows": [] } } diff --git a/clash-verge-rev/src/components/layout/layout-control.tsx b/clash-verge-rev/src/components/layout/layout-control.tsx index eda6a8c3bd..bd12afd5d2 100644 --- a/clash-verge-rev/src/components/layout/layout-control.tsx +++ b/clash-verge-rev/src/components/layout/layout-control.tsx @@ -95,7 +95,7 @@ export const LayoutControl = () => { svg: { transform: "scale(1.05)" }, ":hover": { bgcolor: "#ff000090" }, }} - onClick={() => appWindow.close()} + onClick={() => appWindow.hide()} > diff --git a/clash-verge-rev/src/components/setting/mods/layout-viewer.tsx b/clash-verge-rev/src/components/setting/mods/layout-viewer.tsx index 4253545d14..be0d70cd28 100644 --- a/clash-verge-rev/src/components/setting/mods/layout-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/layout-viewer.tsx @@ -196,8 +196,8 @@ export const LayoutViewer = forwardRef((props, ref) => { }, ], }); - if (selected?.path.length) { - await copyIconFile(`${selected.path}`, "common"); + if (selected) { + await copyIconFile(`${selected}`, "common"); await initIconPath(); onChangeData({ common_tray_icon: true }); patchVerge({ common_tray_icon: true }); @@ -242,8 +242,8 @@ export const LayoutViewer = forwardRef((props, ref) => { }, ], }); - if (selected?.path.length) { - await copyIconFile(`${selected.path}`, "sysproxy"); + if (selected) { + await copyIconFile(`${selected}`, "sysproxy"); await initIconPath(); onChangeData({ sysproxy_tray_icon: true }); patchVerge({ sysproxy_tray_icon: true }); @@ -281,13 +281,13 @@ export const LayoutViewer = forwardRef((props, ref) => { multiple: false, filters: [ { - name: "Tray Icon Image", + name: "Tun Icon Image", extensions: ["png", "ico"], }, ], }); - if (selected?.path.length) { - await copyIconFile(`${selected.path}`, "tun"); + if (selected) { + await copyIconFile(`${selected}`, "tun"); await initIconPath(); onChangeData({ tun_tray_icon: true }); patchVerge({ tun_tray_icon: true }); diff --git a/clash-verge-rev/src/components/setting/mods/service-switcher.tsx b/clash-verge-rev/src/components/setting/mods/service-switcher.tsx deleted file mode 100644 index 9dd2d5a6c9..0000000000 --- a/clash-verge-rev/src/components/setting/mods/service-switcher.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import { KeyedMutator } from "swr"; -import { useState } from "react"; -import { useLockFn } from "ahooks"; -import { useTranslation } from "react-i18next"; -import { installService, uninstallService } from "@/services/cmds"; -import { Notice } from "@/components/base"; -import { LoadingButton } from "@mui/lab"; -import { PasswordInput } from "./password-input"; -import getSystem from "@/utils/get-system"; - -interface Props { - status: "active" | "installed" | "unknown" | "uninstall"; - mutate: KeyedMutator<"active" | "installed" | "unknown" | "uninstall">; - patchVerge: (value: Partial) => Promise; - onChangeData: (patch: Partial) => void; -} - -export const ServiceSwitcher = (props: Props) => { - const { status, mutate, patchVerge, onChangeData } = props; - const isWindows = getSystem() === "windows"; - const isActive = status === "active"; - const isInstalled = status === "installed"; - const isUninstall = status === "uninstall" || status === "unknown"; - - const { t } = useTranslation(); - const [serviceLoading, setServiceLoading] = useState(false); - const [uninstallServiceLoaing, setUninstallServiceLoading] = useState(false); - const [openInstall, setOpenInstall] = useState(false); - const [openUninstall, setOpenUninstall] = useState(false); - - async function install(passwd: string) { - try { - setOpenInstall(false); - await installService(passwd); - await mutate(); - setTimeout(() => { - mutate(); - }, 2000); - Notice.success(t("Service Installed Successfully")); - setServiceLoading(false); - } catch (err: any) { - await mutate(); - setTimeout(() => { - mutate(); - }, 2000); - Notice.error(err.message || err.toString()); - setServiceLoading(false); - } - } - - async function uninstall(passwd: string) { - try { - setOpenUninstall(false); - await uninstallService(passwd); - await mutate(); - setTimeout(() => { - mutate(); - }, 2000); - Notice.success(t("Service Uninstalled Successfully")); - setUninstallServiceLoading(false); - } catch (err: any) { - await mutate(); - setTimeout(() => { - mutate(); - }, 2000); - Notice.error(err.message || err.toString()); - setUninstallServiceLoading(false); - } - } - - const onInstallOrEnableService = useLockFn(async () => { - setServiceLoading(true); - if (isUninstall) { - // install service - if (isWindows) { - await install(""); - } else { - setOpenInstall(true); - } - } else { - try { - // enable or disable service - await patchVerge({ enable_service_mode: !isActive }); - onChangeData({ enable_service_mode: !isActive }); - await mutate(); - setTimeout(() => { - mutate(); - }, 2000); - setServiceLoading(false); - } catch (err: any) { - await mutate(); - Notice.error(err.message || err.toString()); - setServiceLoading(false); - } - } - }); - - const onUninstallService = useLockFn(async () => { - setUninstallServiceLoading(true); - if (isWindows) { - await uninstall(""); - } else { - setOpenUninstall(true); - } - }); - - return ( - <> - {openInstall && } - {openUninstall && } - - - {isActive ? t("Disable") : isInstalled ? t("Enable") : t("Install")} - - {isInstalled && ( - - {t("Uninstall")} - - )} - - ); -}; diff --git a/clash-verge-rev/src/components/setting/mods/update-viewer.tsx b/clash-verge-rev/src/components/setting/mods/update-viewer.tsx index d0887e6f3b..ca600ff68a 100644 --- a/clash-verge-rev/src/components/setting/mods/update-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/update-viewer.tsx @@ -7,10 +7,11 @@ import { relaunch } from "@tauri-apps/plugin-process"; import { check as checkUpdate } from "@tauri-apps/plugin-updater"; import { BaseDialog, DialogRef, Notice } from "@/components/base"; import { useUpdateState, useSetUpdateState } from "@/services/states"; -import { listen, Event, UnlistenFn } from "@tauri-apps/api/event"; +import { Event, UnlistenFn } from "@tauri-apps/api/event"; import { portableFlag } from "@/pages/_layout"; import { open as openUrl } from "@tauri-apps/plugin-shell"; import ReactMarkdown from "react-markdown"; +import { useListen } from "@/hooks/use-listen"; let eventListener: UnlistenFn | null = null; @@ -21,6 +22,7 @@ export const UpdateViewer = forwardRef((props, ref) => { const updateState = useUpdateState(); const setUpdateState = useSetUpdateState(); + const { addListener } = useListen(); const { data: updateInfo } = useSWR("checkUpdate", checkUpdate, { errorRetryCount: 2, @@ -66,7 +68,7 @@ export const UpdateViewer = forwardRef((props, ref) => { if (eventListener !== null) { eventListener(); } - eventListener = await listen( + eventListener = await addListener( "tauri://update-download-progress", (e: Event) => { setTotal(e.payload.contentLength); diff --git a/clash-verge-rev/src/components/setting/setting-system.tsx b/clash-verge-rev/src/components/setting/setting-system.tsx index 7686c8f622..7f5799cb96 100644 --- a/clash-verge-rev/src/components/setting/setting-system.tsx +++ b/clash-verge-rev/src/components/setting/setting-system.tsx @@ -7,7 +7,6 @@ import { useVerge } from "@/hooks/use-verge"; import { DialogRef, Notice, Switch } from "@/components/base"; import { SettingList, SettingItem } from "./mods/setting-comp"; import { GuardState } from "./mods/guard-state"; -import { ServiceSwitcher } from "./mods/service-switcher"; import { SysproxyViewer } from "./mods/sysproxy-viewer"; import { TunViewer } from "./mods/tun-viewer"; import { TooltipIcon } from "@/components/base/base-tooltip-icon"; @@ -67,34 +66,15 @@ const SettingSystem = ({ onError }: Props) => { onCatch={onError} onFormat={onSwitchFormat} onChange={(e) => { - if (serviceStatus !== "active") { - onChangeData({ enable_tun_mode: false }); - } else { - onChangeData({ enable_tun_mode: e }); - } + onChangeData({ enable_tun_mode: e }); }} onGuard={(e) => { - if (serviceStatus !== "active" && e) { - Notice.error(t("Please Enable Service Mode")); - return Promise.resolve(); - } else { - return patchVerge({ enable_tun_mode: e }); - } + return patchVerge({ enable_tun_mode: e }); }} > - - - - - { }, ], }); - if (selected?.path.length) { - onChangeData({ startup_script: `${selected.path}` }); - patchVerge({ startup_script: `${selected.path}` }); + if (selected) { + onChangeData({ startup_script: `${selected}` }); + patchVerge({ startup_script: `${selected}` }); } }} > @@ -243,7 +243,7 @@ const SettingVerge = ({ onError }: Props) => { label={t("Runtime Config")} /> - + diff --git a/clash-verge-rev/src/components/test/test-item.tsx b/clash-verge-rev/src/components/test/test-item.tsx index faee6e37a5..dfb75315b8 100644 --- a/clash-verge-rev/src/components/test/test-item.tsx +++ b/clash-verge-rev/src/components/test/test-item.tsx @@ -18,9 +18,9 @@ import { Notice } from "@/components/base"; import { TestBox } from "./test-box"; import delayManager from "@/services/delay"; import { cmdTestDelay, downloadIconCache } from "@/services/cmds"; -import { listen, UnlistenFn } from "@tauri-apps/api/event"; +import { UnlistenFn } from "@tauri-apps/api/event"; import { convertFileSrc } from "@tauri-apps/api/core"; - +import { useListen } from "@/hooks/use-listen"; interface Props { id: string; itemData: IVergeTestItem; @@ -47,6 +47,7 @@ export const TestItem = (props: Props) => { const [delay, setDelay] = useState(-1); const { uid, name, icon, url } = itemData; const [iconCachePath, setIconCachePath] = useState(""); + const { addListener } = useListen(); useEffect(() => { initIconCachePath(); @@ -91,7 +92,7 @@ export const TestItem = (props: Props) => { const listenTsetEvent = async () => { eventListener(); - eventListener = await listen("verge://test-all", () => { + eventListener = await addListener("verge://test-all", () => { onDelay(); }); }; diff --git a/clash-verge-rev/src/components/test/test-viewer.tsx b/clash-verge-rev/src/components/test/test-viewer.tsx index 00d7f8d08b..97601fecff 100644 --- a/clash-verge-rev/src/components/test/test-viewer.tsx +++ b/clash-verge-rev/src/components/test/test-viewer.tsx @@ -67,6 +67,16 @@ export const TestViewer = forwardRef((props, ref) => { let newList; let uid; + if (form.icon && form.icon.startsWith(" { + const unlistenFns = useRef([]); + + const addListener = async ( + eventName: string, + handler: EventCallback + ) => { + const unlisten = await listen(eventName, handler); + unlistenFns.current.push(unlisten); + return unlisten; + }; + const removeAllListeners = () => { + unlistenFns.current.forEach((unlisten) => unlisten()); + unlistenFns.current = []; + }; + + const setupCloseListener = async function () { + await event.once("tauri://close-requested", async () => { + removeAllListeners(); + }); + }; + + return { + addListener, + setupCloseListener, + }; +}; diff --git a/clash-verge-rev/src/locales/en.json b/clash-verge-rev/src/locales/en.json index 58e06f36c3..7a2d652a5a 100644 --- a/clash-verge-rev/src/locales/en.json +++ b/clash-verge-rev/src/locales/en.json @@ -193,9 +193,9 @@ "Test URL": "Test URL", "Settings": "Settings", "System Setting": "System Setting", - "Tun Mode": "Tun Mode", + "Tun Mode": "Tun (Virtual NIC) Mode", "Reset to Default": "Reset to Default", - "Tun Mode Info": "The Tun mode requires granting core-related permissions. Please enable service mode before using it", + "Tun Mode Info": "Tun (Virtual NIC) mode: Captures all system traffic, when enabled, there is no need to enable system proxy.", "Stack": "Tun Stack", "System and Mixed Can Only be Used in Service Mode": "System and Mixed Can Only be Used in Service Mode", "Device": "Device Name", @@ -205,7 +205,7 @@ "DNS Hijack": "DNS Hijack", "MTU": "Max Transmission Unit", "Service Mode": "Service Mode", - "Service Mode Info": "The core launched by the service can obtain corresponding permissions after installation and authorization of the service", + "Service Mode Info": "Please install the service mode before enabling TUN mode. The kernel process started by the service can obtain the permission to install the virtual network card (TUN mode)", "Current State": "Current State", "pending": "pending", "installed": "installed", @@ -331,14 +331,14 @@ "toggle_system_proxy": "Enable/Disable System Proxy", "toggle_tun_mode": "Enable/Disable Tun Mode", "Runtime Config": "Runtime Config", - "Open App Dir": "Open App Dir", + "Open Conf Dir": "Open Conf Dir", "Open Core Dir": "Open Core Dir", "Open Logs Dir": "Open Logs Dir", "Check for Updates": "Check for Updates", "Go to Release Page": "Go to Release Page", "Portable Updater Error": "The portable version does not support in-app updates. Please manually download and replace it", "Break Change Update Error": "This version is a major update and does not support in-app updates. Please uninstall it and manually download and install the new version", - "Open Dev Tools": "Open Dev Tools", + "Open Dev Tools": "Dev Tools", "Exit": "Exit", "Verge Version": "Verge Version", "ReadOnly": "ReadOnly", @@ -367,5 +367,6 @@ "Clash Core Restarted": "Clash Core Restarted", "Switched to _clash Core": "Switched to {{core}} Core", "GeoData Updated": "GeoData Updated", - "Currently on the Latest Version": "Currently on the Latest Version" + "Currently on the Latest Version": "Currently on the Latest Version", + "Import Subscription Successful": "Import subscription successful" } diff --git a/clash-verge-rev/src/locales/fa.json b/clash-verge-rev/src/locales/fa.json index 1b533dd828..108dc01d35 100644 --- a/clash-verge-rev/src/locales/fa.json +++ b/clash-verge-rev/src/locales/fa.json @@ -191,9 +191,9 @@ "Test URL": "آدرس آزمون", "Settings": "تنظیمات", "System Setting": "تنظیمات سیستم", - "Tun Mode": "حالت Tun", + "Tun Mode": "Tun (کارت شبکه مجازی)", "Reset to Default": "بازنشانی به پیش‌فرض", - "Tun Mode Info": "حالت Tun نیاز به اعطای مجوزهای مربوط به هسته دارد. لطفاً قبل از استفاده، حالت سرویس را فعال کنید", + "Tun Mode Info": "حالت Tun (NIC مجازی): تمام ترافیک سیستم را ضبط می کند، وقتی فعال باشد، نیازی به فعال کردن پروکسی سیستم نیست.", "Stack": "انباشته Tun", "System and Mixed Can Only be Used in Service Mode": "سیستم و ترکیبی تنها می‌توانند در حالت سرویس استفاده شوند", "Device": "نام دستگاه", @@ -203,7 +203,7 @@ "DNS Hijack": "ربایش DNS", "MTU": "واحد حداکثر انتقال", "Service Mode": "حالت سرویس", - "Service Mode Info": "هسته راه اندازی شده توسط سرویس می تواند مجوزهای مربوطه را پس از نصب و مجوز سرویس دریافت کند", + "Service Mode Info": "لطفاً قبل از فعال کردن حالت TUN، حالت سرویس را نصب کنید.", "Current State": "وضعیت فعلی", "pending": "در انتظار", "installed": "نصب شده", @@ -329,7 +329,7 @@ "toggle_system_proxy": "فعال/غیرفعال کردن پراکسی سیستم", "toggle_tun_mode": "فعال/غیرفعال کردن حالت Tun", "Runtime Config": "پیکربندی زمان اجرا", - "Open App Dir": "باز کردن پوشه برنامه", + "Open Conf Dir": "باز کردن پوشه برنامه", "Open Core Dir": "باز کردن پوشه هسته", "Open Logs Dir": "باز کردن پوشه لاگ‌ها", "Check for Updates": "بررسی برای به‌روزرسانی‌ها", @@ -365,5 +365,6 @@ "Clash Core Restarted": "هسته Clash مجدداً راه‌اندازی شد", "Switched to _clash Core": "تغییر به هسته {{core}}", "GeoData Updated": "GeoData به‌روزرسانی شد", - "Currently on the Latest Version": "در حال حاضر در آخرین نسخه" + "Currently on the Latest Version": "در حال حاضر در آخرین نسخه", + "Import Subscription Successfully": "عضویت با موفقیت وارد شد" } diff --git a/clash-verge-rev/src/locales/ru.json b/clash-verge-rev/src/locales/ru.json index 1d753a0e3f..09eaa205f1 100644 --- a/clash-verge-rev/src/locales/ru.json +++ b/clash-verge-rev/src/locales/ru.json @@ -191,9 +191,9 @@ "Test URL": "Тестовый URL", "Settings": "Настройки", "System Setting": "Настройки системы", - "Tun Mode": "Режим туннеля", + "Tun Mode": "Tun (виртуальный сетевой адаптер) режим", "Reset to Default": "Сбросить настройки по умолчанию", - "Tun Mode Info": "Режим туннеля требует предоставления разрешений, связанных с ядрам. Пожалуйста, включите сервисный режим перед его использованием", + "Tun Mode Info": "Режим Tun (виртуальный сетевой адаптер): захватывает весь системный трафик, при включении нет необходимости включать системный прокси-сервер.", "Stack": "Стек", "System and Mixed Can Only be Used in Service Mode": "Система и смешанные могут использоваться только в сервисном режиме", "Device": "Имя устройства", @@ -203,7 +203,7 @@ "DNS Hijack": "DNS-перехват", "MTU": "Максимальная единица передачи", "Service Mode": "Режим сервиса", - "Service Mode Info": "Ядро, запущенное сервисом, может получить соответствующие разрешения после установки и авторизации сервиса", + "Service Mode Info": "Установите сервисный режим перед включением режима TUN. Процесс ядра, запущенный службой, может получить разрешение на установку виртуальной сетевой карты (режим TUN).", "Current State": "Текущее состояние", "pending": "Ожидающий", "installed": "Установленный", @@ -329,7 +329,7 @@ "toggle_system_proxy": "Включить/Отключить системный прокси", "toggle_tun_mode": "Включить/Отключить режим туннеля", "Runtime Config": "Используемый конфиг", - "Open App Dir": "Открыть папку приложения", + "Open Conf Dir": "Открыть папку приложения", "Open Core Dir": "Открыть папку ядра", "Open Logs Dir": "Открыть папку логов", "Check for Updates": "Проверить обновления", @@ -365,5 +365,6 @@ "Clash Core Restarted": "Clash ядра перезапущено", "Switched to _clash Core": "Переключено на ядра {{core}}", "GeoData Updated": "GeoData Обновлена", - "Currently on the Latest Version": "В настоящее время используется последняя версия" + "Currently on the Latest Version": "В настоящее время используется последняя версия", + "Import subscription successful": "Импорт подписки успешно" } diff --git a/clash-verge-rev/src/locales/zh.json b/clash-verge-rev/src/locales/zh.json index 16a1cf7a48..2760e3e9c4 100644 --- a/clash-verge-rev/src/locales/zh.json +++ b/clash-verge-rev/src/locales/zh.json @@ -193,9 +193,9 @@ "Test URL": "测试地址", "Settings": "设置", "System Setting": "系统设置", - "Tun Mode": "Tun 模式", + "Tun Mode": "Tun(虚拟网卡)模式", "Reset to Default": "重置为默认值", - "Tun Mode Info": "Tun模式需要授予内核相关权限,使用前请先开启服务模式", + "Tun Mode Info": "Tun(虚拟网卡)模式接管系统所有流量,启用时无须打开系统代理", "Stack": "Tun 模式堆栈", "System and Mixed Can Only be Used in Service Mode": "System 和 Mixed 只能在服务模式下使用", "Device": "Tun 网卡名称", @@ -205,7 +205,7 @@ "DNS Hijack": "DNS 劫持", "MTU": "最大传输单元", "Service Mode": "服务模式", - "Service Mode Info": "安装并授权服务后,由该服务启动的内核进程可获得相关权限", + "Service Mode Info": "启用TUN模式前请安装服务模式,该服务启动的内核进程可获得安装虚拟网卡(TUN模式)的权限", "Current State": "当前状态", "pending": "等待中", "installed": "已安装", @@ -331,14 +331,14 @@ "toggle_system_proxy": "打开/关闭系统代理", "toggle_tun_mode": "打开/关闭 Tun 模式", "Runtime Config": "当前配置", - "Open App Dir": "应用目录", + "Open Conf Dir": "配置目录", "Open Core Dir": "内核目录", "Open Logs Dir": "日志目录", "Check for Updates": "检查更新", "Go to Release Page": "前往发布页", "Portable Updater Error": "便携版不支持应用内更新,请手动下载替换", "Break Change Update Error": "此版本为重大更新,不支持应用内更新,请卸载后手动下载安装", - "Open Dev Tools": "打开开发者工具", + "Open Dev Tools": "开发者工具", "Exit": "退出", "Verge Version": "Verge 版本", "ReadOnly": "只读", @@ -360,12 +360,13 @@ "Invalid Bypass Format": "无效的代理绕过格式", "Clash Port Modified": "Clash 端口已修改", "Port Conflict": "端口冲突", - "Restart Application to Apply Modifications": "重启应用程序以应用修改", + "Restart Application to Apply Modifications": "重启Verge以应用修改", "External Controller Address Modified": "外部控制器监听地址已修改", "Permissions Granted Successfully for _clash Core": "{{core}} 内核授权成功", "Core Version Updated": "内核版本已更新", "Clash Core Restarted": "已重启 Clash 内核", "Switched to _clash Core": "已切换至 {{core}} 内核", "GeoData Updated": "已更新 GeoData", - "Currently on the Latest Version": "当前已是最新版本" + "Currently on the Latest Version": "当前已是最新版本", + "Import Subscription Successful": "导入订阅成功" } diff --git a/clash-verge-rev/src/pages/_layout.tsx b/clash-verge-rev/src/pages/_layout.tsx index 56a5361626..19d4f8c0a0 100644 --- a/clash-verge-rev/src/pages/_layout.tsx +++ b/clash-verge-rev/src/pages/_layout.tsx @@ -4,9 +4,8 @@ import relativeTime from "dayjs/plugin/relativeTime"; import { SWRConfig, mutate } from "swr"; import { useEffect } from "react"; import { useTranslation } from "react-i18next"; -import { useLocation, useRoutes } from "react-router-dom"; +import { useLocation, useRoutes, useNavigate } from "react-router-dom"; import { List, Paper, ThemeProvider, SvgIcon } from "@mui/material"; -import { listen } from "@tauri-apps/api/event"; import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"; import { routers } from "./_routers"; import { getAxios } from "@/services/api"; @@ -25,9 +24,10 @@ import getSystem from "@/utils/get-system"; import "dayjs/locale/ru"; import "dayjs/locale/zh-cn"; import { getPortableFlag } from "@/services/cmds"; -import { useNavigate } from "react-router-dom"; import React from "react"; import { TransitionGroup, CSSTransition } from "react-transition-group"; +import { useListen } from "@/hooks/use-listen"; + const appWindow = getCurrentWebviewWindow(); export let portableFlag = false; @@ -46,17 +46,13 @@ const Layout = () => { const navigate = useNavigate(); const location = useLocation(); const routersEles = useRoutes(routers); + const { addListener, setupCloseListener } = useListen(); if (!routersEles) return null; - useEffect(() => { - window.addEventListener("keydown", (e) => { - // macOS有cmd+w - if (e.key === "Escape" && OS !== "macos") { - appWindow.close(); - } - }); + setupCloseListener(); - listen("verge://refresh-clash-config", async () => { + useEffect(() => { + addListener("verge://refresh-clash-config", async () => { // the clash info may be updated await getAxios(true); mutate("getProxies"); @@ -66,12 +62,21 @@ const Layout = () => { }); // update the verge config - listen("verge://refresh-verge-config", () => mutate("getVergeConfig")); + addListener("verge://refresh-verge-config", () => mutate("getVergeConfig")); // 设置提示监听 - listen("verge://notice-message", ({ payload }) => { + addListener("verge://notice-message", ({ payload }) => { const [status, msg] = payload as [string, string]; switch (status) { + case "import_sub_url::ok": + navigate("/profile", { state: { current: msg } }); + + Notice.success(t("Import Subscription Successful")); + break; + case "import_sub_url::error": + navigate("/profile"); + Notice.error(msg); + break; case "set_config::ok": Notice.success(t("Clash Config Updated")); break; diff --git a/clash-verge-rev/src/pages/profiles.tsx b/clash-verge-rev/src/pages/profiles.tsx index 71fee9af53..32731415e9 100644 --- a/clash-verge-rev/src/pages/profiles.tsx +++ b/clash-verge-rev/src/pages/profiles.tsx @@ -47,13 +47,15 @@ import { useProfiles } from "@/hooks/use-profiles"; import { ConfigViewer } from "@/components/setting/mods/config-viewer"; import { throttle } from "lodash-es"; import { BaseStyledTextField } from "@/components/base/base-styled-text-field"; -import { listen } from "@tauri-apps/api/event"; import { readTextFile } from "@tauri-apps/plugin-fs"; import { readText } from "@tauri-apps/plugin-clipboard-manager"; +import { useLocation } from "react-router-dom"; +import { useListen } from "@/hooks/use-listen"; const ProfilePage = () => { const { t } = useTranslation(); - + const location = useLocation(); + const { addListener } = useListen(); const [url, setUrl] = useState(""); const [disabled, setDisabled] = useState(false); const [activatings, setActivatings] = useState([]); @@ -64,9 +66,10 @@ const ProfilePage = () => { coordinateGetter: sortableKeyboardCoordinates, }) ); + const { current } = location.state || {}; useEffect(() => { - const unlisten = listen("tauri://file-drop", async (event) => { + const unlisten = addListener("tauri://file-drop", async (event) => { const fileList = event.payload as string[]; for (let file of fileList) { if (!file.endsWith(".yaml") && !file.endsWith(".yml")) { @@ -138,11 +141,11 @@ const ProfilePage = () => { const remoteItem = newProfiles.items?.find((e) => e.type === "remote"); - const profilesCount = newProfiles.items?.filter( + const itemsCount = newProfiles.items?.filter( (e) => e.type === "remote" || e.type === "local" ).length as number; - if (remoteItem && (profilesCount == 1 || !newProfiles.current)) { + if (remoteItem && (itemsCount == 1 || !newProfiles.current)) { const current = remoteItem.uid; await patchProfiles({ current }); mutateLogs(); @@ -168,27 +171,40 @@ const ProfilePage = () => { } }; - const onSelect = useLockFn(async (current: string, force: boolean) => { - if (!force && current === profiles.current) return; + const activateProfile = async (profile: string) => { // 避免大多数情况下loading态闪烁 + const reset = setTimeout(() => { - setActivatings([...currentActivatings(), current]); + setActivatings((prev) => [...prev, profile]); }, 100); + try { - await patchProfiles({ current }); + await patchProfiles({ current: profile }); await mutateLogs(); closeAllConnections(); - activateSelected().then(() => { - Notice.success(t("Profile Switched"), 1000); - }); + await activateSelected(); + Notice.success(t("Profile Switched"), 1000); } catch (err: any) { Notice.error(err?.message || err.toString(), 4000); } finally { clearTimeout(reset); setActivatings([]); } + }; + const onSelect = useLockFn(async (current: string, force: boolean) => { + if (!force && current === profiles.current) return; + await activateProfile(current); }); + useEffect(() => { + (async () => { + if (current && current !== profiles.current) { + console.log("current:", current); + await activateProfile(current); + } + })(); + }, current); + const onEnhance = useLockFn(async () => { setActivatings(currentActivatings()); try { diff --git a/clash-verge-rev/src/services/cmds.ts b/clash-verge-rev/src/services/cmds.ts index 552da399ea..c4e305898b 100644 --- a/clash-verge-rev/src/services/cmds.ts +++ b/clash-verge-rev/src/services/cmds.ts @@ -200,15 +200,6 @@ export async function checkService() { return "uninstall"; } } - -export async function installService(passwd: string) { - return invoke("install_service", { passwd }); -} - -export async function uninstallService(passwd: string) { - return invoke("uninstall_service", { passwd }); -} - export async function invoke_uwp_tool() { return invoke("invoke_uwp_tool").catch((err) => Notice.error(err?.message || err.toString(), 1500) diff --git a/lede/package/boot/uboot-rockchip/Makefile b/lede/package/boot/uboot-rockchip/Makefile index b92abee1f1..a3f0e5147d 100644 --- a/lede/package/boot/uboot-rockchip/Makefile +++ b/lede/package/boot/uboot-rockchip/Makefile @@ -298,6 +298,13 @@ define U-Boot/Default/rk3588 TPL:=rk3588_ddr_lp4_2112MHz_lp5_2400MHz_v1.16.bin endef +define U-Boot/rock5b-rk3588 + $(U-Boot/Default/rk3588) + NAME:=ROCK 5B + BUILD_DEVICES:= \ + radxa_rock-5b +endef + define U-Boot/sige7-rk3588 $(U-Boot/Default/rk3588) NAME:=Sige7 @@ -305,6 +312,29 @@ define U-Boot/sige7-rk3588 armsom_sige7 endef +define U-Boot/nanopc-t6-rk3588 + $(U-Boot/Default/rk3588) + NAME:=NanoPC T6 + BUILD_DEVICES:= \ + friendlyarm_nanopc-t6 +endef + +# RK3588S boards + +define U-Boot/nanopi-r6c-rk3588s + $(U-Boot/Default/rk3588) + NAME:=NanoPi R6C + BUILD_DEVICES:= \ + friendlyarm_nanopi-r6c +endef + +define U-Boot/nanopi-r6s-rk3588s + $(U-Boot/Default/rk3588) + NAME:=NanoPi R6S + BUILD_DEVICES:= \ + friendlyarm_nanopi-r6s +endef + UBOOT_TARGETS := \ panther-x2-rk3566 \ rock-3c-rk3566 \ @@ -337,6 +367,10 @@ UBOOT_TARGETS := \ nanopi-r2s-rk3328 \ orangepi-r1-plus-rk3328 \ orangepi-r1-plus-lts-rk3328 \ + nanopc-t6-rk3588 \ + nanopi-r6c-rk3588s \ + nanopi-r6s-rk3588s \ + rock5b-rk3588 \ sige7-rk3588 UBOOT_CONFIGURE_VARS += USE_PRIVATE_LIBGCC=yes diff --git a/lede/package/boot/uboot-rockchip/patches/320-rockchip-rk3588-Add-support-for-rock5b.patch b/lede/package/boot/uboot-rockchip/patches/320-rockchip-rk3588-Add-support-for-rock5b.patch new file mode 100644 index 0000000000..4781c5d412 --- /dev/null +++ b/lede/package/boot/uboot-rockchip/patches/320-rockchip-rk3588-Add-support-for-rock5b.patch @@ -0,0 +1,10 @@ +--- a/configs/rock5b-rk3588_defconfig ++++ b/configs/rock5b-rk3588_defconfig +@@ -27,7 +27,6 @@ + CONFIG_DEBUG_UART=y + CONFIG_FIT=y + CONFIG_FIT_VERBOSE=y +-CONFIG_SPL_FIT_SIGNATURE=y + CONFIG_SPL_LOAD_FIT=y + CONFIG_LEGACY_IMAGE_FORMAT=y + CONFIG_OF_BOARD_SETUP=y diff --git a/lede/package/boot/uboot-rockchip/patches/322-rockchip-rk3588s-Add-FriendlyElec-NanoPi-R6S.patch b/lede/package/boot/uboot-rockchip/patches/322-rockchip-rk3588s-Add-FriendlyElec-NanoPi-R6S.patch new file mode 100644 index 0000000000..ac85ced623 --- /dev/null +++ b/lede/package/boot/uboot-rockchip/patches/322-rockchip-rk3588s-Add-FriendlyElec-NanoPi-R6S.patch @@ -0,0 +1,823 @@ +--- /dev/null ++++ b/arch/arm/dts/rk3588s-nanopi-r6s-u-boot.dtsi +@@ -0,0 +1,30 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Copyright (c) 2021 Rockchip Electronics Co., Ltd. ++ */ ++ ++#include "rk3588s-u-boot.dtsi" ++ ++/ { ++ aliases { ++ mmc0 = &sdmmc; ++ mmc1 = &sdhci; ++ }; ++ ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc, &sdhci; ++ }; ++}; ++ ++&rng { ++ status = "okay"; ++}; ++ ++&sdhci { ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_data_strobe &emmc_rstnout>; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3588s-nanopi-r6s.dts +@@ -0,0 +1,713 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Copyright (c) 2021 Rockchip Electronics Co., Ltd. ++ * ++ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyelec.com) ++ * ++ * ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++#include ++#include ++#include "rk3588s.dtsi" ++ ++/ { ++ model = "FriendlyElec NanoPi R6S"; ++ compatible = "friendlyarm,nanopi-r6s", "rockchip,rk3588"; ++ ++ aliases { ++ ethernet0 = &gmac1; ++ mmc0 = &sdmmc; ++ mmc1 = &sdhci; ++ serial2 = &uart2; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&reset_button_pin>; ++ ++ button-reset { ++ debounce-interval = <50>; ++ gpios = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>; ++ label = "reset"; ++ linux,code = ; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lan1_led_pin>, <&lan2_led_pin>, <&power_led_pin>, <&wan_led_pin>; ++ ++ led-lan1 { ++ label = "green:lan1"; ++ gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ led-lan2 { ++ label = "green:lan2"; ++ gpios = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ power_led: led-power { ++ label = "red:power"; ++ gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ led-wan { ++ label = "green:wan"; ++ gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc5v0_usb: vcc5v0-usb-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ ++ vcc5v0_host_20: vcc5v0-host-20-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_host20_en>; ++ regulator-name = "vcc5v0_host_20"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++ ++ vcc_3v3_pcie20: vcc3v3-pcie20-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_3v3_pcie20"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3_s3>; ++ }; ++ ++ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_1v1_nldo_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ ++ vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc3v3_sd_en>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-max-microvolt = <3000000>; ++ regulator-min-microvolt = <3000000>; ++ regulator-name = "vcc_3v3_sd_s0"; ++ vin-supply = <&vcc_3v3_s3>; ++ }; ++ ++ vbus5v0_typec: vbus5v0-typec-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vbus5v0_typec_en>; ++ regulator-name = "vbus5v0_typec"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_big0_s0>; ++ mem-supply = <&vdd_cpu_big0_mem_s0>; ++}; ++ ++&cpu_b2 { ++ cpu-supply = <&vdd_cpu_big1_s0>; ++ mem-supply = <&vdd_cpu_big1_mem_s0>; ++}; ++ ++&gmac1 { ++ clock_in_out = "output"; ++ phy-handle = <&rgmii_phy1>; ++ phy-mode = "rgmii-rxid"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac1_miim ++ &gmac1_tx_bus2 ++ &gmac1_rx_bus2 ++ &gmac1_rgmii_clk ++ &gmac1_rgmii_bus>; ++ snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ /* Reset time is 20ms, 100ms for rtl8211f */ ++ snps,reset-delays-us = <0 20000 100000>; ++ tx_delay = <0x42>; ++ /* rx_delay = <0x4f>; */ ++ status = "okay"; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0m2_xfer>; ++ status = "okay"; ++ ++ vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: regulator@42 { ++ compatible = "rockchip,rk8602"; ++ reg = <0x42>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu_big0_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: regulator@43 { ++ compatible = "rockchip,rk8603", "rockchip,rk8602"; ++ reg = <0x43>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu_big1_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++}; ++ ++&i2c6 { ++ status = "okay"; ++ ++ hym8563: rtc@51 { ++ compatible = "haoyu,hym8563"; ++ reg = <0x51>; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ clock-output-names = "hym8563"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hym8563_int>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ wakeup-source; ++ }; ++}; ++ ++&mdio1 { ++ rgmii_phy1: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ }; ++}; ++ ++&pinctrl { ++ gpio-leds { ++ lan1_led_pin: lan1-led-pin { ++ rockchip,pins = <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ lan2_led_pin: lan2-led-pin { ++ rockchip,pins = <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ power_led_pin: power-led-pin { ++ rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ wan_led_pin: wan-led-pin { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ hym8563 { ++ hym8563_int: hym8563-int { ++ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ rockchip-key { ++ reset_button_pin: reset-button-pin { ++ rockchip,pins = <1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdmmc { ++ vcc3v3_sd_en: vcc3v3-sd-en { ++ rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ vbus5v0_typec_en: vbus5v0-typec-en { ++ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ vcc5v0_host20_en: vcc5v0-host20-en { ++ rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ max-frequency = <200000000>; ++ mmc-hs200-1_8v; ++ no-sdio; ++ no-sd; ++ non-removable; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ no-sdio; ++ no-mmc; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc_det>; ++ vmmc-supply = <&vcc_3v3_sd_s0>; ++ vqmmc-supply = <&vccio_sd_s0>; ++ status = "okay"; ++}; ++ ++&spi2 { ++ status = "okay"; ++ assigned-clocks = <&cru CLK_SPI2>; ++ assigned-clock-rates = <200000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; ++ num-cs = <1>; ++ ++ rk806single: rk806single@0 { ++ compatible = "rockchip,rk806"; ++ spi-max-frequency = <1000000>; ++ reg = <0x0>; ++ ++ interrupt-parent = <&gpio0>; ++ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, <&rk806_dvs2_null>, <&rk806_dvs3_null>; ++ ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc5-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc5v0_sys>; ++ vcc9-supply = <&vcc5v0_sys>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc_2v0_pldo_s3>; ++ vcc12-supply = <&vcc5v0_sys>; ++ vcc13-supply = <&vcc_1v1_nldo_s3>; ++ vcc14-supply = <&vcc_1v1_nldo_s3>; ++ vcca-supply = <&vcc5v0_sys>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ rk806_dvs1_null: dvs1-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs1_slp: dvs1-slp-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs1_pwrdn: dvs1-pwrdn-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs1_rst: dvs1-rst-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs2_null: dvs2-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs2_slp: dvs2-slp-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs2_pwrdn: dvs2-pwrdn-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs2_rst: dvs2-rst-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs2_dvs: dvs2-dvs-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_dvs2_gpio: dvs2-gpio-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun5"; ++ }; ++ ++ rk806_dvs3_null: dvs3-null-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs3_slp: dvs3-slp-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs3_pwrdn: dvs3-pwrdn-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs3_rst: dvs3-rst-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs3_dvs: dvs3-dvs-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_dvs3_gpio: dvs3-gpio-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun5"; ++ }; ++ ++ regulators { ++ vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_gpu_s0"; ++ regulator-enable-ramp-delay = <400>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_lit_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_log_s0: dcdc-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <750000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_log_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <750000>; ++ }; ++ }; ++ ++ vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-init-microvolt = <750000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_vdenc_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_ddr_s0: dcdc-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <900000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_ddr_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <850000>; ++ }; ++ }; ++ ++ vdd2_ddr_s3: dcdc-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vdd2_ddr_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_2v0_pldo_s3: dcdc-reg7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <2000000>; ++ regulator-max-microvolt = <2000000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_2v0_pldo_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <2000000>; ++ }; ++ }; ++ ++ vcc_3v3_s3: dcdc-reg8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc_3v3_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vddq_ddr_s0: dcdc-reg9 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vddq_ddr_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8_s3: dcdc-reg10 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ avcc_1v8_s0: pldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "avcc_1v8_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8_s0: pldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ avdd_1v2_s0: pldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-name = "avdd_1v2_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3_s0: pldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_3v3_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd_s0: pldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vccio_sd_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ pldo6_s3: pldo-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "pldo6_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_0v75_s3: nldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "vdd_0v75_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <750000>; ++ }; ++ }; ++ ++ vdd_ddr_pll_s0: nldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-name = "vdd_ddr_pll_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <850000>; ++ }; ++ }; ++ ++ avdd_0v75_s0: nldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "avdd_0v75_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_0v85_s0: nldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-name = "vdd_0v85_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_0v75_s0: nldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "vdd_0v75_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&uart2 { ++ pinctrl-0 = <&uart2m0_xfer>; ++ status = "okay"; ++}; +diff --git a/package/boot/uboot-rockchip/src/configs/nanopi-r6s-rk3588s_defconfig b/package/boot/uboot-rockchip/src/configs/nanopi-r6s-rk3588s_defconfig +new file mode 100644 +index 0000000000..1e38954075 +--- /dev/null ++++ b/configs/nanopi-r6s-rk3588s_defconfig +@@ -0,0 +1,68 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_COUNTER_FREQUENCY=24000000 ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y ++CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000 ++CONFIG_DEFAULT_DEVICE_TREE="rk3588s-nanopi-r6s" ++CONFIG_ROCKCHIP_RK3588=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3588=y ++CONFIG_SPL_STACK=0x400000 ++CONFIG_DEBUG_UART_BASE=0xFEB50000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_DEBUG_UART=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_BOARD_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3588s-nanopi-r6s.dtb" ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++CONFIG_SPL_MAX_SIZE=0x40000 ++CONFIG_SPL_PAD_TO=0x7f8000 ++CONFIG_SPL_HAS_BSS_LINKER_SECTION=y ++CONFIG_SPL_BSS_START_ADDR=0x4000000 ++CONFIG_SPL_BSS_MAX_SIZE=0x4000 ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_ATF=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_SUPPORT_EMMC_RPMB=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYS_NS16550_MEM32=y ++CONFIG_SYSRESET=y ++CONFIG_ERRNO_STR=y diff --git a/lede/package/boot/uboot-rockchip/patches/323-rockchip-rk3588s-Add-FriendlyElec-NanoPi-R6C.patch b/lede/package/boot/uboot-rockchip/patches/323-rockchip-rk3588s-Add-FriendlyElec-NanoPi-R6C.patch new file mode 100644 index 0000000000..16c1a2ec9a --- /dev/null +++ b/lede/package/boot/uboot-rockchip/patches/323-rockchip-rk3588s-Add-FriendlyElec-NanoPi-R6C.patch @@ -0,0 +1,99 @@ +--- /dev/null ++++ b/arch/arm/dts/rk3588s-nanopi-r6c-u-boot.dtsi +@@ -0,0 +1,3 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++ ++#include "rk3588s-nanopi-r6s-u-boot.dtsi" +--- /dev/null ++++ b/arch/arm/dts/rk3588s-nanopi-r6c.dts +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++ ++/dts-v1/; ++#include "rk3588s-nanopi-r6s.dts" ++ ++/ { ++ model = "FriendlyElec NanoPi R6C"; ++ compatible = "friendlyarm,nanopi-r6c", "rockchip,rk3588"; ++ ++ gpio-leds { ++ led-lan1 { ++ label = "green:lan"; ++ }; ++ ++ led-lan2 { ++ label = "green:user"; ++ }; ++ }; ++}; +--- /dev/null ++++ b/configs/nanopi-r6c-rk3588s_defconfig +@@ -0,0 +1,68 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_COUNTER_FREQUENCY=24000000 ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y ++CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000 ++CONFIG_DEFAULT_DEVICE_TREE="rk3588s-nanopi-r6c" ++CONFIG_ROCKCHIP_RK3588=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3588=y ++CONFIG_SPL_STACK=0x400000 ++CONFIG_DEBUG_UART_BASE=0xFEB50000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_DEBUG_UART=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_BOARD_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3588s-nanopi-r6c.dtb" ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++CONFIG_SPL_MAX_SIZE=0x40000 ++CONFIG_SPL_PAD_TO=0x7f8000 ++CONFIG_SPL_HAS_BSS_LINKER_SECTION=y ++CONFIG_SPL_BSS_START_ADDR=0x4000000 ++CONFIG_SPL_BSS_MAX_SIZE=0x4000 ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_ATF=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_SUPPORT_EMMC_RPMB=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYS_NS16550_MEM32=y ++CONFIG_SYSRESET=y ++CONFIG_ERRNO_STR=y diff --git a/lede/package/boot/uboot-rockchip/patches/324-rockchip-rk3588s-Add-FriendlyElec-NanoPC-T6.patch b/lede/package/boot/uboot-rockchip/patches/324-rockchip-rk3588s-Add-FriendlyElec-NanoPC-T6.patch new file mode 100644 index 0000000000..32775d798c --- /dev/null +++ b/lede/package/boot/uboot-rockchip/patches/324-rockchip-rk3588s-Add-FriendlyElec-NanoPC-T6.patch @@ -0,0 +1,896 @@ +--- /dev/null ++++ b/arch/arm/dts/rk3588-nanopc-t6-u-boot.dtsi +@@ -0,0 +1,31 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Copyright (c) 2023 Tianling Shen ++ */ ++ ++#include "rk3588-u-boot.dtsi" ++ ++/ { ++ aliases { ++ mmc0 = &sdmmc; ++ mmc1 = &sdhci; ++ }; ++ ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc, &sdhci; ++ }; ++}; ++ ++&rng { ++ status = "okay"; ++}; ++ ++&sdhci { ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs400-1_8v; ++ mmc-hs400-enhanced-strobe; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_data_strobe &emmc_rstnout>; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3588-nanopc-t6.dts +@@ -0,0 +1,785 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyelec.com) ++ * ++ * Copyright (c) 2023 Thomas McKahan ++ * Copyright (c) 2023 Tianling Shen ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++#include ++#include ++#include ++#include "rk3588.dtsi" ++ ++/ { ++ model = "FriendlyElec NanoPC T6"; ++ compatible = "friendlyarm,nanopc-t6", "rockchip,rk3588"; ++ ++ aliases { ++ mmc0 = &sdmmc; ++ mmc1 = &sdhci; ++ serial2 = &uart2; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&power_led_pin>, <&wan_led_pin>; ++ ++ power_led: led-power { ++ label = "red:power"; ++ gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ led-wan { ++ label = "green:wan"; ++ gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc5v0_usb: vcc5v0-usb-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ ++ vcc5v0_host_30: vcc5v0-host-30-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_host_30"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc5v0_usb>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_host30_en>; ++ }; ++ ++ vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_pcie2x1l0"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ enable-active-high; ++ gpio = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc5v0_sys>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie2_0_vcc3v3_en>; ++ }; ++ ++ vcc3v3_pcie30: vcc3v3-pcie30-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_pcie30"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ enable-active-high; ++ gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc5v0_sys>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie3_vcc3v3_en>; ++ }; ++ ++ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_1v1_nldo_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ ++ vcc_3v3_pcie20: vcc3v3-pcie20-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_3v3_pcie20"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3_s3>; ++ }; ++ ++ vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-max-microvolt = <3000000>; ++ regulator-min-microvolt = <3000000>; ++ regulator-name = "vcc_3v3_sd_s0"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc_3v3_s3>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc3v3_sd_en>; ++ }; ++ ++ vbus5v0_typec: vbus5v0-typec-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vbus5v0_typec"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc5v0_usb>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vbus5v0_typec_en>; ++ }; ++ ++ vdd_4glte_3v3: vdd-4glte-3v3-regulator { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vdd_4glte_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ enable-active-high; ++ gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>; ++ startup-delay-us = <10000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_big0_s0>; ++ mem-supply = <&vdd_cpu_big0_mem_s0>; ++}; ++ ++&cpu_b2 { ++ cpu-supply = <&vdd_cpu_big1_s0>; ++ mem-supply = <&vdd_cpu_big1_mem_s0>; ++}; ++ ++&gpio0 { ++ gpio-line-names = /* GPIO0 A0-A7 */ ++ "", "", "", "", ++ "", "", "", "", ++ /* GPIO0 B0-B7 */ ++ "", "", "", "", ++ "", "", "", "", ++ /* GPIO0 C0-C7 */ ++ "", "", "", "", ++ "HEADER_10", "HEADER_08", "HEADER_32", "", ++ /* GPIO0 D0-D7 */ ++ "", "", "", "", ++ "", "", "", ""; ++}; ++ ++&gpio1 { ++ gpio-line-names = /* GPIO1 A0-A7 */ ++ "HEADER_27", "HEADER_28", "", "", ++ "", "", "", "HEADER_15", ++ /* GPIO1 B0-B7 */ ++ "HEADER_26", "HEADER_21", "HEADER_19", "HEADER_23", ++ "HEADER_24", "HEADER_22", "", "", ++ /* GPIO1 C0-C7 */ ++ "", "", "", "", ++ "", "", "", "", ++ /* GPIO1 D0-D7 */ ++ "", "", "", "", ++ "", "", "HEADER_05", "HEADER_03"; ++}; ++ ++&gpio2 { ++ gpio-line-names = /* GPIO2 A0-A7 */ ++ "", "", "", "", ++ "", "", "", "", ++ /* GPIO2 B0-B7 */ ++ "", "", "", "", ++ "", "", "", "", ++ /* GPIO2 C0-C7 */ ++ "", "CSI1_11", "CSI1_12", "", ++ "", "", "", "", ++ /* GPIO2 D0-D7 */ ++ "", "", "", "", ++ "", "", "", ""; ++}; ++ ++&gpio3 { ++ gpio-line-names = /* GPIO3 A0-A7 */ ++ "HEADER_35", "HEADER_38", "HEADER_40", "HEADER_36", ++ "HEADER_37", "", "DSI0_12", "", ++ /* GPIO3 B0-B7 */ ++ "HEADER_33", "DSI0_10", "HEADER_07", "HEADER_16", ++ "HEADER_18", "HEADER_29", "HEADER_31", "HEADER_12", ++ /* GPIO3 C0-C7 */ ++ "DSI0_08", "DSI0_14", "HEADER_11", "HEADER_13", ++ "", "", "", "", ++ /* GPIO3 D0-D7 */ ++ "", "", "", "", ++ "", "DSI1_10", "", ""; ++}; ++ ++&gpio4 { ++ gpio-line-names = /* GPIO4 A0-A7 */ ++ "DSI1_08", "DSI1_14", "", "DSI1_12", ++ "", "", "", "", ++ /* GPIO4 B0-B7 */ ++ "", "", "", "", ++ "", "", "", "", ++ /* GPIO4 C0-C7 */ ++ "", "", "", "", ++ "CSI0_11", "CSI0_12", "", "", ++ /* GPIO4 D0-D7 */ ++ "", "", "", "", ++ "", "", "", ""; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0m2_xfer>; ++ status = "okay"; ++ ++ vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: regulator@42 { ++ compatible = "rockchip,rk8602"; ++ reg = <0x42>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu_big0_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: regulator@43 { ++ compatible = "rockchip,rk8603", "rockchip,rk8602"; ++ reg = <0x43>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu_big1_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++}; ++ ++&i2c6 { ++ status = "okay"; ++ ++ hym8563: rtc@51 { ++ compatible = "haoyu,hym8563"; ++ reg = <0x51>; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ clock-output-names = "hym8563"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hym8563_int>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ wakeup-source; ++ }; ++}; ++ ++&pinctrl { ++ gpio-leds { ++ power_led_pin: power-led-pin { ++ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ wan_led_pin: wan-led-pin { ++ rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ hym8563 { ++ hym8563_int: hym8563-int { ++ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ pcie2 { ++ pcie2_0_vcc3v3_en: pcie2-0-vcc-en { ++ rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pcie3 { ++ pcie3_vcc3v3_en: pcie3-vcc3v3-en { ++ rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ rockchip-key { ++ reset_button_pin: reset-button-pin { ++ rockchip,pins = <1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdmmc { ++ vcc3v3_sd_en: vcc3v3-sd-en { ++ rockchip,pins = <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ usbc0_int: usbc0-int { ++ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ vbus5v0_typec_en: vbus5v0-typec-en { ++ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ vcc5v0_host30_en: vcc5v0-host30-en { ++ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ }; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ max-frequency = <200000000>; ++ mmc-hs400-1_8v; ++ mmc-hs400-enhanced-strobe; ++ no-sdio; ++ no-sd; ++ non-removable; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ no-sdio; ++ no-mmc; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc_det>; ++ vmmc-supply = <&vcc_3v3_sd_s0>; ++ vqmmc-supply = <&vccio_sd_s0>; ++ status = "okay"; ++}; ++ ++&spi2 { ++ status = "okay"; ++ assigned-clocks = <&cru CLK_SPI2>; ++ assigned-clock-rates = <200000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; ++ num-cs = <1>; ++ ++ rk806single: rk806single@0 { ++ compatible = "rockchip,rk806"; ++ spi-max-frequency = <1000000>; ++ reg = <0x0>; ++ ++ interrupt-parent = <&gpio0>; ++ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, <&rk806_dvs2_null>, <&rk806_dvs3_null>; ++ ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc5-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc5v0_sys>; ++ vcc9-supply = <&vcc5v0_sys>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc_2v0_pldo_s3>; ++ vcc12-supply = <&vcc5v0_sys>; ++ vcc13-supply = <&vcc_1v1_nldo_s3>; ++ vcc14-supply = <&vcc_1v1_nldo_s3>; ++ vcca-supply = <&vcc5v0_sys>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ rk806_dvs1_null: dvs1-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs1_slp: dvs1-slp-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs1_pwrdn: dvs1-pwrdn-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs1_rst: dvs1-rst-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs2_null: dvs2-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs2_slp: dvs2-slp-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs2_pwrdn: dvs2-pwrdn-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs2_rst: dvs2-rst-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs2_dvs: dvs2-dvs-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_dvs2_gpio: dvs2-gpio-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun5"; ++ }; ++ ++ rk806_dvs3_null: dvs3-null-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs3_slp: dvs3-slp-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs3_pwrdn: dvs3-pwrdn-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs3_rst: dvs3-rst-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs3_dvs: dvs3-dvs-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_dvs3_gpio: dvs3-gpio-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun5"; ++ }; ++ ++ regulators { ++ vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_gpu_s0"; ++ regulator-enable-ramp-delay = <400>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_lit_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_log_s0: dcdc-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <750000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_log_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <750000>; ++ }; ++ }; ++ ++ vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-init-microvolt = <750000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_vdenc_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_ddr_s0: dcdc-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <900000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_ddr_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <850000>; ++ }; ++ }; ++ ++ vdd2_ddr_s3: dcdc-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vdd2_ddr_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_2v0_pldo_s3: dcdc-reg7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <2000000>; ++ regulator-max-microvolt = <2000000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_2v0_pldo_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <2000000>; ++ }; ++ }; ++ ++ vcc_3v3_s3: dcdc-reg8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc_3v3_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vddq_ddr_s0: dcdc-reg9 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vddq_ddr_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8_s3: dcdc-reg10 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ avcc_1v8_s0: pldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "avcc_1v8_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8_s0: pldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ avdd_1v2_s0: pldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-name = "avdd_1v2_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3_s0: pldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_3v3_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd_s0: pldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vccio_sd_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ pldo6_s3: pldo-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "pldo6_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_0v75_s3: nldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "vdd_0v75_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <750000>; ++ }; ++ }; ++ ++ vdd_ddr_pll_s0: nldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-name = "vdd_ddr_pll_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <850000>; ++ }; ++ }; ++ ++ avdd_0v75_s0: nldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "avdd_0v75_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_0v85_s0: nldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-name = "vdd_0v85_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_0v75_s0: nldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "vdd_0v75_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&uart2 { ++ pinctrl-0 = <&uart2m0_xfer>; ++ status = "okay"; ++}; +diff --git a/package/boot/uboot-rockchip/src/configs/nanopc-t6-rk3588_defconfig b/package/boot/uboot-rockchip/src/configs/nanopc-t6-rk3588_defconfig +new file mode 100644 +index 0000000000..e8b46cf744 +--- /dev/null ++++ b/configs/nanopc-t6-rk3588_defconfig +@@ -0,0 +1,68 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_COUNTER_FREQUENCY=24000000 ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y ++CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000 ++CONFIG_DEFAULT_DEVICE_TREE="rk3588-nanopc-t6" ++CONFIG_ROCKCHIP_RK3588=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3588=y ++CONFIG_SPL_STACK=0x400000 ++CONFIG_DEBUG_UART_BASE=0xFEB50000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_DEBUG_UART=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_BOARD_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3588-nanopc-t6.dtb" ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++CONFIG_SPL_MAX_SIZE=0x40000 ++CONFIG_SPL_PAD_TO=0x7f8000 ++CONFIG_SPL_HAS_BSS_LINKER_SECTION=y ++CONFIG_SPL_BSS_START_ADDR=0x4000000 ++CONFIG_SPL_BSS_MAX_SIZE=0x4000 ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_ATF=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_SUPPORT_EMMC_RPMB=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYS_NS16550_MEM32=y ++CONFIG_SYSRESET=y ++CONFIG_ERRNO_STR=y diff --git a/lede/package/firmware/ipq-wifi/Makefile b/lede/package/firmware/ipq-wifi/Makefile index b79ccf6475..97ee1ab84a 100644 --- a/lede/package/firmware/ipq-wifi/Makefile +++ b/lede/package/firmware/ipq-wifi/Makefile @@ -6,9 +6,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git -PKG_SOURCE_DATE:=2024-04-16 -PKG_SOURCE_VERSION:=1d51799e6768a304da7840b8346e7487efd77f49 -PKG_MIRROR_HASH:=9cf0917532283c1a1708643022a5ed1ec4af6bb9ebaff57fc2f0f2c229f2469e +PKG_SOURCE_DATE:=2024-10-08 +PKG_SOURCE_VERSION:=dcbab62272bf5cab2ed857bc655d240970e14f2a +PKG_MIRROR_HASH:=23fc47a0fd9f39defe272b9f5d5b08622e7762a57bc4830965972ee89d89f481 PKG_FLAGS:=nonshared diff --git a/lede/package/lean/autocore/files/luci-mod-status-autocore.json b/lede/package/lean/autocore/files/luci-mod-status-autocore.json index 5e2330a2da..6627667ebd 100644 --- a/lede/package/lean/autocore/files/luci-mod-status-autocore.json +++ b/lede/package/lean/autocore/files/luci-mod-status-autocore.json @@ -3,7 +3,7 @@ "description": "Grant access to autocore", "read": { "ubus": { - "luci": [ "getCPUInfo", "getTempInfo" ] + "luci": [ "getCPUInfo", "getCPUUsage", "getTempInfo" ] } } } diff --git a/lede/target/linux/qualcommax/Makefile b/lede/target/linux/qualcommax/Makefile index feafd5a950..92ddf3c402 100644 --- a/lede/target/linux/qualcommax/Makefile +++ b/lede/target/linux/qualcommax/Makefile @@ -18,6 +18,6 @@ DEFAULT_PACKAGES += \ kmod-qca-nss-ecm kmod-qca-nss-drv-bridge-mgr \ kmod-qca-nss-drv-vlan kmod-qca-nss-drv-pppoe \ kmod-ath11k-ahb wpad-openssl uboot-envtools \ - e2fsprogs f2fsck mkf2fs losetup automount + e2fsprogs f2fsck mkf2fs losetup automount autocore-arm $(eval $(call BuildTarget)) diff --git a/lede/target/linux/qualcommax/image/ipq60xx.mk b/lede/target/linux/qualcommax/image/ipq60xx.mk index 14c6f11e1c..249fbeff26 100644 --- a/lede/target/linux/qualcommax/image/ipq60xx.mk +++ b/lede/target/linux/qualcommax/image/ipq60xx.mk @@ -71,6 +71,7 @@ define Device/jdcloud_re-cs-02 BLOCKSIZE := 64k KERNEL_SIZE := 6144k DEVICE_DTS_CONFIG := config@cp03-c3 + SUPPORTED_DEVICES += jdcloud,ax6600 DEVICE_PACKAGES := ipq-wifi-jdcloud_ax6600 kmod-ath11k-pci ath11k-firmware-qcn9074 endef TARGET_DEVICES += jdcloud_re-cs-02 @@ -84,6 +85,7 @@ define Device/jdcloud_re-ss-01 BLOCKSIZE := 64k KERNEL_SIZE := 6144k DEVICE_DTS_CONFIG := config@cp03-c2 + SUPPORTED_DEVICES += jdcloud,ax1800-pro DEVICE_PACKAGES := ipq-wifi-jdcloud_ax1800pro endef TARGET_DEVICES += jdcloud_re-ss-01 diff --git a/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts new file mode 100644 index 0000000000..43885caa12 --- /dev/null +++ b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -0,0 +1,857 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include "rk3588.dtsi" + +/ { + model = "Radxa ROCK 5B"; + compatible = "radxa,rock-5b", "rockchip,rk3588"; + + aliases { + mmc0 = &sdhci; + mmc1 = &sdmmc; + mmc2 = &sdio; + + led-boot = &status_led; + led-failsafe = &status_led; + led-running = &status_led; + led-upgrade = &status_led; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + analog-sound { + compatible = "audio-graph-card"; + label = "rk3588-es8316"; + + widgets = "Microphone", "Mic Jack", + "Headphone", "Headphones"; + + routing = "MIC2", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR"; + + dais = <&i2s0_8ch_p0>; + hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_detect>; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_rgb_b>; + + status_led: led_rgb_b { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + cooling-levels = <0 120 150 180 210 240 255>; + fan-supply = <&vcc5v0_sys>; + pwms = <&pwm1 0 50000 0>; + #cooling-cells = <2>; + }; + + rfkill { + compatible = "rfkill-gpio"; + label = "rfkill-pcie-wlan"; + radio-type = "wlan"; + shutdown-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + }; + + vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_0_vcc3v3_en>; + regulator-name = "vcc3v3_pcie2x1l0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <50000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie2x1l2"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <5000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc3v3_pcie30: vcc3v3-pcie30-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_vcc3v3_en>; + regulator-name = "vcc3v3_pcie30"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <5000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c6 { + status = "okay"; + + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + interrupt-parent = <&gpio0>; + interrupts = ; + wakeup-source; + }; +}; + +&i2c7 { + status = "okay"; + + es8316: audio-codec@11 { + compatible = "everest,es8316"; + reg = <0x11>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + clock-names = "mclk"; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + assigned-clock-rates = <12288000>; + #sound-dai-cells = <0>; + + port { + es8316_p0_0: endpoint { + remote-endpoint = <&i2s0_8ch_p0_0>; + }; + }; + }; +}; + +&i2s0_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_lrck + &i2s0_mclk + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; + status = "okay"; + + i2s0_8ch_p0: port { + i2s0_8ch_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&es8316_p0_0>; + }; + }; +}; + +&package_thermal { + polling-delay = <1000>; + + trips { + package_fan0: package-fan0 { + temperature = <55000>; + hysteresis = <2000>; + type = "active"; + }; + + package_fan1: package-fan1 { + temperature = <65000>; + hysteresis = <2000>; + type = "active"; + }; + }; + + cooling-maps { + map1 { + trip = <&package_fan0>; + cooling-device = <&fan THERMAL_NO_LIMIT 1>; + }; + + map2 { + trip = <&package_fan1>; + cooling-device = <&fan 2 THERMAL_NO_LIMIT>; + }; + }; +}; + +&pcie2x1l0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_0_rst>; + reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie2x1l0>; + status = "okay"; +}; + +&pcie2x1l2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_2_rst>; + reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie2x1l2>; + status = "okay"; +}; + +&pcie30phy { + status = "okay"; +}; + +&pcie3x4 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_rst>; + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie30>; + status = "okay"; +}; + +&pinctrl { + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + leds { + led_rgb_b: led-rgb-b { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sound { + hp_detect: hp-detect { + rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie2 { + pcie2_0_rst: pcie2-0-rst { + rockchip,pins = <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie2_0_vcc3v3_en: pcie2-0-vcc-en { + rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie2_2_rst: pcie2-2-rst { + rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie3 { + pcie3_rst: pcie3-rst { + rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie3_vcc3v3_en: pcie3-vcc3v3-en { + rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + status = "okay"; +}; + +&sdmmc { + max-frequency = <200000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + sd-uhs-sdr50; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&sdio { + max-frequency = <200000000>; + no-sd; + no-mmc; + non-removable; + bus-width = <4>; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + wakeup-source; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_pcie2x1l0>; + vqmmc-supply = <&vcc_1v8_s3>; + pinctrl-names = "default"; + pinctrl-0 = <&sdiom0_pins>; + status = "okay"; +}; + +&sfc { + pinctrl-names = "default"; + pinctrl-0 = <&fspim2_pins>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <104000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&uart6 { + pinctrl-names = "default"; + pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>; + status = "okay"; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + num-cs = <1>; + + pmic@0 { + compatible = "rockchip,rk806"; + spi-max-frequency = <1000000>; + reg = <0x0>; + + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + + system-power-controller; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_2v0_pldo_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "avcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "avdd_1v2_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_sd_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "pldo6_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_ddr_pll_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy1_otg { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy2_host { + /* connected to USB hub, which is powered by vcc5v0_sys */ + phy-supply = <&vcc5v0_sys>; + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usbdp_phy1 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usb_host2_xhci { + status = "okay"; +}; diff --git a/lede/target/linux/rockchip/image/armv8.mk b/lede/target/linux/rockchip/image/armv8.mk index e983734e4c..969e2ad321 100644 --- a/lede/target/linux/rockchip/image/armv8.mk +++ b/lede/target/linux/rockchip/image/armv8.mk @@ -123,6 +123,16 @@ define Device/friendlyarm_nanopi-neo3 endef TARGET_DEVICES += friendlyarm_nanopi-neo3 +define Device/friendlyarm_nanopc-t6 + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPC T6 + SOC := rk3588 + UBOOT_DEVICE_NAME := nanopc-t6-rk3588 + IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8125-rss +endef +TARGET_DEVICES += friendlyarm_nanopc-t6 + define Device/friendlyarm_nanopi-r2c DEVICE_VENDOR := FriendlyARM DEVICE_MODEL := NanoPi R2C @@ -183,6 +193,26 @@ define Device/friendlyarm_nanopi-r5s endef TARGET_DEVICES += friendlyarm_nanopi-r5s +define Device/friendlyarm_nanopi-r6c + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPi R6C + SOC := rk3588s + UBOOT_DEVICE_NAME := nanopi-r6c-rk3588s + IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8125-rss +endef +TARGET_DEVICES += friendlyarm_nanopi-r6c + +define Device/friendlyarm_nanopi-r6s + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPi R6S + SOC := rk3588s + UBOOT_DEVICE_NAME := nanopi-r6s-rk3588s + IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8125-rss +endef +TARGET_DEVICES += friendlyarm_nanopi-r6s + define Device/firefly_station-p2 DEVICE_VENDOR := Firefly DEVICE_MODEL := Station P2 @@ -323,6 +353,16 @@ define Device/radxa_rock-pi-4 endef TARGET_DEVICES += radxa_rock-pi-4 +define Device/radxa_rock-5b + DEVICE_VENDOR := Radxa + DEVICE_MODEL := ROCK 5B + SOC := rk3588 + UBOOT_DEVICE_NAME := rock5b-rk3588 + IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8125-rss kmod-hwmon-pwmfan +endef +TARGET_DEVICES += radxa_rock-5b + define Device/rongpin_king3399 DEVICE_VENDOR := Rongpin DEVICE_MODEL := King3399 diff --git a/lede/target/linux/rockchip/patches-6.6/050-08-v6.8-arm64-dts-rockchip-move-rk3588-serial-aliases-to-soc-dtsi.patch b/lede/target/linux/rockchip/patches-6.6/050-08-v6.8-arm64-dts-rockchip-move-rk3588-serial-aliases-to-soc-dtsi.patch index fda9d09def..3d7f3d8547 100644 --- a/lede/target/linux/rockchip/patches-6.6/050-08-v6.8-arm64-dts-rockchip-move-rk3588-serial-aliases-to-soc-dtsi.patch +++ b/lede/target/linux/rockchip/patches-6.6/050-08-v6.8-arm64-dts-rockchip-move-rk3588-serial-aliases-to-soc-dtsi.patch @@ -20,7 +20,6 @@ Link: https://lore.kernel.org/r/20231205164842.556684-2-heiko@sntech.de arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts | 1 - .../boot/dts/rockchip/rk3588-orangepi-5-plus.dts | 1 - arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts | 1 - - arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 1 - arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 2 -- .../boot/dts/rockchip/rk3588s-indiedroid-nova.dts | 1 - .../boot/dts/rockchip/rk3588s-khadas-edge2.dts | 1 - @@ -64,16 +63,6 @@ Link: https://lore.kernel.org/r/20231205164842.556684-2-heiko@sntech.de - serial2 = &uart2; }; - chosen { ---- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -@@ -12,7 +12,6 @@ - aliases { - mmc0 = &sdhci; - mmc1 = &sdmmc; -- serial2 = &uart2; - }; - chosen { --- a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts diff --git a/mihomo/go.mod b/mihomo/go.mod index a223cf77ac..098030629a 100644 --- a/mihomo/go.mod +++ b/mihomo/go.mod @@ -20,12 +20,12 @@ require ( github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 github.com/metacubex/chacha v0.1.0 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 - github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4 + github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174 github.com/metacubex/randv2 v0.2.0 github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 github.com/metacubex/sing-shadowsocks v0.2.8 github.com/metacubex/sing-shadowsocks2 v0.2.2 - github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1 + github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3 github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa @@ -39,7 +39,7 @@ require ( github.com/sagernet/cors v1.2.1 github.com/sagernet/fswatch v0.1.1 github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a - github.com/sagernet/sing v0.5.0-alpha.13 + github.com/sagernet/sing v0.5.0-rc.4 github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 github.com/sagernet/sing-shadowtls v0.1.4 github.com/samber/lo v1.47.0 @@ -116,4 +116,4 @@ require ( golang.org/x/tools v0.24.0 // indirect ) -replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297 +replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a diff --git a/mihomo/go.sum b/mihomo/go.sum index 2b3bba6542..0508ac59ce 100644 --- a/mihomo/go.sum +++ b/mihomo/go.sum @@ -104,20 +104,20 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw= -github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4 h1:CgdUBRxmNlxEGkp35HwvgQ10jwOOUJKWdOxpi8yWi8o= -github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4/go.mod h1:Y7yRGqFE6UQL/3aKPYmiYdjfVkeujJaStP4+jiZMcN8= +github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174 h1:GvigRPEU+cbnzdLWne47cxLrc28Abohl3ECtVdnrbq0= +github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174/go.mod h1:AiZ+UPgrkO1DTnmiAX4b+kRoV1Vfc65UkYD7RbFlIZA= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= -github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297 h1:YG/JkwGPbca5rUtEMHIu8ZuqzR7BSVm1iqY8hNoMeMA= -github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a h1:JuR0/7RDxQtlZp/GOzrdqNq04HplTxavPRHrek8ouJk= +github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 h1:HobpULaPK6OoxrHMmgcwLkwwIduXVmwdcznwUfH1GQM= github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8= github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4= github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0= github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo= github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q= -github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1 h1:ypfofGDZbP8p3Y4P/m74JYu7sQViesi3c8nbmT6cS0Y= -github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1/go.mod h1:olbEx9yVcaw5tHTNlRamRoxmMKcvDvcVS1YLnQGzvWE= +github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c h1:qfUZ8xBrViOCZamvcC8CyV7Ii8sAUrn7RqZxFGn56tQ= +github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c/go.mod h1:lCrP0AW7ieKnXG1JEeZLW+9h99QzjuOX0MfCQfz6TgE= github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I= github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY= github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3 h1:xg71VmzLS6ByAzi/57phwDvjE+dLLs+ozH00k4DnOns= diff --git a/mihomo/listener/sing_tun/server.go b/mihomo/listener/sing_tun/server.go index 79856c466c..ad3d113e4a 100644 --- a/mihomo/listener/sing_tun/server.go +++ b/mihomo/listener/sing_tun/server.go @@ -279,7 +279,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis return } - defaultInterfaceMonitor, err = tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{OverrideAndroidVPN: true}) + defaultInterfaceMonitor, err = tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{InterfaceFinder: interfaceFinder, OverrideAndroidVPN: true}) if err != nil { err = E.Cause(err, "create DefaultInterfaceMonitor") return diff --git a/shadowsocks-rust/debian/compat b/shadowsocks-rust/debian/compat index ec635144f6..f599e28b8a 100644 --- a/shadowsocks-rust/debian/compat +++ b/shadowsocks-rust/debian/compat @@ -1 +1 @@ -9 +10 diff --git a/shadowsocks-rust/debian/control b/shadowsocks-rust/debian/control index 94d0284728..ea233796f0 100644 --- a/shadowsocks-rust/debian/control +++ b/shadowsocks-rust/debian/control @@ -2,7 +2,7 @@ Source: shadowsocks-rust Section: net Priority: optional Maintainer: Y. T. Chung -Build-Depends: debhelper (>=9), rustc, cargo, apg | pwgen, libcap2-bin [linux-any] +Build-Depends: debhelper (>=9), rustc, cargo, libcap2-bin [linux-any] Standards-Version: 3.9.6 Homepage: https://github.com/shadowsocks/shadowsocks-rust diff --git a/shadowsocks-rust/debian/shadowsocks-rust-local@.service b/shadowsocks-rust/debian/shadowsocks-rust-local@.service index 05a99643b5..ec609b92ae 100644 --- a/shadowsocks-rust/debian/shadowsocks-rust-local@.service +++ b/shadowsocks-rust/debian/shadowsocks-rust-local@.service @@ -13,6 +13,7 @@ After=network.target Type=simple CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE +DynamicUser=yes ExecStart=/usr/bin/ssservice local --log-without-time -c /etc/shadowsocks-rust/%i.json [Install] diff --git a/shadowsocks-rust/debian/shadowsocks-rust-server@.service b/shadowsocks-rust/debian/shadowsocks-rust-server@.service index 0f129e782e..73f59d561d 100644 --- a/shadowsocks-rust/debian/shadowsocks-rust-server@.service +++ b/shadowsocks-rust/debian/shadowsocks-rust-server@.service @@ -13,6 +13,7 @@ After=network.target Type=simple CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE +DynamicUser=yes ExecStart=/usr/bin/ssservice server --log-without-time -c /etc/shadowsocks-rust/%i.json [Install] diff --git a/shadowsocks-rust/debian/shadowsocks-rust.postinst b/shadowsocks-rust/debian/shadowsocks-rust.postinst index 12fc0bbb60..e8a2be7e24 100644 --- a/shadowsocks-rust/debian/shadowsocks-rust.postinst +++ b/shadowsocks-rust/debian/shadowsocks-rust.postinst @@ -27,8 +27,7 @@ case "$1" in if [ ! -f /etc/shadowsocks-rust/config.json ]; then set +e passwd=$(/usr/bin/ssservice genkey -m "chacha20-ietf-poly1305") - passwd="${passwd//+/\\+}" - passwd="${passwd//\//\\/}" + passwd=$(echo $passwd | sed "s/+/\\\\+/g" | sed "s/\\//\\\\\\//g") set -e mkdir -p /etc/shadowsocks-rust sed "s/barfoo/$passwd/" /usr/share/shadowsocks-rust/config.json \ diff --git a/shadowsocks-rust/debian/shadowsocks-rust.service b/shadowsocks-rust/debian/shadowsocks-rust.service index af56887d7e..f4b807d43e 100644 --- a/shadowsocks-rust/debian/shadowsocks-rust.service +++ b/shadowsocks-rust/debian/shadowsocks-rust.service @@ -11,8 +11,7 @@ After=network.target [Service] Type=simple EnvironmentFile=/etc/default/shadowsocks-rust -User=nobody -Group=nogroup +DynamicUser=yes LimitNOFILE=32768 ExecStart=/usr/bin/ssservice server -c ${CONFFILE} ${DAEMON_ARGS} diff --git a/sing-box/adapter/conn_router.go b/sing-box/adapter/conn_router.go deleted file mode 100644 index a87c45e8c5..0000000000 --- a/sing-box/adapter/conn_router.go +++ /dev/null @@ -1,104 +0,0 @@ -package adapter - -import ( - "context" - "net" - - "github.com/sagernet/sing/common/logger" - M "github.com/sagernet/sing/common/metadata" - N "github.com/sagernet/sing/common/network" -) - -type ConnectionRouter interface { - RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error - RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error -} - -func NewRouteHandler( - metadata InboundContext, - router ConnectionRouter, - logger logger.ContextLogger, -) UpstreamHandlerAdapter { - return &routeHandlerWrapper{ - metadata: metadata, - router: router, - logger: logger, - } -} - -func NewRouteContextHandler( - router ConnectionRouter, - logger logger.ContextLogger, -) UpstreamHandlerAdapter { - return &routeContextHandlerWrapper{ - router: router, - logger: logger, - } -} - -var _ UpstreamHandlerAdapter = (*routeHandlerWrapper)(nil) - -type routeHandlerWrapper struct { - metadata InboundContext - router ConnectionRouter - logger logger.ContextLogger -} - -func (w *routeHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { - myMetadata := w.metadata - if metadata.Source.IsValid() { - myMetadata.Source = metadata.Source - } - if metadata.Destination.IsValid() { - myMetadata.Destination = metadata.Destination - } - return w.router.RouteConnection(ctx, conn, myMetadata) -} - -func (w *routeHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { - myMetadata := w.metadata - if metadata.Source.IsValid() { - myMetadata.Source = metadata.Source - } - if metadata.Destination.IsValid() { - myMetadata.Destination = metadata.Destination - } - return w.router.RoutePacketConnection(ctx, conn, myMetadata) -} - -func (w *routeHandlerWrapper) NewError(ctx context.Context, err error) { - w.logger.ErrorContext(ctx, err) -} - -var _ UpstreamHandlerAdapter = (*routeContextHandlerWrapper)(nil) - -type routeContextHandlerWrapper struct { - router ConnectionRouter - logger logger.ContextLogger -} - -func (w *routeContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { - myMetadata := ContextFrom(ctx) - if metadata.Source.IsValid() { - myMetadata.Source = metadata.Source - } - if metadata.Destination.IsValid() { - myMetadata.Destination = metadata.Destination - } - return w.router.RouteConnection(ctx, conn, *myMetadata) -} - -func (w *routeContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { - myMetadata := ContextFrom(ctx) - if metadata.Source.IsValid() { - myMetadata.Source = metadata.Source - } - if metadata.Destination.IsValid() { - myMetadata.Destination = metadata.Destination - } - return w.router.RoutePacketConnection(ctx, conn, *myMetadata) -} - -func (w *routeContextHandlerWrapper) NewError(ctx context.Context, err error) { - w.logger.ErrorContext(ctx, err) -} diff --git a/sing-box/adapter/handler.go b/sing-box/adapter/handler.go index bc5bcfbb02..6da158ab20 100644 --- a/sing-box/adapter/handler.go +++ b/sing-box/adapter/handler.go @@ -6,27 +6,53 @@ import ( "github.com/sagernet/sing/common/buf" E "github.com/sagernet/sing/common/exceptions" + M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" ) +// Deprecated type ConnectionHandler interface { NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error } +type ConnectionHandlerEx interface { + NewConnectionEx(ctx context.Context, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc) +} + +// Deprecated: use PacketHandlerEx instead type PacketHandler interface { NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata InboundContext) error } +type PacketHandlerEx interface { + NewPacketEx(buffer *buf.Buffer, source M.Socksaddr) +} + +// Deprecated: use OOBPacketHandlerEx instead type OOBPacketHandler interface { NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, oob []byte, metadata InboundContext) error } +type OOBPacketHandlerEx interface { + NewPacketEx(buffer *buf.Buffer, oob []byte, source M.Socksaddr) +} + +// Deprecated type PacketConnectionHandler interface { NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error } +type PacketConnectionHandlerEx interface { + NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc) +} + type UpstreamHandlerAdapter interface { N.TCPConnectionHandler N.UDPConnectionHandler E.Handler } + +type UpstreamHandlerAdapterEx interface { + N.TCPConnectionHandlerEx + N.UDPConnectionHandlerEx +} diff --git a/sing-box/adapter/inbound.go b/sing-box/adapter/inbound.go index ffc4c56454..9c7646a586 100644 --- a/sing-box/adapter/inbound.go +++ b/sing-box/adapter/inbound.go @@ -2,13 +2,11 @@ package adapter import ( "context" - "net" "net/netip" "github.com/sagernet/sing-box/common/process" "github.com/sagernet/sing-box/option" M "github.com/sagernet/sing/common/metadata" - N "github.com/sagernet/sing/common/network" ) type Inbound interface { @@ -17,11 +15,14 @@ type Inbound interface { Tag() string } -type InjectableInbound interface { +type TCPInjectableInbound interface { Inbound - Network() []string - NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error - NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error + ConnectionHandlerEx +} + +type UDPInjectableInbound interface { + Inbound + PacketConnectionHandlerEx } type InboundContext struct { @@ -43,16 +44,18 @@ type InboundContext struct { // cache - InboundDetour string - LastInbound string - OriginDestination M.Socksaddr - InboundOptions option.InboundOptions - DestinationAddresses []netip.Addr - SourceGeoIPCode string - GeoIPCode string - ProcessInfo *process.Info - QueryType uint16 - FakeIP bool + InboundDetour string + LastInbound string + OriginDestination M.Socksaddr + // Deprecated + InboundOptions option.InboundOptions + UDPDisableDomainUnmapping bool + DestinationAddresses []netip.Addr + SourceGeoIPCode string + GeoIPCode string + ProcessInfo *process.Info + QueryType uint16 + FakeIP bool // rule cache diff --git a/sing-box/adapter/outbound.go b/sing-box/adapter/outbound.go index b6980fb97c..312cdf3ed0 100644 --- a/sing-box/adapter/outbound.go +++ b/sing-box/adapter/outbound.go @@ -1,9 +1,6 @@ package adapter import ( - "context" - "net" - N "github.com/sagernet/sing/common/network" ) @@ -15,6 +12,4 @@ type Outbound interface { Network() []string Dependencies() []string N.Dialer - NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error - NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error } diff --git a/sing-box/adapter/router.go b/sing-box/adapter/router.go index 619c1110cb..023fcf14ee 100644 --- a/sing-box/adapter/router.go +++ b/sing-box/adapter/router.go @@ -2,6 +2,7 @@ package adapter import ( "context" + "net" "net/http" "net/netip" @@ -30,6 +31,7 @@ type Router interface { FakeIPStore() FakeIPStore ConnectionRouter + ConnectionRouterEx GeoIPReader() *geoip.Reader LoadGeosite(code string) (Rule, error) @@ -66,6 +68,18 @@ type Router interface { ResetNetwork() error } +// Deprecated: Use ConnectionRouterEx instead. +type ConnectionRouter interface { + RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error + RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error +} + +type ConnectionRouterEx interface { + ConnectionRouter + RouteConnectionEx(ctx context.Context, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc) + RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc) +} + func ContextWithRouter(ctx context.Context, router Router) context.Context { return service.ContextWith(ctx, router) } @@ -74,28 +88,6 @@ func RouterFromContext(ctx context.Context) Router { return service.FromContext[Router](ctx) } -type HeadlessRule interface { - Match(metadata *InboundContext) bool - String() string -} - -type Rule interface { - HeadlessRule - Service - Type() string - UpdateGeosite() error - Outbound() string -} - -type DNSRule interface { - Rule - DisableCache() bool - RewriteTTL() *uint32 - ClientSubnet() *netip.Prefix - WithAddressLimit() bool - MatchAddressLimit(metadata *InboundContext) bool -} - type RuleSet interface { Name() string StartContext(ctx context.Context, startContext RuleSetStartContext) error diff --git a/sing-box/adapter/rule.go b/sing-box/adapter/rule.go new file mode 100644 index 0000000000..f3737a25de --- /dev/null +++ b/sing-box/adapter/rule.go @@ -0,0 +1,38 @@ +package adapter + +import ( + C "github.com/sagernet/sing-box/constant" +) + +type HeadlessRule interface { + Match(metadata *InboundContext) bool + String() string +} + +type Rule interface { + HeadlessRule + Service + Type() string + UpdateGeosite() error + Action() RuleAction +} + +type DNSRule interface { + Rule + WithAddressLimit() bool + MatchAddressLimit(metadata *InboundContext) bool +} + +type RuleAction interface { + Type() string + String() string +} + +func IsFinalAction(action RuleAction) bool { + switch action.Type() { + case C.RuleActionTypeSniff, C.RuleActionTypeResolve: + return false + default: + return true + } +} diff --git a/sing-box/adapter/upstream.go b/sing-box/adapter/upstream.go index 95dd98ea1b..8b0d7c035b 100644 --- a/sing-box/adapter/upstream.go +++ b/sing-box/adapter/upstream.go @@ -4,112 +4,165 @@ import ( "context" "net" - E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" ) type ( - ConnectionHandlerFunc = func(ctx context.Context, conn net.Conn, metadata InboundContext) error - PacketConnectionHandlerFunc = func(ctx context.Context, conn N.PacketConn, metadata InboundContext) error + ConnectionHandlerFuncEx = func(ctx context.Context, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc) + PacketConnectionHandlerFuncEx = func(ctx context.Context, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc) ) -func NewUpstreamHandler( +func NewUpstreamHandlerEx( metadata InboundContext, - connectionHandler ConnectionHandlerFunc, - packetHandler PacketConnectionHandlerFunc, - errorHandler E.Handler, -) UpstreamHandlerAdapter { - return &myUpstreamHandlerWrapper{ + connectionHandler ConnectionHandlerFuncEx, + packetHandler PacketConnectionHandlerFuncEx, +) UpstreamHandlerAdapterEx { + return &myUpstreamHandlerWrapperEx{ metadata: metadata, connectionHandler: connectionHandler, packetHandler: packetHandler, - errorHandler: errorHandler, } } -var _ UpstreamHandlerAdapter = (*myUpstreamHandlerWrapper)(nil) +var _ UpstreamHandlerAdapterEx = (*myUpstreamHandlerWrapperEx)(nil) -type myUpstreamHandlerWrapper struct { +type myUpstreamHandlerWrapperEx struct { metadata InboundContext - connectionHandler ConnectionHandlerFunc - packetHandler PacketConnectionHandlerFunc - errorHandler E.Handler + connectionHandler ConnectionHandlerFuncEx + packetHandler PacketConnectionHandlerFuncEx } -func (w *myUpstreamHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { +func (w *myUpstreamHandlerWrapperEx) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { myMetadata := w.metadata - if metadata.Source.IsValid() { - myMetadata.Source = metadata.Source + if source.IsValid() { + myMetadata.Source = source } - if metadata.Destination.IsValid() { - myMetadata.Destination = metadata.Destination + if destination.IsValid() { + myMetadata.Destination = destination } - return w.connectionHandler(ctx, conn, myMetadata) + w.connectionHandler(ctx, conn, myMetadata, onClose) } -func (w *myUpstreamHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { +func (w *myUpstreamHandlerWrapperEx) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { myMetadata := w.metadata - if metadata.Source.IsValid() { - myMetadata.Source = metadata.Source + if source.IsValid() { + myMetadata.Source = source } - if metadata.Destination.IsValid() { - myMetadata.Destination = metadata.Destination + if destination.IsValid() { + myMetadata.Destination = destination } - return w.packetHandler(ctx, conn, myMetadata) + w.packetHandler(ctx, conn, myMetadata, onClose) } -func (w *myUpstreamHandlerWrapper) NewError(ctx context.Context, err error) { - w.errorHandler.NewError(ctx, err) +var _ UpstreamHandlerAdapterEx = (*myUpstreamContextHandlerWrapperEx)(nil) + +type myUpstreamContextHandlerWrapperEx struct { + connectionHandler ConnectionHandlerFuncEx + packetHandler PacketConnectionHandlerFuncEx } -func UpstreamMetadata(metadata InboundContext) M.Metadata { - return M.Metadata{ - Source: metadata.Source, - Destination: metadata.Destination, - } -} - -type myUpstreamContextHandlerWrapper struct { - connectionHandler ConnectionHandlerFunc - packetHandler PacketConnectionHandlerFunc - errorHandler E.Handler -} - -func NewUpstreamContextHandler( - connectionHandler ConnectionHandlerFunc, - packetHandler PacketConnectionHandlerFunc, - errorHandler E.Handler, -) UpstreamHandlerAdapter { - return &myUpstreamContextHandlerWrapper{ +func NewUpstreamContextHandlerEx( + connectionHandler ConnectionHandlerFuncEx, + packetHandler PacketConnectionHandlerFuncEx, +) UpstreamHandlerAdapterEx { + return &myUpstreamContextHandlerWrapperEx{ connectionHandler: connectionHandler, packetHandler: packetHandler, - errorHandler: errorHandler, } } -func (w *myUpstreamContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { +func (w *myUpstreamContextHandlerWrapperEx) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { myMetadata := ContextFrom(ctx) - if metadata.Source.IsValid() { - myMetadata.Source = metadata.Source + if source.IsValid() { + myMetadata.Source = source } - if metadata.Destination.IsValid() { - myMetadata.Destination = metadata.Destination + if destination.IsValid() { + myMetadata.Destination = destination } - return w.connectionHandler(ctx, conn, *myMetadata) + w.connectionHandler(ctx, conn, *myMetadata, onClose) } -func (w *myUpstreamContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { +func (w *myUpstreamContextHandlerWrapperEx) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { myMetadata := ContextFrom(ctx) - if metadata.Source.IsValid() { - myMetadata.Source = metadata.Source + if source.IsValid() { + myMetadata.Source = source } - if metadata.Destination.IsValid() { - myMetadata.Destination = metadata.Destination + if destination.IsValid() { + myMetadata.Destination = destination } - return w.packetHandler(ctx, conn, *myMetadata) + w.packetHandler(ctx, conn, *myMetadata, onClose) } -func (w *myUpstreamContextHandlerWrapper) NewError(ctx context.Context, err error) { - w.errorHandler.NewError(ctx, err) +func NewRouteHandlerEx( + metadata InboundContext, + router ConnectionRouterEx, +) UpstreamHandlerAdapterEx { + return &routeHandlerWrapperEx{ + metadata: metadata, + router: router, + } +} + +var _ UpstreamHandlerAdapterEx = (*routeHandlerWrapperEx)(nil) + +type routeHandlerWrapperEx struct { + metadata InboundContext + router ConnectionRouterEx +} + +func (r *routeHandlerWrapperEx) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + if source.IsValid() { + r.metadata.Source = source + } + if destination.IsValid() { + r.metadata.Destination = destination + } + r.router.RouteConnectionEx(ctx, conn, r.metadata, onClose) +} + +func (r *routeHandlerWrapperEx) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + if source.IsValid() { + r.metadata.Source = source + } + if destination.IsValid() { + r.metadata.Destination = destination + } + r.router.RoutePacketConnectionEx(ctx, conn, r.metadata, onClose) +} + +func NewRouteContextHandlerEx( + router ConnectionRouterEx, +) UpstreamHandlerAdapterEx { + return &routeContextHandlerWrapperEx{ + router: router, + } +} + +var _ UpstreamHandlerAdapterEx = (*routeContextHandlerWrapperEx)(nil) + +type routeContextHandlerWrapperEx struct { + router ConnectionRouterEx +} + +func (r *routeContextHandlerWrapperEx) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + metadata := ContextFrom(ctx) + if source.IsValid() { + metadata.Source = source + } + if destination.IsValid() { + metadata.Destination = destination + } + r.router.RouteConnectionEx(ctx, conn, *metadata, onClose) +} + +func (r *routeContextHandlerWrapperEx) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + metadata := ContextFrom(ctx) + if source.IsValid() { + metadata.Source = source + } + if destination.IsValid() { + metadata.Destination = destination + } + r.router.RoutePacketConnectionEx(ctx, conn, *metadata, onClose) } diff --git a/sing-box/adapter/upstream_legacy.go b/sing-box/adapter/upstream_legacy.go new file mode 100644 index 0000000000..1c6c15c017 --- /dev/null +++ b/sing-box/adapter/upstream_legacy.go @@ -0,0 +1,216 @@ +package adapter + +import ( + "context" + "net" + + E "github.com/sagernet/sing/common/exceptions" + "github.com/sagernet/sing/common/logger" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" +) + +type ( + // Deprecated + ConnectionHandlerFunc = func(ctx context.Context, conn net.Conn, metadata InboundContext) error + // Deprecated + PacketConnectionHandlerFunc = func(ctx context.Context, conn N.PacketConn, metadata InboundContext) error +) + +// Deprecated +func NewUpstreamHandler( + metadata InboundContext, + connectionHandler ConnectionHandlerFunc, + packetHandler PacketConnectionHandlerFunc, + errorHandler E.Handler, +) UpstreamHandlerAdapter { + return &myUpstreamHandlerWrapper{ + metadata: metadata, + connectionHandler: connectionHandler, + packetHandler: packetHandler, + errorHandler: errorHandler, + } +} + +var _ UpstreamHandlerAdapter = (*myUpstreamHandlerWrapper)(nil) + +// Deprecated +type myUpstreamHandlerWrapper struct { + metadata InboundContext + connectionHandler ConnectionHandlerFunc + packetHandler PacketConnectionHandlerFunc + errorHandler E.Handler +} + +func (w *myUpstreamHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + myMetadata := w.metadata + if metadata.Source.IsValid() { + myMetadata.Source = metadata.Source + } + if metadata.Destination.IsValid() { + myMetadata.Destination = metadata.Destination + } + return w.connectionHandler(ctx, conn, myMetadata) +} + +func (w *myUpstreamHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { + myMetadata := w.metadata + if metadata.Source.IsValid() { + myMetadata.Source = metadata.Source + } + if metadata.Destination.IsValid() { + myMetadata.Destination = metadata.Destination + } + return w.packetHandler(ctx, conn, myMetadata) +} + +func (w *myUpstreamHandlerWrapper) NewError(ctx context.Context, err error) { + w.errorHandler.NewError(ctx, err) +} + +// Deprecated +func UpstreamMetadata(metadata InboundContext) M.Metadata { + return M.Metadata{ + Source: metadata.Source, + Destination: metadata.Destination, + } +} + +// Deprecated +type myUpstreamContextHandlerWrapper struct { + connectionHandler ConnectionHandlerFunc + packetHandler PacketConnectionHandlerFunc + errorHandler E.Handler +} + +// Deprecated +func NewUpstreamContextHandler( + connectionHandler ConnectionHandlerFunc, + packetHandler PacketConnectionHandlerFunc, + errorHandler E.Handler, +) UpstreamHandlerAdapter { + return &myUpstreamContextHandlerWrapper{ + connectionHandler: connectionHandler, + packetHandler: packetHandler, + errorHandler: errorHandler, + } +} + +func (w *myUpstreamContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + myMetadata := ContextFrom(ctx) + if metadata.Source.IsValid() { + myMetadata.Source = metadata.Source + } + if metadata.Destination.IsValid() { + myMetadata.Destination = metadata.Destination + } + return w.connectionHandler(ctx, conn, *myMetadata) +} + +func (w *myUpstreamContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { + myMetadata := ContextFrom(ctx) + if metadata.Source.IsValid() { + myMetadata.Source = metadata.Source + } + if metadata.Destination.IsValid() { + myMetadata.Destination = metadata.Destination + } + return w.packetHandler(ctx, conn, *myMetadata) +} + +func (w *myUpstreamContextHandlerWrapper) NewError(ctx context.Context, err error) { + w.errorHandler.NewError(ctx, err) +} + +// Deprecated: Use ConnectionRouterEx instead. +func NewRouteHandler( + metadata InboundContext, + router ConnectionRouter, + logger logger.ContextLogger, +) UpstreamHandlerAdapter { + return &routeHandlerWrapper{ + metadata: metadata, + router: router, + logger: logger, + } +} + +// Deprecated: Use ConnectionRouterEx instead. +func NewRouteContextHandler( + router ConnectionRouter, + logger logger.ContextLogger, +) UpstreamHandlerAdapter { + return &routeContextHandlerWrapper{ + router: router, + logger: logger, + } +} + +var _ UpstreamHandlerAdapter = (*routeHandlerWrapper)(nil) + +// Deprecated: Use ConnectionRouterEx instead. +type routeHandlerWrapper struct { + metadata InboundContext + router ConnectionRouter + logger logger.ContextLogger +} + +func (w *routeHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + myMetadata := w.metadata + if metadata.Source.IsValid() { + myMetadata.Source = metadata.Source + } + if metadata.Destination.IsValid() { + myMetadata.Destination = metadata.Destination + } + return w.router.RouteConnection(ctx, conn, myMetadata) +} + +func (w *routeHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { + myMetadata := w.metadata + if metadata.Source.IsValid() { + myMetadata.Source = metadata.Source + } + if metadata.Destination.IsValid() { + myMetadata.Destination = metadata.Destination + } + return w.router.RoutePacketConnection(ctx, conn, myMetadata) +} + +func (w *routeHandlerWrapper) NewError(ctx context.Context, err error) { + w.logger.ErrorContext(ctx, err) +} + +var _ UpstreamHandlerAdapter = (*routeContextHandlerWrapper)(nil) + +// Deprecated: Use ConnectionRouterEx instead. +type routeContextHandlerWrapper struct { + router ConnectionRouter + logger logger.ContextLogger +} + +func (w *routeContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + myMetadata := ContextFrom(ctx) + if metadata.Source.IsValid() { + myMetadata.Source = metadata.Source + } + if metadata.Destination.IsValid() { + myMetadata.Destination = metadata.Destination + } + return w.router.RouteConnection(ctx, conn, *myMetadata) +} + +func (w *routeContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { + myMetadata := ContextFrom(ctx) + if metadata.Source.IsValid() { + myMetadata.Source = metadata.Source + } + if metadata.Destination.IsValid() { + myMetadata.Destination = metadata.Destination + } + return w.router.RoutePacketConnection(ctx, conn, *myMetadata) +} + +func (w *routeContextHandlerWrapper) NewError(ctx context.Context, err error) { + w.logger.ErrorContext(ctx, err) +} diff --git a/sing-box/cmd/sing-box/cmd_rule_set_match.go b/sing-box/cmd/sing-box/cmd_rule_set_match.go index 937458f2c6..bfa340cf41 100644 --- a/sing-box/cmd/sing-box/cmd_rule_set_match.go +++ b/sing-box/cmd/sing-box/cmd_rule_set_match.go @@ -10,7 +10,7 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" - "github.com/sagernet/sing-box/route" + "github.com/sagernet/sing-box/route/rule" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" "github.com/sagernet/sing/common/json" @@ -84,7 +84,7 @@ func ruleSetMatch(sourcePath string, domain string) error { } for i, ruleOptions := range plainRuleSet.Rules { var currentRule adapter.HeadlessRule - currentRule, err = route.NewHeadlessRule(nil, ruleOptions) + currentRule, err = rule.NewHeadlessRule(nil, ruleOptions) if err != nil { return E.Cause(err, "parse rule_set.rules.[", i, "]") } diff --git a/sing-box/cmd/sing-box/internal/convertor/adguard/convertor_test.go b/sing-box/cmd/sing-box/internal/convertor/adguard/convertor_test.go index 7da8a22841..6098485cf0 100644 --- a/sing-box/cmd/sing-box/internal/convertor/adguard/convertor_test.go +++ b/sing-box/cmd/sing-box/internal/convertor/adguard/convertor_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/route" + "github.com/sagernet/sing-box/route/rule" "github.com/stretchr/testify/require" ) @@ -26,7 +26,7 @@ example.arpa `)) require.NoError(t, err) require.Len(t, rules, 1) - rule, err := route.NewHeadlessRule(nil, rules[0]) + rule, err := rule.NewHeadlessRule(nil, rules[0]) require.NoError(t, err) matchDomain := []string{ "example.org", @@ -85,7 +85,7 @@ func TestHosts(t *testing.T) { `)) require.NoError(t, err) require.Len(t, rules, 1) - rule, err := route.NewHeadlessRule(nil, rules[0]) + rule, err := rule.NewHeadlessRule(nil, rules[0]) require.NoError(t, err) matchDomain := []string{ "google.com", @@ -115,7 +115,7 @@ www.example.org `)) require.NoError(t, err) require.Len(t, rules, 1) - rule, err := route.NewHeadlessRule(nil, rules[0]) + rule, err := rule.NewHeadlessRule(nil, rules[0]) require.NoError(t, err) matchDomain := []string{ "example.com", diff --git a/sing-box/common/mux/router.go b/sing-box/common/mux/router.go index 8a2296852b..2d4e7705d9 100644 --- a/sing-box/common/mux/router.go +++ b/sing-box/common/mux/router.go @@ -15,11 +15,11 @@ import ( ) type Router struct { - router adapter.ConnectionRouter + router adapter.ConnectionRouterEx service *mux.Service } -func NewRouterWithOptions(router adapter.ConnectionRouter, logger logger.ContextLogger, options option.InboundMultiplexOptions) (adapter.ConnectionRouter, error) { +func NewRouterWithOptions(router adapter.ConnectionRouterEx, logger logger.ContextLogger, options option.InboundMultiplexOptions) (adapter.ConnectionRouterEx, error) { if !options.Enabled { return router, nil } @@ -54,6 +54,7 @@ func NewRouterWithOptions(router adapter.ConnectionRouter, logger logger.Context func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { if metadata.Destination == mux.Destination { + // TODO: check if WithContext is necessary return r.service.NewConnection(adapter.WithContext(ctx, &metadata), conn, adapter.UpstreamMetadata(metadata)) } else { return r.router.RouteConnection(ctx, conn, metadata) @@ -63,3 +64,15 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { return r.router.RoutePacketConnection(ctx, conn, metadata) } + +func (r *Router) RouteConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + if metadata.Destination == mux.Destination { + r.service.NewConnectionEx(adapter.WithContext(ctx, &metadata), conn, metadata.Source, metadata.Destination, onClose) + return + } + r.router.RouteConnectionEx(ctx, conn, metadata, onClose) +} + +func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + r.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose) +} diff --git a/sing-box/common/sniff/sniff.go b/sing-box/common/sniff/sniff.go index 80bb2984f9..81fc0a2794 100644 --- a/sing-box/common/sniff/sniff.go +++ b/sing-box/common/sniff/sniff.go @@ -18,7 +18,7 @@ type ( PacketSniffer = func(ctx context.Context, metadata *adapter.InboundContext, packet []byte) error ) -func Skip(metadata adapter.InboundContext) bool { +func Skip(metadata *adapter.InboundContext) bool { // skip server first protocols switch metadata.Destination.Port { case 25, 465, 587: diff --git a/sing-box/common/uot/router.go b/sing-box/common/uot/router.go index fb2d23d557..93dd65e8b6 100644 --- a/sing-box/common/uot/router.go +++ b/sing-box/common/uot/router.go @@ -13,14 +13,14 @@ import ( "github.com/sagernet/sing/common/uot" ) -var _ adapter.ConnectionRouter = (*Router)(nil) +var _ adapter.ConnectionRouterEx = (*Router)(nil) type Router struct { - router adapter.ConnectionRouter + router adapter.ConnectionRouterEx logger logger.ContextLogger } -func NewRouter(router adapter.ConnectionRouter, logger logger.ContextLogger) *Router { +func NewRouter(router adapter.ConnectionRouterEx, logger logger.ContextLogger) *Router { return &Router{router, logger} } @@ -51,3 +51,37 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { return r.router.RoutePacketConnection(ctx, conn, metadata) } + +func (r *Router) RouteConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + switch metadata.Destination.Fqdn { + case uot.MagicAddress: + request, err := uot.ReadRequest(conn) + if err != nil { + err = E.Cause(err, "UoT read request") + r.logger.ErrorContext(ctx, "process connection from ", metadata.Source, ": ", err) + conn.Close() + onClose(err) + return + } + if request.IsConnect { + r.logger.InfoContext(ctx, "inbound UoT connect connection to ", request.Destination) + } else { + r.logger.InfoContext(ctx, "inbound UoT connection to ", request.Destination) + } + metadata.Domain = metadata.Destination.Fqdn + metadata.Destination = request.Destination + r.router.RoutePacketConnectionEx(ctx, uot.NewConn(conn, *request), metadata, onClose) + return + case uot.LegacyMagicAddress: + r.logger.InfoContext(ctx, "inbound legacy UoT connection") + metadata.Domain = metadata.Destination.Fqdn + metadata.Destination = M.Socksaddr{Addr: netip.IPv4Unspecified()} + r.RoutePacketConnectionEx(ctx, uot.NewConn(conn, uot.Request{}), metadata, onClose) + return + } + r.router.RouteConnectionEx(ctx, conn, metadata, onClose) +} + +func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + r.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose) +} diff --git a/sing-box/constant/rule.go b/sing-box/constant/rule.go index 718e79a5e6..02e03d8af0 100644 --- a/sing-box/constant/rule.go +++ b/sing-box/constant/rule.go @@ -22,3 +22,18 @@ const ( RuleSetVersion1 = 1 + iota RuleSetVersion2 ) + +const ( + RuleActionTypeRoute = "route" + RuleActionTypeReturn = "return" + RuleActionTypeReject = "reject" + RuleActionTypeHijackDNS = "hijack-dns" + RuleActionTypeSniff = "sniff" + RuleActionTypeResolve = "resolve" +) + +const ( + RuleActionRejectMethodDefault = "default" + RuleActionRejectMethodPortUnreachable = "port-unreachable" + RuleActionRejectMethodDrop = "drop" +) diff --git a/sing-box/experimental/clashapi/rules.go b/sing-box/experimental/clashapi/rules.go index 6ab5dda108..bc8fbb2bba 100644 --- a/sing-box/experimental/clashapi/rules.go +++ b/sing-box/experimental/clashapi/rules.go @@ -30,10 +30,9 @@ func getRules(router adapter.Router) func(w http.ResponseWriter, r *http.Request rules = append(rules, Rule{ Type: rule.Type(), Payload: rule.String(), - Proxy: rule.Outbound(), + Proxy: rule.Action().String(), }) } - render.JSON(w, r, render.M{ "rules": rules, }) diff --git a/sing-box/experimental/clashapi/trafficontrol/tracker.go b/sing-box/experimental/clashapi/trafficontrol/tracker.go index 73c28e69bd..5ccf6f2fd5 100644 --- a/sing-box/experimental/clashapi/trafficontrol/tracker.go +++ b/sing-box/experimental/clashapi/trafficontrol/tracker.go @@ -5,6 +5,7 @@ import ( "time" "github.com/sagernet/sing-box/adapter" + R "github.com/sagernet/sing-box/route/rule" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/bufio" @@ -60,7 +61,7 @@ func (t TrackerMetadata) MarshalJSON() ([]byte, error) { } var rule string if t.Rule != nil { - rule = F.ToString(t.Rule, " => ", t.Rule.Outbound()) + rule = F.ToString(t.Rule, " => ", t.Rule.Action()) } else { rule = "final" } @@ -131,19 +132,17 @@ func NewTCPTracker(conn net.Conn, manager *Manager, metadata adapter.InboundCont outbound string outboundType string ) - if rule == nil { - if defaultOutbound, err := router.DefaultOutbound(N.NetworkTCP); err == nil { - next = defaultOutbound.Tag() - } - } else { - next = rule.Outbound() + if routeAction, isRouteAction := rule.Action().(*R.RuleActionRoute); isRouteAction { + next = routeAction.Outbound + } else if defaultOutbound, err := router.DefaultOutbound(N.NetworkTCP); err == nil { + next = defaultOutbound.Tag() } for { - chain = append(chain, next) detour, loaded := router.Outbound(next) if !loaded { break } + chain = append(chain, next) outbound = detour.Tag() outboundType = detour.Type() group, isGroup := detour.(adapter.OutboundGroup) @@ -218,19 +217,17 @@ func NewUDPTracker(conn N.PacketConn, manager *Manager, metadata adapter.Inbound outbound string outboundType string ) - if rule == nil { - if defaultOutbound, err := router.DefaultOutbound(N.NetworkUDP); err == nil { - next = defaultOutbound.Tag() - } - } else { - next = rule.Outbound() + if routeAction, isRouteAction := rule.Action().(*R.RuleActionRoute); isRouteAction { + next = routeAction.Outbound + } else if defaultOutbound, err := router.DefaultOutbound(N.NetworkUDP); err == nil { + next = defaultOutbound.Tag() } for { - chain = append(chain, next) detour, loaded := router.Outbound(next) if !loaded { break } + chain = append(chain, next) outbound = detour.Tag() outboundType = detour.Type() group, isGroup := detour.(adapter.OutboundGroup) diff --git a/sing-box/go.mod b/sing-box/go.mod index ab71a4cb56..72c681e391 100644 --- a/sing-box/go.mod +++ b/sing-box/go.mod @@ -24,17 +24,17 @@ require ( github.com/sagernet/cors v1.2.1 github.com/sagernet/fswatch v0.1.1 github.com/sagernet/gomobile v0.1.4 - github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f + github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3 github.com/sagernet/quic-go v0.48.0-beta.1 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 - github.com/sagernet/sing v0.5.0-rc.2 - github.com/sagernet/sing-dns v0.3.0-rc.2 - github.com/sagernet/sing-mux v0.2.0 + github.com/sagernet/sing v0.5.0-rc.4.0.20241021153852-cf58af1a4627 + github.com/sagernet/sing-dns v0.3.0-rc.2.0.20241021154031-a59e0fbba3ce + github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec github.com/sagernet/sing-quic v0.3.0-rc.1 github.com/sagernet/sing-shadowsocks v0.2.7 github.com/sagernet/sing-shadowsocks2 v0.2.0 github.com/sagernet/sing-shadowtls v0.1.4 - github.com/sagernet/sing-tun v0.4.0-rc.4 + github.com/sagernet/sing-tun v0.4.0-rc.4.0.20241021153919-9ae45181180d github.com/sagernet/sing-vmess v0.1.12 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 github.com/sagernet/utls v1.6.7 @@ -46,6 +46,7 @@ require ( go4.org/netipx v0.0.0-20231129151722-fdeea329fbba golang.org/x/crypto v0.28.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 + golang.org/x/mod v0.20.0 golang.org/x/net v0.30.0 golang.org/x/sys v0.26.0 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 @@ -65,10 +66,10 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect - github.com/google/btree v1.1.2 // indirect + github.com/google/btree v1.1.3 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect - github.com/hashicorp/yamux v0.1.1 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/native v1.1.0 // indirect github.com/klauspost/compress v1.17.4 // indirect @@ -89,10 +90,9 @@ require ( github.com/vishvananda/netns v0.0.4 // indirect github.com/zeebo/blake3 v0.2.3 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.20.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/text v0.19.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.24.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect diff --git a/sing-box/go.sum b/sing-box/go.sum index c989fe47ca..8bdf7df0fd 100644 --- a/sing-box/go.sum +++ b/sing-box/go.sum @@ -33,14 +33,14 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= @@ -104,8 +104,8 @@ github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQ github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= github.com/sagernet/gomobile v0.1.4 h1:WzX9ka+iHdupMgy2Vdich+OAt7TM8C2cZbIbzNjBrJY= github.com/sagernet/gomobile v0.1.4/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E= -github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I= -github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0= +github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3 h1:RxEz7LhPNiF/gX/Hg+OXr5lqsM9iVAgmaK1L1vzlDRM= +github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3/go.mod h1:ehZwnT2UpmOWAHFL48XdBhnd4Qu4hN2O3Ji0us3ZHMw= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I= @@ -115,12 +115,12 @@ github.com/sagernet/quic-go v0.48.0-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.5.0-rc.2 h1:tIrs6pRbjJWvI0ITRSg47P1wosY+iSuHpw9t5/hBx+Q= -github.com/sagernet/sing v0.5.0-rc.2/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing-dns v0.3.0-rc.2 h1:z1yROBxd/6wik5h53Sz5df1DSmbPTaOu/Z0wAmyXGoQ= -github.com/sagernet/sing-dns v0.3.0-rc.2/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M= -github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo= -github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ= +github.com/sagernet/sing v0.5.0-rc.4.0.20241021153852-cf58af1a4627 h1:wWRmqHPHfyWRPUIGsjAmYshvXF+pC/csl9pAmo/vGpo= +github.com/sagernet/sing v0.5.0-rc.4.0.20241021153852-cf58af1a4627/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing-dns v0.3.0-rc.2.0.20241021154031-a59e0fbba3ce h1:OfpxE5qnXMyU/9LtNgX4M7bGP11lJx4s+KZ3Sijb0HE= +github.com/sagernet/sing-dns v0.3.0-rc.2.0.20241021154031-a59e0fbba3ce/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M= +github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec h1:6Fd/VsEsw9qIjaGi1IBTZSb4b4v5JYtNcoiBtGsQC48= +github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec/go.mod h1:RSwqqHwbtTOX3vs6ms8vMtBGH/0ZNyLm/uwt6TlmR84= github.com/sagernet/sing-quic v0.3.0-rc.1 h1:SlzL1yfEAKJyRduub8vzOVtbyTLAX7RZEEBZxO5utts= github.com/sagernet/sing-quic v0.3.0-rc.1/go.mod h1:uX+aUHA0fgIN6U3WViseDpSdTQriViZ7qz0Wbsf1mNQ= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= @@ -129,8 +129,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.4.0-rc.4 h1:EFz+UjLZTm+YS3ob1vpqjOga67wyvnxWcbQKfe5wE3Y= -github.com/sagernet/sing-tun v0.4.0-rc.4/go.mod h1:+lQdWhqD4atzrCgRhoyrxBCg1OBru/hAv2BT3kdgmGM= +github.com/sagernet/sing-tun v0.4.0-rc.4.0.20241021153919-9ae45181180d h1:zWcIQM3eAKJGzy7zhqkO7zm7ZI890OdR4vSwx2mevS0= +github.com/sagernet/sing-tun v0.4.0-rc.4.0.20241021153919-9ae45181180d/go.mod h1:Xhv+Mz2nE7HZTwResni8EtTa7AMJz/S6uQLT5lV23M8= github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg= github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= @@ -198,8 +198,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/sing-box/inbound/default.go b/sing-box/inbound/default.go index 44c580deb9..880dd26f61 100644 --- a/sing-box/inbound/default.go +++ b/sing-box/inbound/default.go @@ -22,13 +22,13 @@ type myInboundAdapter struct { protocol string network []string ctx context.Context - router adapter.ConnectionRouter + router adapter.ConnectionRouterEx logger log.ContextLogger tag string listenOptions option.ListenOptions - connHandler adapter.ConnectionHandler - packetHandler adapter.PacketHandler - oobPacketHandler adapter.OOBPacketHandler + connHandler adapter.ConnectionHandlerEx + packetHandler adapter.PacketHandlerEx + oobPacketHandler adapter.OOBPacketHandlerEx packetUpstream any // http mixed @@ -55,10 +55,6 @@ func (a *myInboundAdapter) Tag() string { return a.tag } -func (a *myInboundAdapter) Network() []string { - return a.network -} - func (a *myInboundAdapter) Start() error { var err error if common.Contains(a.network, N.NetworkTCP) { @@ -150,6 +146,31 @@ func (a *myInboundAdapter) newPacketConnection(ctx context.Context, conn N.Packe return a.router.RoutePacketConnection(ctx, conn, metadata) } +func (a *myInboundAdapter) upstreamHandlerEx(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapterEx { + return adapter.NewUpstreamHandlerEx(metadata, a.newConnectionEx, a.streamPacketConnectionEx) +} + +func (a *myInboundAdapter) upstreamContextHandlerEx() adapter.UpstreamHandlerAdapterEx { + return adapter.NewUpstreamContextHandlerEx(a.newConnectionEx, a.newPacketConnectionEx) +} + +func (a *myInboundAdapter) newConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + a.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) + a.router.RouteConnectionEx(ctx, conn, metadata, onClose) +} + +func (a *myInboundAdapter) newPacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + ctx = log.ContextWithNewID(ctx) + a.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source) + a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) + a.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose) +} + +func (a *myInboundAdapter) streamPacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) + a.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose) +} + func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.InboundContext) adapter.InboundContext { metadata.Inbound = a.tag metadata.InboundType = a.protocol @@ -167,25 +188,17 @@ func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.Inboun return metadata } -func (a *myInboundAdapter) createPacketMetadata(conn N.PacketConn, metadata adapter.InboundContext) adapter.InboundContext { - metadata.Inbound = a.tag - metadata.InboundType = a.protocol - metadata.InboundDetour = a.listenOptions.Detour - metadata.InboundOptions = a.listenOptions.InboundOptions - if !metadata.Destination.IsValid() { - metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap() - } - return metadata -} - +// Deprecated: don't use func (a *myInboundAdapter) newError(err error) { a.logger.Error(err) } +// Deprecated: don't use func (a *myInboundAdapter) NewError(ctx context.Context, err error) { NewError(a.logger, ctx, err) } +// Deprecated: don't use func NewError(logger log.ContextLogger, ctx context.Context, err error) { common.Close(err) if E.IsClosedOrCanceled(err) { diff --git a/sing-box/inbound/default_tcp.go b/sing-box/inbound/default_tcp.go index d680c6951a..6316026b51 100644 --- a/sing-box/inbound/default_tcp.go +++ b/sing-box/inbound/default_tcp.go @@ -1,7 +1,6 @@ package inbound import ( - "context" "net" "github.com/sagernet/sing-box/adapter" @@ -71,18 +70,5 @@ func (a *myInboundAdapter) injectTCP(conn net.Conn, metadata adapter.InboundCont ctx := log.ContextWithNewID(a.ctx) metadata = a.createMetadata(conn, metadata) a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) - hErr := a.connHandler.NewConnection(ctx, conn, metadata) - if hErr != nil { - conn.Close() - a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source)) - } -} - -func (a *myInboundAdapter) routeTCP(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) { - a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) - hErr := a.newConnection(ctx, conn, metadata) - if hErr != nil { - conn.Close() - a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source)) - } + a.connHandler.NewConnectionEx(ctx, conn, metadata, nil) } diff --git a/sing-box/inbound/default_udp.go b/sing-box/inbound/default_udp.go index 8e39471ac7..6bcde79dae 100644 --- a/sing-box/inbound/default_udp.go +++ b/sing-box/inbound/default_udp.go @@ -42,7 +42,6 @@ func (a *myInboundAdapter) loopUDPIn() { defer buffer.Release() buffer.IncRef() defer buffer.DecRef() - packetService := (*myInboundPacketAdapter)(a) for { buffer.Reset() n, addr, err := a.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes()) @@ -50,16 +49,7 @@ func (a *myInboundAdapter) loopUDPIn() { return } buffer.Truncate(n) - var metadata adapter.InboundContext - metadata.Inbound = a.tag - metadata.InboundType = a.protocol - metadata.InboundOptions = a.listenOptions.InboundOptions - metadata.Source = M.SocksaddrFromNetIP(addr).Unwrap() - metadata.OriginDestination = a.udpAddr - err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata) - if err != nil { - a.newError(E.Cause(err, "process packet from ", metadata.Source)) - } + a.packetHandler.NewPacketEx(buffer, M.SocksaddrFromNetIP(addr).Unwrap()) } } @@ -69,7 +59,6 @@ func (a *myInboundAdapter) loopUDPOOBIn() { defer buffer.Release() buffer.IncRef() defer buffer.DecRef() - packetService := (*myInboundPacketAdapter)(a) oob := make([]byte, 1024) for { buffer.Reset() @@ -78,22 +67,12 @@ func (a *myInboundAdapter) loopUDPOOBIn() { return } buffer.Truncate(n) - var metadata adapter.InboundContext - metadata.Inbound = a.tag - metadata.InboundType = a.protocol - metadata.InboundOptions = a.listenOptions.InboundOptions - metadata.Source = M.SocksaddrFromNetIP(addr).Unwrap() - metadata.OriginDestination = a.udpAddr - err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata) - if err != nil { - a.newError(E.Cause(err, "process packet from ", metadata.Source)) - } + a.oobPacketHandler.NewPacketEx(buffer, oob[:oobN], M.SocksaddrFromNetIP(addr).Unwrap()) } } func (a *myInboundAdapter) loopUDPInThreadSafe() { defer close(a.packetOutboundClosed) - packetService := (*myInboundPacketAdapter)(a) for { buffer := buf.NewPacket() n, addr, err := a.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes()) @@ -102,23 +81,12 @@ func (a *myInboundAdapter) loopUDPInThreadSafe() { return } buffer.Truncate(n) - var metadata adapter.InboundContext - metadata.Inbound = a.tag - metadata.InboundType = a.protocol - metadata.InboundOptions = a.listenOptions.InboundOptions - metadata.Source = M.SocksaddrFromNetIP(addr).Unwrap() - metadata.OriginDestination = a.udpAddr - err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata) - if err != nil { - buffer.Release() - a.newError(E.Cause(err, "process packet from ", metadata.Source)) - } + a.packetHandler.NewPacketEx(buffer, M.SocksaddrFromNetIP(addr).Unwrap()) } } func (a *myInboundAdapter) loopUDPOOBInThreadSafe() { defer close(a.packetOutboundClosed) - packetService := (*myInboundPacketAdapter)(a) oob := make([]byte, 1024) for { buffer := buf.NewPacket() @@ -128,17 +96,7 @@ func (a *myInboundAdapter) loopUDPOOBInThreadSafe() { return } buffer.Truncate(n) - var metadata adapter.InboundContext - metadata.Inbound = a.tag - metadata.InboundType = a.protocol - metadata.InboundOptions = a.listenOptions.InboundOptions - metadata.Source = M.SocksaddrFromNetIP(addr).Unwrap() - metadata.OriginDestination = a.udpAddr - err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata) - if err != nil { - buffer.Release() - a.newError(E.Cause(err, "process packet from ", metadata.Source)) - } + a.oobPacketHandler.NewPacketEx(buffer, oob[:oobN], M.SocksaddrFromNetIP(addr).Unwrap()) } } @@ -148,7 +106,7 @@ func (a *myInboundAdapter) loopUDPOut() { case packet := <-a.packetOutbound: err := a.writePacket(packet.buffer, packet.destination) if err != nil && !E.IsClosed(err) { - a.newError(E.New("write back udp: ", err)) + a.logger.Error(E.New("write back udp: ", err)) } continue case <-a.packetOutboundClosed: @@ -164,15 +122,36 @@ func (a *myInboundAdapter) loopUDPOut() { } } +func (a *myInboundAdapter) packetConn() N.PacketConn { + return (*myInboundPacketAdapter)(a) +} + +func (a *myInboundAdapter) createPacketMetadata(conn N.PacketConn, metadata adapter.InboundContext) adapter.InboundContext { + metadata.Inbound = a.tag + metadata.InboundType = a.protocol + metadata.InboundDetour = a.listenOptions.Detour + metadata.InboundOptions = a.listenOptions.InboundOptions + if !metadata.Destination.IsValid() { + metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap() + } + metadata.OriginDestination = a.udpAddr + return metadata +} + +func (a *myInboundAdapter) createPacketMetadataEx(source M.Socksaddr, destination M.Socksaddr) adapter.InboundContext { + var metadata adapter.InboundContext + metadata.Inbound = a.tag + metadata.InboundType = a.protocol + metadata.InboundDetour = a.listenOptions.Detour + metadata.InboundOptions = a.listenOptions.InboundOptions + metadata.Source = source + metadata.Destination = destination + metadata.OriginDestination = a.udpAddr + return metadata +} + func (a *myInboundAdapter) writePacket(buffer *buf.Buffer, destination M.Socksaddr) error { defer buffer.Release() - if destination.IsFqdn() { - udpAddr, err := net.ResolveUDPAddr(N.NetworkUDP, destination.String()) - if err != nil { - return err - } - return common.Error(a.udpConn.WriteTo(buffer.Bytes(), udpAddr)) - } return common.Error(a.udpConn.WriteToUDPAddrPort(buffer.Bytes(), destination.AddrPort())) } diff --git a/sing-box/inbound/direct.go b/sing-box/inbound/direct.go index 7079a9f24f..1b13f428ea 100644 --- a/sing-box/inbound/direct.go +++ b/sing-box/inbound/direct.go @@ -3,7 +3,6 @@ package inbound import ( "context" "net" - "net/netip" "time" "github.com/sagernet/sing-box/adapter" @@ -13,14 +12,14 @@ import ( "github.com/sagernet/sing/common/buf" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" - "github.com/sagernet/sing/common/udpnat" + "github.com/sagernet/sing/common/udpnat2" ) var _ adapter.Inbound = (*Direct)(nil) type Direct struct { myInboundAdapter - udpNat *udpnat.Service[netip.AddrPort] + udpNat *udpnat.Service overrideOption int overrideDestination M.Socksaddr } @@ -54,10 +53,9 @@ func NewDirect(ctx context.Context, router adapter.Router, logger log.ContextLog } else { udpTimeout = C.UDPTimeout } - inbound.udpNat = udpnat.New[netip.AddrPort](int64(udpTimeout.Seconds()), adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound)) + inbound.udpNat = udpnat.New(inbound, inbound.preparePacketConnection, udpTimeout) inbound.connHandler = inbound inbound.packetHandler = inbound - inbound.packetUpstream = inbound.udpNat return inbound } @@ -76,29 +74,38 @@ func (d *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adap return d.router.RouteConnection(ctx, conn, metadata) } -func (d *Direct) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error { +func (d *Direct) NewPacketEx(buffer *buf.Buffer, source M.Socksaddr) { + var destination M.Socksaddr switch d.overrideOption { case 1: - metadata.Destination = d.overrideDestination + destination = d.overrideDestination case 2: - destination := d.overrideDestination - destination.Port = metadata.Destination.Port - metadata.Destination = destination + destination = d.overrideDestination + destination.Port = source.Port case 3: - metadata.Destination.Port = d.overrideDestination.Port + destination = source + destination.Port = d.overrideDestination.Port } - d.udpNat.NewContextPacket(ctx, metadata.Source.AddrPort(), buffer, adapter.UpstreamMetadata(metadata), func(natConn N.PacketConn) (context.Context, N.PacketWriter) { - return adapter.WithContext(log.ContextWithNewID(ctx), &metadata), &udpnat.DirectBackWriter{Source: conn, Nat: natConn} - }) - return nil + d.udpNat.NewPacket([][]byte{buffer.Bytes()}, source, destination, nil) } -func (d *Direct) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return d.router.RouteConnection(ctx, conn, metadata) +func (d *Direct) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + d.newConnectionEx(ctx, conn, metadata, onClose) } -func (d *Direct) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - ctx = log.ContextWithNewID(ctx) - d.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source) - return d.router.RoutePacketConnection(ctx, conn, metadata) +func (d *Direct) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + d.newPacketConnectionEx(ctx, conn, d.createPacketMetadataEx(source, destination), onClose) +} + +func (d *Direct) preparePacketConnection(source M.Socksaddr, destination M.Socksaddr, userData any) (bool, context.Context, N.PacketWriter, N.CloseHandlerFunc) { + return true, d.ctx, &directPacketWriter{d.packetConn(), source}, nil +} + +type directPacketWriter struct { + writer N.PacketWriter + source M.Socksaddr +} + +func (w *directPacketWriter) WritePacket(buffer *buf.Buffer, addr M.Socksaddr) error { + return w.writer.WritePacket(buffer, w.source) } diff --git a/sing-box/inbound/http.go b/sing-box/inbound/http.go index b466331995..20c8f6903d 100644 --- a/sing-box/inbound/http.go +++ b/sing-box/inbound/http.go @@ -4,7 +4,6 @@ import ( std_bufio "bufio" "context" "net" - "os" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/tls" @@ -20,8 +19,8 @@ import ( ) var ( - _ adapter.Inbound = (*HTTP)(nil) - _ adapter.InjectableInbound = (*HTTP)(nil) + _ adapter.Inbound = (*HTTP)(nil) + _ adapter.TCPInjectableInbound = (*HTTP)(nil) ) type HTTP struct { @@ -72,7 +71,15 @@ func (h *HTTP) Close() error { ) } -func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { +func (h *HTTP) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.newConnection(ctx, conn, metadata, onClose) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } +} + +func (h *HTTP) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error { var err error if h.tlsConfig != nil { conn, err = tls.ServerHandshake(ctx, conn, h.tlsConfig) @@ -80,35 +87,33 @@ func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapte return err } } - return http.HandleConnection(ctx, conn, std_bufio.NewReader(conn), h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata)) + return http.HandleConnectionEx(ctx, conn, std_bufio.NewReader(conn), h.authenticator, nil, h.upstreamUserHandlerEx(metadata), metadata.Source, onClose) } -func (h *HTTP) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (a *myInboundAdapter) upstreamUserHandlerEx(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapterEx { + return adapter.NewUpstreamHandlerEx(metadata, a.newUserConnection, a.streamUserPacketConnection) } -func (a *myInboundAdapter) upstreamUserHandler(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapter { - return adapter.NewUpstreamHandler(metadata, a.newUserConnection, a.streamUserPacketConnection, a) -} - -func (a *myInboundAdapter) newUserConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { +func (a *myInboundAdapter) newUserConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { user, loaded := auth.UserFromContext[string](ctx) if !loaded { a.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) - return a.router.RouteConnection(ctx, conn, metadata) + a.router.RouteConnectionEx(ctx, conn, metadata, onClose) + return } metadata.User = user a.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination) - return a.router.RouteConnection(ctx, conn, metadata) + a.router.RouteConnectionEx(ctx, conn, metadata, onClose) } -func (a *myInboundAdapter) streamUserPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { +func (a *myInboundAdapter) streamUserPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { user, loaded := auth.UserFromContext[string](ctx) if !loaded { a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) - return a.router.RoutePacketConnection(ctx, conn, metadata) + a.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose) + return } metadata.User = user a.logger.InfoContext(ctx, "[", user, "] inbound packet connection to ", metadata.Destination) - return a.router.RoutePacketConnection(ctx, conn, metadata) + a.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose) } diff --git a/sing-box/inbound/mixed.go b/sing-box/inbound/mixed.go index 3933f7af05..81f6a43a09 100644 --- a/sing-box/inbound/mixed.go +++ b/sing-box/inbound/mixed.go @@ -4,7 +4,6 @@ import ( std_bufio "bufio" "context" "net" - "os" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/uot" @@ -12,6 +11,7 @@ import ( "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common/auth" + E "github.com/sagernet/sing/common/exceptions" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/protocol/http" "github.com/sagernet/sing/protocol/socks" @@ -20,8 +20,8 @@ import ( ) var ( - _ adapter.Inbound = (*Mixed)(nil) - _ adapter.InjectableInbound = (*Mixed)(nil) + _ adapter.Inbound = (*Mixed)(nil) + _ adapter.TCPInjectableInbound = (*Mixed)(nil) ) type Mixed struct { @@ -47,20 +47,24 @@ func NewMixed(ctx context.Context, router adapter.Router, logger log.ContextLogg return inbound } -func (h *Mixed) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - reader := std_bufio.NewReader(conn) - headerBytes, err := reader.Peek(1) +func (h *Mixed) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.newConnection(ctx, conn, metadata, onClose) + N.CloseOnHandshakeFailure(conn, onClose, err) if err != nil { - return err - } - switch headerBytes[0] { - case socks4.Version, socks5.Version: - return socks.HandleConnection0(ctx, conn, reader, h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata)) - default: - return http.HandleConnection(ctx, conn, reader, h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata)) + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) } } -func (h *Mixed) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (h *Mixed) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error { + reader := std_bufio.NewReader(conn) + headerBytes, err := reader.Peek(1) + if err != nil { + return E.Cause(err, "peek first byte") + } + switch headerBytes[0] { + case socks4.Version, socks5.Version: + return socks.HandleConnectionEx(ctx, conn, reader, h.authenticator, nil, h.upstreamUserHandlerEx(metadata), metadata.Source, metadata.Destination, onClose) + default: + return http.HandleConnectionEx(ctx, conn, reader, h.authenticator, nil, h.upstreamUserHandlerEx(metadata), metadata.Source, onClose) + } } diff --git a/sing-box/inbound/naive.go b/sing-box/inbound/naive.go index 07328c09f4..498e823cec 100644 --- a/sing-box/inbound/naive.go +++ b/sing-box/inbound/naive.go @@ -17,6 +17,7 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-box/transport/v2rayhttp" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/auth" "github.com/sagernet/sing/common/buf" @@ -164,13 +165,13 @@ func (n *Naive) ServeHTTP(writer http.ResponseWriter, request *http.Request) { n.badRequest(ctx, request, E.New("hijack failed")) return } - n.newConnection(ctx, &naiveH1Conn{Conn: conn}, userName, source, destination) + n.newConnection(ctx, false, &naiveH1Conn{Conn: conn}, userName, source, destination) } else { - n.newConnection(ctx, &naiveH2Conn{reader: request.Body, writer: writer, flusher: writer.(http.Flusher)}, userName, source, destination) + n.newConnection(ctx, true, &naiveH2Conn{reader: request.Body, writer: writer, flusher: writer.(http.Flusher)}, userName, source, destination) } } -func (n *Naive) newConnection(ctx context.Context, conn net.Conn, userName string, source, destination M.Socksaddr) { +func (n *Naive) newConnection(ctx context.Context, waitForClose bool, conn net.Conn, userName string, source M.Socksaddr, destination M.Socksaddr) { if userName != "" { n.logger.InfoContext(ctx, "[", userName, "] inbound connection from ", source) n.logger.InfoContext(ctx, "[", userName, "] inbound connection to ", destination) @@ -178,19 +179,26 @@ func (n *Naive) newConnection(ctx context.Context, conn net.Conn, userName strin n.logger.InfoContext(ctx, "inbound connection from ", source) n.logger.InfoContext(ctx, "inbound connection to ", destination) } - hErr := n.router.RouteConnection(ctx, conn, n.createMetadata(conn, adapter.InboundContext{ + metadata := n.createMetadata(conn, adapter.InboundContext{ Source: source, Destination: destination, User: userName, - })) - if hErr != nil { - conn.Close() - n.NewError(ctx, E.Cause(hErr, "process connection from ", source)) + }) + if !waitForClose { + n.router.RouteConnectionEx(ctx, conn, metadata, nil) + } else { + done := make(chan struct{}) + wrapper := v2rayhttp.NewHTTP2Wrapper(conn) + n.router.RouteConnectionEx(ctx, conn, metadata, N.OnceClose(func(it error) { + close(done) + })) + <-done + wrapper.CloseWrapper() } } func (n *Naive) badRequest(ctx context.Context, request *http.Request, err error) { - n.NewError(ctx, E.Cause(err, "process connection from ", request.RemoteAddr)) + n.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", request.RemoteAddr)) } func rejectHTTP(writer http.ResponseWriter, statusCode int) { diff --git a/sing-box/inbound/redirect.go b/sing-box/inbound/redirect.go index 4c7cf1d585..c4c6faf341 100644 --- a/sing-box/inbound/redirect.go +++ b/sing-box/inbound/redirect.go @@ -9,7 +9,6 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" - E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" ) @@ -34,11 +33,13 @@ func NewRedirect(ctx context.Context, router adapter.Router, logger log.ContextL return redirect } -func (r *Redirect) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { +func (r *Redirect) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { destination, err := redir.GetOriginalDestination(conn) if err != nil { - return E.Cause(err, "get redirect destination") + conn.Close() + r.logger.ErrorContext(ctx, "process connection from ", conn.RemoteAddr(), ": get redirect destination: ", err) + return } metadata.Destination = M.SocksaddrFromNetIP(destination) - return r.newConnection(ctx, conn, metadata) + r.newConnectionEx(ctx, conn, metadata, onClose) } diff --git a/sing-box/inbound/shadowsocks.go b/sing-box/inbound/shadowsocks.go index ca15b8d8e8..3fff231d8f 100644 --- a/sing-box/inbound/shadowsocks.go +++ b/sing-box/inbound/shadowsocks.go @@ -3,7 +3,6 @@ package inbound import ( "context" "net" - "os" "time" "github.com/sagernet/sing-box/adapter" @@ -18,6 +17,7 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" E "github.com/sagernet/sing/common/exceptions" + M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/ntp" ) @@ -36,8 +36,8 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte } var ( - _ adapter.Inbound = (*Shadowsocks)(nil) - _ adapter.InjectableInbound = (*Shadowsocks)(nil) + _ adapter.Inbound = (*Shadowsocks)(nil) + _ adapter.TCPInjectableInbound = (*Shadowsocks)(nil) ) type Shadowsocks struct { @@ -74,11 +74,11 @@ func newShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte } switch { case options.Method == shadowsocks.MethodNone: - inbound.service = shadowsocks.NewNoneService(int64(udpTimeout.Seconds()), inbound.upstreamContextHandler()) + inbound.service = shadowsocks.NewNoneService(int64(udpTimeout.Seconds()), adapter.NewUpstreamHandler(adapter.InboundContext{}, inbound.newConnection, inbound.newPacketConnection, inbound)) case common.Contains(shadowaead.List, options.Method): - inbound.service, err = shadowaead.NewService(options.Method, nil, options.Password, int64(udpTimeout.Seconds()), inbound.upstreamContextHandler()) + inbound.service, err = shadowaead.NewService(options.Method, nil, options.Password, int64(udpTimeout.Seconds()), adapter.NewUpstreamHandler(adapter.InboundContext{}, inbound.newConnection, inbound.newPacketConnection, inbound)) case common.Contains(shadowaead_2022.List, options.Method): - inbound.service, err = shadowaead_2022.NewServiceWithPassword(options.Method, options.Password, int64(udpTimeout.Seconds()), inbound.upstreamContextHandler(), ntp.TimeFuncFromContext(ctx)) + inbound.service, err = shadowaead_2022.NewServiceWithPassword(options.Method, options.Password, int64(udpTimeout.Seconds()), adapter.NewUpstreamHandler(adapter.InboundContext{}, inbound.newConnection, inbound.newPacketConnection, inbound), ntp.TimeFuncFromContext(ctx)) default: err = E.New("unsupported method: ", options.Method) } @@ -86,14 +86,29 @@ func newShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte return inbound, err } -func (h *Shadowsocks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) +func (h *Shadowsocks) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.service.NewConnection(ctx, conn, adapter.UpstreamMetadata(metadata)) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } } -func (h *Shadowsocks) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error { - return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata)) +func (h *Shadowsocks) NewPacketEx(buffer *buf.Buffer, source M.Socksaddr) { + err := h.service.NewPacket(h.ctx, h.packetConn(), buffer, M.Metadata{Source: source}) + if err != nil { + h.logger.Error(E.Cause(err, "process packet from ", source)) + } } -func (h *Shadowsocks) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (h *Shadowsocks) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { + h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) + return h.router.RouteConnection(ctx, conn, h.createMetadata(conn, metadata)) +} + +func (h *Shadowsocks) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { + ctx = log.ContextWithNewID(ctx) + h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source) + h.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) + return h.router.RoutePacketConnection(ctx, conn, h.createPacketMetadata(conn, metadata)) } diff --git a/sing-box/inbound/shadowsocks_multi.go b/sing-box/inbound/shadowsocks_multi.go index a291af4acb..2953419490 100644 --- a/sing-box/inbound/shadowsocks_multi.go +++ b/sing-box/inbound/shadowsocks_multi.go @@ -20,13 +20,14 @@ import ( "github.com/sagernet/sing/common/buf" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" + M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/ntp" ) var ( - _ adapter.Inbound = (*ShadowsocksMulti)(nil) - _ adapter.InjectableInbound = (*ShadowsocksMulti)(nil) + _ adapter.Inbound = (*ShadowsocksMulti)(nil) + _ adapter.TCPInjectableInbound = (*ShadowsocksMulti)(nil) ) type ShadowsocksMulti struct { @@ -66,14 +67,15 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log. options.Method, options.Password, int64(udpTimeout.Seconds()), - adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), + adapter.NewUpstreamHandler(adapter.InboundContext{}, inbound.newConnection, inbound.newPacketConnection, inbound), ntp.TimeFuncFromContext(ctx), ) } else if common.Contains(shadowaead.List, options.Method) { service, err = shadowaead.NewMultiService[int]( options.Method, int64(udpTimeout.Seconds()), - adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound)) + adapter.NewUpstreamHandler(adapter.InboundContext{}, inbound.newConnection, inbound.newPacketConnection, inbound), + ) } else { return nil, E.New("unsupported method: " + options.Method) } @@ -94,16 +96,19 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log. return inbound, err } -func (h *ShadowsocksMulti) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) +func (h *ShadowsocksMulti) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.service.NewConnection(ctx, conn, adapter.UpstreamMetadata(metadata)) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } } -func (h *ShadowsocksMulti) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error { - return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata)) -} - -func (h *ShadowsocksMulti) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (h *ShadowsocksMulti) NewPacketEx(buffer *buf.Buffer, source M.Socksaddr) { + err := h.service.NewPacket(h.ctx, h.packetConn(), buffer, M.Metadata{Source: source}) + if err != nil { + h.logger.Error(E.Cause(err, "process packet from ", source)) + } } func (h *ShadowsocksMulti) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { @@ -118,7 +123,7 @@ func (h *ShadowsocksMulti) newConnection(ctx context.Context, conn net.Conn, met metadata.User = user } h.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination) - return h.router.RouteConnection(ctx, conn, metadata) + return h.router.RouteConnection(ctx, conn, h.createMetadata(conn, metadata)) } func (h *ShadowsocksMulti) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { @@ -135,5 +140,5 @@ func (h *ShadowsocksMulti) newPacketConnection(ctx context.Context, conn N.Packe ctx = log.ContextWithNewID(ctx) h.logger.InfoContext(ctx, "[", user, "] inbound packet connection from ", metadata.Source) h.logger.InfoContext(ctx, "[", user, "] inbound packet connection to ", metadata.Destination) - return h.router.RoutePacketConnection(ctx, conn, metadata) + return h.router.RoutePacketConnection(ctx, conn, h.createPacketMetadata(conn, metadata)) } diff --git a/sing-box/inbound/shadowsocks_relay.go b/sing-box/inbound/shadowsocks_relay.go index fbc2838ade..02246a3f3c 100644 --- a/sing-box/inbound/shadowsocks_relay.go +++ b/sing-box/inbound/shadowsocks_relay.go @@ -16,13 +16,15 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/auth" "github.com/sagernet/sing/common/buf" + E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" + M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" ) var ( - _ adapter.Inbound = (*ShadowsocksRelay)(nil) - _ adapter.InjectableInbound = (*ShadowsocksRelay)(nil) + _ adapter.Inbound = (*ShadowsocksRelay)(nil) + _ adapter.TCPInjectableInbound = (*ShadowsocksRelay)(nil) ) type ShadowsocksRelay struct { @@ -61,7 +63,7 @@ func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log. options.Method, options.Password, int64(udpTimeout.Seconds()), - adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), + adapter.NewUpstreamHandler(adapter.InboundContext{}, inbound.newConnection, inbound.newPacketConnection, inbound), ) if err != nil { return nil, err @@ -79,16 +81,19 @@ func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log. return inbound, err } -func (h *ShadowsocksRelay) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) +func (h *ShadowsocksRelay) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.service.NewConnection(ctx, conn, adapter.UpstreamMetadata(metadata)) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } } -func (h *ShadowsocksRelay) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error { - return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata)) -} - -func (h *ShadowsocksRelay) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (h *ShadowsocksRelay) NewPacketEx(buffer *buf.Buffer, source M.Socksaddr) { + err := h.service.NewPacket(h.ctx, h.packetConn(), buffer, M.Metadata{Source: source}) + if err != nil { + h.logger.Error(E.Cause(err, "process packet from ", source)) + } } func (h *ShadowsocksRelay) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { @@ -103,7 +108,7 @@ func (h *ShadowsocksRelay) newConnection(ctx context.Context, conn net.Conn, met metadata.User = destination } h.logger.InfoContext(ctx, "[", destination, "] inbound connection to ", metadata.Destination) - return h.router.RouteConnection(ctx, conn, metadata) + return h.router.RouteConnection(ctx, conn, h.createMetadata(conn, metadata)) } func (h *ShadowsocksRelay) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { @@ -120,5 +125,5 @@ func (h *ShadowsocksRelay) newPacketConnection(ctx context.Context, conn N.Packe ctx = log.ContextWithNewID(ctx) h.logger.InfoContext(ctx, "[", destination, "] inbound packet connection from ", metadata.Source) h.logger.InfoContext(ctx, "[", destination, "] inbound packet connection to ", metadata.Destination) - return h.router.RoutePacketConnection(ctx, conn, metadata) + return h.router.RoutePacketConnection(ctx, conn, h.createPacketMetadata(conn, metadata)) } diff --git a/sing-box/inbound/shadowtls.go b/sing-box/inbound/shadowtls.go index 358564f221..ca14228635 100644 --- a/sing-box/inbound/shadowtls.go +++ b/sing-box/inbound/shadowtls.go @@ -12,6 +12,7 @@ import ( "github.com/sagernet/sing-shadowtls" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/auth" + E "github.com/sagernet/sing/common/exceptions" N "github.com/sagernet/sing/common/network" ) @@ -91,3 +92,11 @@ func (h *ShadowTLS) newConnection(ctx context.Context, conn net.Conn, metadata a } return h.router.RouteConnection(ctx, conn, metadata) } + +func (h *ShadowTLS) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.NewConnection(ctx, conn, metadata) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } +} diff --git a/sing-box/inbound/socks.go b/sing-box/inbound/socks.go index 7c5183c9f7..04b0a77dc7 100644 --- a/sing-box/inbound/socks.go +++ b/sing-box/inbound/socks.go @@ -1,9 +1,9 @@ package inbound import ( + std_bufio "bufio" "context" "net" - "os" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/uot" @@ -11,13 +11,14 @@ import ( "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common/auth" + E "github.com/sagernet/sing/common/exceptions" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/protocol/socks" ) var ( - _ adapter.Inbound = (*Socks)(nil) - _ adapter.InjectableInbound = (*Socks)(nil) + _ adapter.Inbound = (*Socks)(nil) + _ adapter.TCPInjectableInbound = (*Socks)(nil) ) type Socks struct { @@ -42,10 +43,10 @@ func NewSocks(ctx context.Context, router adapter.Router, logger log.ContextLogg return inbound } -func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return socks.HandleConnection(ctx, conn, h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata)) -} - -func (h *Socks) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (h *Socks) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := socks.HandleConnectionEx(ctx, conn, std_bufio.NewReader(conn), h.authenticator, nil, h.upstreamUserHandlerEx(metadata), metadata.Source, metadata.Destination, onClose) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } } diff --git a/sing-box/inbound/tproxy.go b/sing-box/inbound/tproxy.go index a074eb495b..6814ac8613 100644 --- a/sing-box/inbound/tproxy.go +++ b/sing-box/inbound/tproxy.go @@ -18,12 +18,12 @@ import ( E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" - "github.com/sagernet/sing/common/udpnat" + "github.com/sagernet/sing/common/udpnat2" ) type TProxy struct { myInboundAdapter - udpNat *udpnat.Service[netip.AddrPort] + udpNat *udpnat.Service } func NewTProxy(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TProxyInboundOptions) *TProxy { @@ -46,8 +46,7 @@ func NewTProxy(ctx context.Context, router adapter.Router, logger log.ContextLog } tproxy.connHandler = tproxy tproxy.oobPacketHandler = tproxy - tproxy.udpNat = udpnat.New[netip.AddrPort](int64(udpTimeout.Seconds()), tproxy.upstreamContextHandler()) - tproxy.packetUpstream = tproxy.udpNat + tproxy.udpNat = udpnat.New(tproxy, tproxy.preparePacketConnection, udpTimeout) return tproxy } @@ -75,35 +74,43 @@ func (t *TProxy) Start() error { return nil } -func (t *TProxy) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { +func (t *TProxy) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap() - return t.newConnection(ctx, conn, metadata) + t.newConnectionEx(ctx, conn, metadata, onClose) } -func (t *TProxy) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, oob []byte, metadata adapter.InboundContext) error { +func (t *TProxy) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + t.newPacketConnectionEx(ctx, conn, t.createPacketMetadataEx(source, destination), onClose) +} + +func (t *TProxy) NewPacketEx(buffer *buf.Buffer, oob []byte, source M.Socksaddr) { destination, err := redir.GetOriginalDestinationFromOOB(oob) if err != nil { - return E.Cause(err, "get tproxy destination") + t.logger.Warn("process packet from ", source, ": get tproxy destination: ", err) + return } - metadata.Destination = M.SocksaddrFromNetIP(destination).Unwrap() - t.udpNat.NewContextPacket(ctx, metadata.Source.AddrPort(), buffer, adapter.UpstreamMetadata(metadata), func(natConn N.PacketConn) (context.Context, N.PacketWriter) { - return adapter.WithContext(log.ContextWithNewID(ctx), &metadata), &tproxyPacketWriter{ctx: ctx, source: natConn, destination: metadata.Destination} - }) - return nil + t.udpNat.NewPacket([][]byte{buffer.Bytes()}, source, M.SocksaddrFromNetIP(destination), nil) } type tproxyPacketWriter struct { ctx context.Context - source N.PacketConn + source netip.AddrPort destination M.Socksaddr conn *net.UDPConn } +func (t *TProxy) preparePacketConnection(source M.Socksaddr, destination M.Socksaddr, userData any) (bool, context.Context, N.PacketWriter, N.CloseHandlerFunc) { + writer := &tproxyPacketWriter{ctx: t.ctx, source: source.AddrPort(), destination: destination} + return true, t.ctx, writer, func(it error) { + common.Close(common.PtrOrNil(writer.conn)) + } +} + func (w *tproxyPacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { defer buffer.Release() conn := w.conn if w.destination == destination && conn != nil { - _, err := conn.WriteToUDPAddrPort(buffer.Bytes(), M.AddrPortFromNet(w.source.LocalAddr())) + _, err := conn.WriteToUDPAddrPort(buffer.Bytes(), w.source) if err != nil { w.conn = nil } @@ -122,9 +129,5 @@ func (w *tproxyPacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socks } else { defer udpConn.Close() } - return common.Error(udpConn.WriteToUDPAddrPort(buffer.Bytes(), M.AddrPortFromNet(w.source.LocalAddr()))) -} - -func (w *tproxyPacketWriter) Close() error { - return common.Close(common.PtrOrNil(w.conn)) + return common.Error(udpConn.WriteToUDPAddrPort(buffer.Bytes(), w.source)) } diff --git a/sing-box/inbound/trojan.go b/sing-box/inbound/trojan.go index 203b6d3927..a0b5d8febd 100644 --- a/sing-box/inbound/trojan.go +++ b/sing-box/inbound/trojan.go @@ -22,8 +22,8 @@ import ( ) var ( - _ adapter.Inbound = (*Trojan)(nil) - _ adapter.InjectableInbound = (*Trojan)(nil) + _ adapter.Inbound = (*Trojan)(nil) + _ adapter.TCPInjectableInbound = (*Trojan)(nil) ) type Trojan struct { @@ -165,8 +165,12 @@ func (h *Trojan) NewConnection(ctx context.Context, conn net.Conn, metadata adap return h.service.NewConnection(adapter.WithContext(ctx, &metadata), conn, adapter.UpstreamMetadata(metadata)) } -func (h *Trojan) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (h *Trojan) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.NewConnection(ctx, conn, metadata) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } } func (h *Trojan) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { diff --git a/sing-box/inbound/tun.go b/sing-box/inbound/tun.go index 6cb65de249..5781e37d3f 100644 --- a/sing-box/inbound/tun.go +++ b/sing-box/inbound/tun.go @@ -27,17 +27,18 @@ import ( "go4.org/netipx" ) -var _ adapter.Inbound = (*Tun)(nil) +var _ adapter.Inbound = (*TUN)(nil) -type Tun struct { - tag string - ctx context.Context - router adapter.Router - logger log.ContextLogger +type TUN struct { + tag string + ctx context.Context + router adapter.Router + logger log.ContextLogger + // Deprecated inboundOptions option.InboundOptions tunOptions tun.Options endpointIndependentNat bool - udpTimeout int64 + udpTimeout time.Duration stack string tunIf tun.Tun tunStack tun.Stack @@ -52,7 +53,7 @@ type Tun struct { routeExcludeAddressSet []*netipx.IPSet } -func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TunInboundOptions, platformInterface platform.Interface) (*Tun, error) { +func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TunInboundOptions, platformInterface platform.Interface) (*TUN, error) { address := options.Address //nolint:staticcheck //goland:noinspection GoDeprecation @@ -150,7 +151,7 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger outputMark = tun.DefaultAutoRedirectOutputMark } - inbound := &Tun{ + inbound := &TUN{ tag: tag, ctx: ctx, router: router, @@ -182,7 +183,7 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger InterfaceMonitor: router.InterfaceMonitor(), }, endpointIndependentNat: options.EndpointIndependentNat, - udpTimeout: int64(udpTimeout.Seconds()), + udpTimeout: udpTimeout, stack: options.Stack, platformInterface: platformInterface, platformOptions: common.PtrValueOrDefault(options.Platform), @@ -195,7 +196,7 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger inbound.autoRedirect, err = tun.NewAutoRedirect(tun.AutoRedirectOptions{ TunOptions: &inbound.tunOptions, Context: ctx, - Handler: inbound, + Handler: (*autoRedirectHandler)(inbound), Logger: logger, NetworkMonitor: router.NetworkMonitor(), InterfaceFinder: router.InterfaceFinder(), @@ -271,17 +272,17 @@ func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges. return uidRanges, nil } -func (t *Tun) Type() string { +func (t *TUN) Type() string { return C.TypeTun } -func (t *Tun) Tag() string { +func (t *TUN) Tag() string { return t.tag } -func (t *Tun) Start() error { +func (t *TUN) Start() error { if C.IsAndroid && t.platformInterface == nil { - t.tunOptions.BuildAndroidRules(t.router.PackageManager(), t) + t.tunOptions.BuildAndroidRules(t.router.PackageManager()) } if t.tunOptions.Name == "" { t.tunOptions.Name = tun.CalculateInterfaceName("") @@ -337,7 +338,7 @@ func (t *Tun) Start() error { return nil } -func (t *Tun) PostStart() error { +func (t *TUN) PostStart() error { monitor := taskmonitor.New(t.logger, C.StartTimeout) if t.autoRedirect != nil { t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet) @@ -376,7 +377,7 @@ func (t *Tun) PostStart() error { return nil } -func (t *Tun) updateRouteAddressSet(it adapter.RuleSet) { +func (t *TUN) updateRouteAddressSet(it adapter.RuleSet) { t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet) t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet) t.autoRedirect.UpdateRouteAddressSet() @@ -384,7 +385,7 @@ func (t *Tun) updateRouteAddressSet(it adapter.RuleSet) { t.routeExcludeAddressSet = nil } -func (t *Tun) Close() error { +func (t *TUN) Close() error { return common.Close( t.tunStack, t.tunIf, @@ -392,44 +393,48 @@ func (t *Tun) Close() error { ) } -func (t *Tun) NewConnection(ctx context.Context, conn net.Conn, upstreamMetadata M.Metadata) error { - ctx = log.ContextWithNewID(ctx) - var metadata adapter.InboundContext - metadata.Inbound = t.tag - metadata.InboundType = C.TypeTun - metadata.Source = upstreamMetadata.Source - metadata.Destination = upstreamMetadata.Destination - metadata.InboundOptions = t.inboundOptions - if upstreamMetadata.Protocol != "" { - t.logger.InfoContext(ctx, "inbound ", upstreamMetadata.Protocol, " connection from ", metadata.Source) - } else { - t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) - } - t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) - err := t.router.RouteConnection(ctx, conn, metadata) - if err != nil { - t.NewError(ctx, err) - } +func (t *TUN) PrepareConnection(source M.Socksaddr, destination M.Socksaddr) error { + // TODO: implement rejects return nil } -func (t *Tun) NewPacketConnection(ctx context.Context, conn N.PacketConn, upstreamMetadata M.Metadata) error { +func (t *TUN) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { ctx = log.ContextWithNewID(ctx) var metadata adapter.InboundContext metadata.Inbound = t.tag metadata.InboundType = C.TypeTun - metadata.Source = upstreamMetadata.Source - metadata.Destination = upstreamMetadata.Destination + metadata.Source = source + metadata.Destination = destination + metadata.InboundOptions = t.inboundOptions + t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) + t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) + t.router.RouteConnectionEx(ctx, conn, metadata, onClose) +} + +func (t *TUN) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + ctx = log.ContextWithNewID(ctx) + var metadata adapter.InboundContext + metadata.Inbound = t.tag + metadata.InboundType = C.TypeTun + metadata.Source = source + metadata.Destination = destination metadata.InboundOptions = t.inboundOptions t.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source) t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) - err := t.router.RoutePacketConnection(ctx, conn, metadata) - if err != nil { - t.NewError(ctx, err) - } - return nil + t.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose) } -func (t *Tun) NewError(ctx context.Context, err error) { - NewError(t.logger, ctx, err) +type autoRedirectHandler TUN + +func (t *autoRedirectHandler) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + ctx = log.ContextWithNewID(ctx) + var metadata adapter.InboundContext + metadata.Inbound = t.tag + metadata.InboundType = C.TypeTun + metadata.Source = source + metadata.Destination = destination + metadata.InboundOptions = t.inboundOptions + t.logger.InfoContext(ctx, "inbound redirect connection from ", metadata.Source) + t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) + t.router.RouteConnectionEx(ctx, conn, metadata, onClose) } diff --git a/sing-box/inbound/vless.go b/sing-box/inbound/vless.go index 567475647a..90fdae8158 100644 --- a/sing-box/inbound/vless.go +++ b/sing-box/inbound/vless.go @@ -25,8 +25,8 @@ import ( ) var ( - _ adapter.Inbound = (*VLESS)(nil) - _ adapter.InjectableInbound = (*VLESS)(nil) + _ adapter.Inbound = (*VLESS)(nil) + _ adapter.TCPInjectableInbound = (*VLESS)(nil) ) type VLESS struct { @@ -144,8 +144,12 @@ func (h *VLESS) NewConnection(ctx context.Context, conn net.Conn, metadata adapt return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) } -func (h *VLESS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (h *VLESS) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.NewConnection(ctx, conn, metadata) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } } func (h *VLESS) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { diff --git a/sing-box/inbound/vmess.go b/sing-box/inbound/vmess.go index 154512751c..8e6d493927 100644 --- a/sing-box/inbound/vmess.go +++ b/sing-box/inbound/vmess.go @@ -25,8 +25,8 @@ import ( ) var ( - _ adapter.Inbound = (*VMess)(nil) - _ adapter.InjectableInbound = (*VMess)(nil) + _ adapter.Inbound = (*VMess)(nil) + _ adapter.TCPInjectableInbound = (*VMess)(nil) ) type VMess struct { @@ -158,8 +158,12 @@ func (h *VMess) NewConnection(ctx context.Context, conn net.Conn, metadata adapt return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) } -func (h *VMess) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid +func (h *VMess) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := h.NewConnection(ctx, conn, metadata) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source)) + } } func (h *VMess) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { diff --git a/sing-box/option/inbound.go b/sing-box/option/inbound.go index 54e8bab84a..d38799048f 100644 --- a/sing-box/option/inbound.go +++ b/sing-box/option/inbound.go @@ -98,6 +98,7 @@ func (h *Inbound) UnmarshalJSON(bytes []byte) error { return nil } +// Deprecated: Use rule action instead type InboundOptions struct { SniffEnabled bool `json:"sniff,omitempty"` SniffOverrideDestination bool `json:"sniff_override_destination,omitempty"` diff --git a/sing-box/option/rule.go b/sing-box/option/rule.go index 5f15645c9b..98e9891391 100644 --- a/sing-box/option/rule.go +++ b/sing-box/option/rule.go @@ -64,7 +64,7 @@ func (r Rule) IsValid() bool { } } -type _DefaultRule struct { +type RawDefaultRule struct { Inbound Listable[string] `json:"inbound,omitempty"` IPVersion int `json:"ip_version,omitempty"` Network Listable[string] `json:"network,omitempty"` @@ -98,16 +98,22 @@ type _DefaultRule struct { RuleSet Listable[string] `json:"rule_set,omitempty"` RuleSetIPCIDRMatchSource bool `json:"rule_set_ip_cidr_match_source,omitempty"` Invert bool `json:"invert,omitempty"` - Outbound string `json:"outbound,omitempty"` // Deprecated: renamed to rule_set_ip_cidr_match_source Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"` } -type DefaultRule _DefaultRule +type DefaultRule struct { + RawDefaultRule + RuleAction +} -func (r *DefaultRule) UnmarshalJSON(bytes []byte) error { - err := json.Unmarshal(bytes, (*_DefaultRule)(r)) +func (r *DefaultRule) MarshalJSON() ([]byte, error) { + return MarshallObjects(r.RawDefaultRule, r.RuleAction) +} + +func (r *DefaultRule) UnmarshalJSON(data []byte) error { + err := json.Unmarshal(data, &r.RawDefaultRule) if err != nil { return err } @@ -117,23 +123,39 @@ func (r *DefaultRule) UnmarshalJSON(bytes []byte) error { r.Deprecated_RulesetIPCIDRMatchSource = false r.RuleSetIPCIDRMatchSource = true } - return nil + return UnmarshallExcluded(data, &r.RawDefaultRule, &r.RuleAction) } func (r *DefaultRule) IsValid() bool { var defaultValue DefaultRule defaultValue.Invert = r.Invert - defaultValue.Outbound = r.Outbound + defaultValue.Action = r.Action return !reflect.DeepEqual(r, defaultValue) } -type LogicalRule struct { - Mode string `json:"mode"` - Rules []Rule `json:"rules,omitempty"` - Invert bool `json:"invert,omitempty"` - Outbound string `json:"outbound,omitempty"` +type _LogicalRule struct { + Mode string `json:"mode"` + Rules []Rule `json:"rules,omitempty"` + Invert bool `json:"invert,omitempty"` } -func (r LogicalRule) IsValid() bool { +type LogicalRule struct { + _LogicalRule + RuleAction +} + +func (r *LogicalRule) MarshalJSON() ([]byte, error) { + return MarshallObjects(r._LogicalRule, r.RuleAction) +} + +func (r *LogicalRule) UnmarshalJSON(data []byte) error { + err := json.Unmarshal(data, &r._LogicalRule) + if err != nil { + return err + } + return UnmarshallExcluded(data, &r._LogicalRule, &r.RuleAction) +} + +func (r *LogicalRule) IsValid() bool { return len(r.Rules) > 0 && common.All(r.Rules, Rule.IsValid) } diff --git a/sing-box/option/rule_action.go b/sing-box/option/rule_action.go new file mode 100644 index 0000000000..4f0ec177b8 --- /dev/null +++ b/sing-box/option/rule_action.go @@ -0,0 +1,166 @@ +package option + +import ( + C "github.com/sagernet/sing-box/constant" + E "github.com/sagernet/sing/common/exceptions" + "github.com/sagernet/sing/common/json" +) + +type _RuleAction struct { + Action string `json:"action,omitempty"` + RouteOptions RouteActionOptions `json:"-"` + RejectOptions RejectActionOptions `json:"-"` + SniffOptions RouteActionSniff `json:"-"` + ResolveOptions RouteActionResolve `json:"-"` +} + +type RuleAction _RuleAction + +func (r RuleAction) MarshalJSON() ([]byte, error) { + var v any + switch r.Action { + case C.RuleActionTypeRoute: + r.Action = "" + v = r.RouteOptions + case C.RuleActionTypeReturn: + v = nil + case C.RuleActionTypeReject: + v = r.RejectOptions + case C.RuleActionTypeHijackDNS: + v = nil + case C.RuleActionTypeSniff: + v = r.SniffOptions + case C.RuleActionTypeResolve: + v = r.ResolveOptions + default: + return nil, E.New("unknown rule action: " + r.Action) + } + if v == nil { + return MarshallObjects((_RuleAction)(r)) + } + return MarshallObjects((_RuleAction)(r), v) +} + +func (r *RuleAction) UnmarshalJSON(data []byte) error { + err := json.Unmarshal(data, (*_RuleAction)(r)) + if err != nil { + return err + } + var v any + switch r.Action { + case "", C.RuleActionTypeRoute: + r.Action = C.RuleActionTypeRoute + v = &r.RouteOptions + case C.RuleActionTypeReturn: + v = nil + case C.RuleActionTypeReject: + v = &r.RejectOptions + case C.RuleActionTypeHijackDNS: + v = nil + case C.RuleActionTypeSniff: + v = &r.SniffOptions + case C.RuleActionTypeResolve: + v = &r.ResolveOptions + default: + return E.New("unknown rule action: " + r.Action) + } + if v == nil { + // check unknown fields + return json.UnmarshalDisallowUnknownFields(data, &_RuleAction{}) + } + return UnmarshallExcluded(data, (*_RuleAction)(r), v) +} + +type _DNSRuleAction struct { + Action string `json:"action,omitempty"` + RouteOptions DNSRouteActionOptions `json:"-"` + RejectOptions RejectActionOptions `json:"-"` + SniffOptions RouteActionSniff `json:"-"` + ResolveOptions RouteActionResolve `json:"-"` +} + +type DNSRuleAction _DNSRuleAction + +func (r DNSRuleAction) MarshalJSON() ([]byte, error) { + var v any + switch r.Action { + case C.RuleActionTypeRoute: + r.Action = "" + v = r.RouteOptions + case C.RuleActionTypeReturn: + v = nil + case C.RuleActionTypeReject: + v = r.RejectOptions + default: + return nil, E.New("unknown DNS rule action: " + r.Action) + } + if v == nil { + return MarshallObjects((_DNSRuleAction)(r)) + } + return MarshallObjects((_DNSRuleAction)(r), v) +} + +func (r *DNSRuleAction) UnmarshalJSON(data []byte) error { + err := json.Unmarshal(data, (*_DNSRuleAction)(r)) + if err != nil { + return err + } + var v any + switch r.Action { + case "", C.RuleActionTypeRoute: + r.Action = C.RuleActionTypeRoute + v = &r.RouteOptions + case C.RuleActionTypeReturn: + v = nil + case C.RuleActionTypeReject: + v = &r.RejectOptions + default: + return E.New("unknown DNS rule action: " + r.Action) + } + if v == nil { + // check unknown fields + return json.UnmarshalDisallowUnknownFields(data, &_DNSRuleAction{}) + } + return UnmarshallExcluded(data, (*_DNSRuleAction)(r), v) +} + +type RouteActionOptions struct { + Outbound string `json:"outbound"` + UDPDisableDomainUnmapping bool `json:"udp_disable_domain_unmapping,omitempty"` +} + +type DNSRouteActionOptions struct { + Server string `json:"server"` + DisableCache bool `json:"disable_cache,omitempty"` + RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"` + ClientSubnet *AddrPrefix `json:"client_subnet,omitempty"` +} + +type RejectActionOptions struct { + Method RejectMethod `json:"method,omitempty"` +} + +type RejectMethod string + +func (m *RejectMethod) UnmarshalJSON(bytes []byte) error { + err := json.Unmarshal(bytes, (*string)(m)) + if err != nil { + return err + } + switch *m { + case C.RuleActionRejectMethodDefault, C.RuleActionRejectMethodPortUnreachable, C.RuleActionRejectMethodDrop: + return nil + default: + return E.New("unknown reject method: " + *m) + } +} + +type RouteActionSniff struct { + Sniffer Listable[string] `json:"sniffer,omitempty"` + Timeout Duration `json:"timeout,omitempty"` +} + +type RouteActionResolve struct { + Strategy DomainStrategy `json:"strategy,omitempty"` + Server string `json:"server,omitempty"` +} diff --git a/sing-box/option/rule_dns.go b/sing-box/option/rule_dns.go index 2e03b4252e..85a3764d86 100644 --- a/sing-box/option/rule_dns.go +++ b/sing-box/option/rule_dns.go @@ -64,7 +64,7 @@ func (r DNSRule) IsValid() bool { } } -type _DefaultDNSRule struct { +type RawDefaultDNSRule struct { Inbound Listable[string] `json:"inbound,omitempty"` IPVersion int `json:"ip_version,omitempty"` QueryType Listable[DNSQueryType] `json:"query_type,omitempty"` @@ -100,19 +100,22 @@ type _DefaultDNSRule struct { RuleSetIPCIDRMatchSource bool `json:"rule_set_ip_cidr_match_source,omitempty"` RuleSetIPCIDRAcceptEmpty bool `json:"rule_set_ip_cidr_accept_empty,omitempty"` Invert bool `json:"invert,omitempty"` - Server string `json:"server,omitempty"` - DisableCache bool `json:"disable_cache,omitempty"` - RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"` - ClientSubnet *AddrPrefix `json:"client_subnet,omitempty"` // Deprecated: renamed to rule_set_ip_cidr_match_source Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"` } -type DefaultDNSRule _DefaultDNSRule +type DefaultDNSRule struct { + RawDefaultDNSRule + DNSRuleAction +} -func (r *DefaultDNSRule) UnmarshalJSON(bytes []byte) error { - err := json.UnmarshalDisallowUnknownFields(bytes, (*_DefaultDNSRule)(r)) +func (r *DefaultDNSRule) MarshalJSON() ([]byte, error) { + return MarshallObjects(r.RawDefaultDNSRule, r.DNSRuleAction) +} + +func (r *DefaultDNSRule) UnmarshalJSON(data []byte) error { + err := json.Unmarshal(data, &r.RawDefaultDNSRule) if err != nil { return err } @@ -122,29 +125,39 @@ func (r *DefaultDNSRule) UnmarshalJSON(bytes []byte) error { r.Deprecated_RulesetIPCIDRMatchSource = false r.RuleSetIPCIDRMatchSource = true } - return nil + return UnmarshallExcluded(data, &r.RawDefaultDNSRule, &r.DNSRuleAction) } func (r *DefaultDNSRule) IsValid() bool { var defaultValue DefaultDNSRule defaultValue.Invert = r.Invert - defaultValue.Server = r.Server - defaultValue.DisableCache = r.DisableCache - defaultValue.RewriteTTL = r.RewriteTTL - defaultValue.ClientSubnet = r.ClientSubnet + defaultValue.DNSRuleAction = r.DNSRuleAction return !reflect.DeepEqual(r, defaultValue) } -type LogicalDNSRule struct { - Mode string `json:"mode"` - Rules []DNSRule `json:"rules,omitempty"` - Invert bool `json:"invert,omitempty"` - Server string `json:"server,omitempty"` - DisableCache bool `json:"disable_cache,omitempty"` - RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"` - ClientSubnet *AddrPrefix `json:"client_subnet,omitempty"` +type _LogicalDNSRule struct { + Mode string `json:"mode"` + Rules []DNSRule `json:"rules,omitempty"` + Invert bool `json:"invert,omitempty"` } -func (r LogicalDNSRule) IsValid() bool { +type LogicalDNSRule struct { + _LogicalDNSRule + DNSRuleAction +} + +func (r *LogicalDNSRule) MarshalJSON() ([]byte, error) { + return MarshallObjects(r._LogicalDNSRule, r.DNSRuleAction) +} + +func (r *LogicalDNSRule) UnmarshalJSON(data []byte) error { + err := json.Unmarshal(data, &r._LogicalDNSRule) + if err != nil { + return err + } + return UnmarshallExcluded(data, &r._LogicalDNSRule, &r.DNSRuleAction) +} + +func (r *LogicalDNSRule) IsValid() bool { return len(r.Rules) > 0 && common.All(r.Rules, DNSRule.IsValid) } diff --git a/sing-box/option/types.go b/sing-box/option/types.go index b17f222248..bb6485491e 100644 --- a/sing-box/option/types.go +++ b/sing-box/option/types.go @@ -81,8 +81,11 @@ func (a *AddrPrefix) UnmarshalJSON(content []byte) error { return prefixErr } -func (a AddrPrefix) Build() netip.Prefix { - return netip.Prefix(a) +func (a *AddrPrefix) Build() netip.Prefix { + if a == nil { + return netip.Prefix{} + } + return netip.Prefix(*a) } type NetworkList string @@ -143,12 +146,29 @@ func (l *Listable[T]) UnmarshalJSON(content []byte) error { type DomainStrategy dns.DomainStrategy +func (s DomainStrategy) String() string { + switch dns.DomainStrategy(s) { + case dns.DomainStrategyAsIS: + return "" + case dns.DomainStrategyPreferIPv4: + return "prefer_ipv4" + case dns.DomainStrategyPreferIPv6: + return "prefer_ipv6" + case dns.DomainStrategyUseIPv4: + return "ipv4_only" + case dns.DomainStrategyUseIPv6: + return "ipv6_only" + default: + panic(E.New("unknown domain strategy: ", s)) + } +} + func (s DomainStrategy) MarshalJSON() ([]byte, error) { var value string switch dns.DomainStrategy(s) { case dns.DomainStrategyAsIS: value = "" - // value = "AsIS" + // value = "as_is" case dns.DomainStrategyPreferIPv4: value = "prefer_ipv4" case dns.DomainStrategyPreferIPv6: diff --git a/sing-box/outbound/block.go b/sing-box/outbound/block.go index e73c44228b..b6ccefe2be 100644 --- a/sing-box/outbound/block.go +++ b/sing-box/outbound/block.go @@ -39,12 +39,14 @@ func (h *Block) ListenPacket(ctx context.Context, destination M.Socksaddr) (net. return nil, io.EOF } +// Deprecated func (h *Block) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { conn.Close() h.logger.InfoContext(ctx, "blocked connection to ", metadata.Destination) return nil } +// Deprecated func (h *Block) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { conn.Close() h.logger.InfoContext(ctx, "blocked packet connection to ", metadata.Destination) diff --git a/sing-box/outbound/default.go b/sing-box/outbound/default.go index 972aca9479..d036cf8c87 100644 --- a/sing-box/outbound/default.go +++ b/sing-box/outbound/default.go @@ -124,7 +124,7 @@ func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn, } if destinationAddress.IsValid() { if metadata.Destination.IsFqdn() { - if metadata.InboundOptions.UDPDisableDomainUnmapping { + if metadata.UDPDisableDomainUnmapping { outConn = bufio.NewUnidirectionalNATPacketConn(bufio.NewPacketConn(outConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), metadata.Destination) } else { outConn = bufio.NewNATPacketConn(bufio.NewPacketConn(outConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), metadata.Destination) diff --git a/sing-box/outbound/direct.go b/sing-box/outbound/direct.go index 11f650e4d9..f160ce698e 100644 --- a/sing-box/outbound/direct.go +++ b/sing-box/outbound/direct.go @@ -30,7 +30,7 @@ type Direct struct { fallbackDelay time.Duration overrideOption int overrideDestination M.Socksaddr - loopBack *loopBackDetector + // loopBack *loopBackDetector } func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) { @@ -51,7 +51,7 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti domainStrategy: dns.DomainStrategy(options.DomainStrategy), fallbackDelay: time.Duration(options.FallbackDelay), dialer: outboundDialer, - loopBack: newLoopBackDetector(router), + // loopBack: newLoopBackDetector(router), } if options.ProxyProtocol != 0 { return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0") @@ -90,11 +90,12 @@ func (h *Direct) DialContext(ctx context.Context, network string, destination M. case N.NetworkUDP: h.logger.InfoContext(ctx, "outbound packet connection to ", destination) } - conn, err := h.dialer.DialContext(ctx, network, destination) + /*conn, err := h.dialer.DialContext(ctx, network, destination) if err != nil { return nil, err } - return h.loopBack.NewConn(conn), nil + return h.loopBack.NewConn(conn), nil*/ + return h.dialer.DialContext(ctx, network, destination) } func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) { @@ -148,14 +149,14 @@ func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net if err != nil { return nil, err } - conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn), destination) + // conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn), destination) if originDestination != destination { conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination) } return conn, nil } -func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { +/*func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) { return E.New("reject loopback connection to ", metadata.Destination) } @@ -168,3 +169,4 @@ func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, met } return NewPacketConnection(ctx, h, conn, metadata) } +*/ diff --git a/sing-box/outbound/dns.go b/sing-box/outbound/dns.go index 6ad4a0f8ce..08661a99aa 100644 --- a/sing-box/outbound/dns.go +++ b/sing-box/outbound/dns.go @@ -45,6 +45,7 @@ func (d *DNS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.Pa return nil, os.ErrInvalid } +// Deprecated func (d *DNS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { metadata.Destination = M.Socksaddr{} defer conn.Close() @@ -97,6 +98,7 @@ func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adap return nil } +// Deprecated func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { metadata.Destination = M.Socksaddr{} var reader N.PacketReader = conn diff --git a/sing-box/outbound/http.go b/sing-box/outbound/http.go index cfc03216fa..8b54136699 100644 --- a/sing-box/outbound/http.go +++ b/sing-box/outbound/http.go @@ -64,11 +64,3 @@ func (h *HTTP) DialContext(ctx context.Context, network string, destination M.So func (h *HTTP) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { return nil, os.ErrInvalid } - -func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *HTTP) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid -} diff --git a/sing-box/outbound/hysteria.go b/sing-box/outbound/hysteria.go index cf7f7fed11..f513cf64ed 100644 --- a/sing-box/outbound/hysteria.go +++ b/sing-box/outbound/hysteria.go @@ -122,14 +122,6 @@ func (h *Hysteria) ListenPacket(ctx context.Context, destination M.Socksaddr) (n return h.client.ListenPacket(ctx, destination) } -func (h *Hysteria) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *Hysteria) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return NewPacketConnection(ctx, h, conn, metadata) -} - func (h *Hysteria) InterfaceUpdated() { h.client.CloseWithError(E.New("network changed")) } diff --git a/sing-box/outbound/hysteria2.go b/sing-box/outbound/hysteria2.go index 9079e40308..5e46f6a866 100644 --- a/sing-box/outbound/hysteria2.go +++ b/sing-box/outbound/hysteria2.go @@ -108,14 +108,6 @@ func (h *Hysteria2) ListenPacket(ctx context.Context, destination M.Socksaddr) ( return h.client.ListenPacket(ctx) } -func (h *Hysteria2) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *Hysteria2) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return NewPacketConnection(ctx, h, conn, metadata) -} - func (h *Hysteria2) InterfaceUpdated() { h.client.CloseWithError(E.New("network changed")) } diff --git a/sing-box/outbound/selector.go b/sing-box/outbound/selector.go index e801daeadc..59e940dfa0 100644 --- a/sing-box/outbound/selector.go +++ b/sing-box/outbound/selector.go @@ -142,14 +142,26 @@ func (s *Selector) ListenPacket(ctx context.Context, destination M.Socksaddr) (n return s.interruptGroup.NewPacketConn(conn, interrupt.IsExternalConnectionFromContext(ctx)), nil } +// TODO +// Deprecated func (s *Selector) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { ctx = interrupt.ContextWithIsExternalConnection(ctx) - return s.selected.NewConnection(ctx, conn, metadata) + if legacyHandler, ok := s.selected.(adapter.ConnectionHandler); ok { + return legacyHandler.NewConnection(ctx, conn, metadata) + } else { + return NewConnection(ctx, s.selected, conn, metadata) + } } +// TODO +// Deprecated func (s *Selector) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { ctx = interrupt.ContextWithIsExternalConnection(ctx) - return s.selected.NewPacketConnection(ctx, conn, metadata) + if legacyHandler, ok := s.selected.(adapter.PacketConnectionHandler); ok { + return legacyHandler.NewPacketConnection(ctx, conn, metadata) + } else { + return NewPacketConnection(ctx, s.selected, conn, metadata) + } } func RealTag(detour adapter.Outbound) string { diff --git a/sing-box/outbound/shadowsocks.go b/sing-box/outbound/shadowsocks.go index addb6e576f..e38e01ae41 100644 --- a/sing-box/outbound/shadowsocks.go +++ b/sing-box/outbound/shadowsocks.go @@ -125,14 +125,6 @@ func (h *Shadowsocks) ListenPacket(ctx context.Context, destination M.Socksaddr) } } -func (h *Shadowsocks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *Shadowsocks) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return NewPacketConnection(ctx, h, conn, metadata) -} - func (h *Shadowsocks) InterfaceUpdated() { if h.multiplexDialer != nil { h.multiplexDialer.Reset() diff --git a/sing-box/outbound/shadowtls.go b/sing-box/outbound/shadowtls.go index 4427301c40..5845516a90 100644 --- a/sing-box/outbound/shadowtls.go +++ b/sing-box/outbound/shadowtls.go @@ -106,11 +106,3 @@ func (h *ShadowTLS) DialContext(ctx context.Context, network string, destination func (h *ShadowTLS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { return nil, os.ErrInvalid } - -func (h *ShadowTLS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *ShadowTLS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid -} diff --git a/sing-box/outbound/socks.go b/sing-box/outbound/socks.go index 063f7b952a..19f3ae1f7b 100644 --- a/sing-box/outbound/socks.go +++ b/sing-box/outbound/socks.go @@ -113,6 +113,8 @@ func (h *Socks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net. return h.client.ListenPacket(ctx, destination) } +// TODO +// Deprecated func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { if h.resolve { return NewDirectConnection(ctx, h.router, h, conn, metadata, dns.DomainStrategyUseIPv4) @@ -121,6 +123,8 @@ func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, metadata adapt } } +// TODO +// Deprecated func (h *Socks) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { if h.resolve { return NewDirectPacketConnection(ctx, h.router, h, conn, metadata, dns.DomainStrategyUseIPv4) diff --git a/sing-box/outbound/ssh.go b/sing-box/outbound/ssh.go index ce62b00481..28abe9a5e3 100644 --- a/sing-box/outbound/ssh.go +++ b/sing-box/outbound/ssh.go @@ -199,11 +199,3 @@ func (s *SSH) DialContext(ctx context.Context, network string, destination M.Soc func (s *SSH) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { return nil, os.ErrInvalid } - -func (s *SSH) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, s, conn, metadata) -} - -func (s *SSH) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid -} diff --git a/sing-box/outbound/tor.go b/sing-box/outbound/tor.go index 8ae73a66fa..ccc0c0cfe5 100644 --- a/sing-box/outbound/tor.go +++ b/sing-box/outbound/tor.go @@ -211,11 +211,3 @@ func (t *Tor) DialContext(ctx context.Context, network string, destination M.Soc func (t *Tor) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { return nil, os.ErrInvalid } - -func (t *Tor) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, t, conn, metadata) -} - -func (t *Tor) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return os.ErrInvalid -} diff --git a/sing-box/outbound/trojan.go b/sing-box/outbound/trojan.go index 52d72757e1..abf799f482 100644 --- a/sing-box/outbound/trojan.go +++ b/sing-box/outbound/trojan.go @@ -99,14 +99,6 @@ func (h *Trojan) ListenPacket(ctx context.Context, destination M.Socksaddr) (net } } -func (h *Trojan) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *Trojan) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return NewPacketConnection(ctx, h, conn, metadata) -} - func (h *Trojan) InterfaceUpdated() { if h.transport != nil { h.transport.Close() diff --git a/sing-box/outbound/tuic.go b/sing-box/outbound/tuic.go index c098332375..aaf998b16e 100644 --- a/sing-box/outbound/tuic.go +++ b/sing-box/outbound/tuic.go @@ -136,14 +136,6 @@ func (h *TUIC) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.P } } -func (h *TUIC) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *TUIC) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return NewPacketConnection(ctx, h, conn, metadata) -} - func (h *TUIC) InterfaceUpdated() { _ = h.client.CloseWithError(E.New("network changed")) } diff --git a/sing-box/outbound/urltest.go b/sing-box/outbound/urltest.go index c6e38ec5a8..564a0ddc3a 100644 --- a/sing-box/outbound/urltest.go +++ b/sing-box/outbound/urltest.go @@ -167,11 +167,15 @@ func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (ne return nil, err } +// TODO +// Deprecated func (s *URLTest) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { ctx = interrupt.ContextWithIsExternalConnection(ctx) return NewConnection(ctx, s, conn, metadata) } +// TODO +// Deprecated func (s *URLTest) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { ctx = interrupt.ContextWithIsExternalConnection(ctx) return NewPacketConnection(ctx, s, conn, metadata) diff --git a/sing-box/outbound/vless.go b/sing-box/outbound/vless.go index 66080eafca..56a0522275 100644 --- a/sing-box/outbound/vless.go +++ b/sing-box/outbound/vless.go @@ -118,14 +118,6 @@ func (h *VLESS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net. } } -func (h *VLESS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *VLESS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return NewPacketConnection(ctx, h, conn, metadata) -} - func (h *VLESS) InterfaceUpdated() { if h.transport != nil { h.transport.Close() diff --git a/sing-box/outbound/vmess.go b/sing-box/outbound/vmess.go index c7d88b9040..5946041131 100644 --- a/sing-box/outbound/vmess.go +++ b/sing-box/outbound/vmess.go @@ -146,14 +146,6 @@ func (h *VMess) ListenPacket(ctx context.Context, destination M.Socksaddr) (net. } } -func (h *VMess) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewConnection(ctx, h, conn, metadata) -} - -func (h *VMess) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return NewPacketConnection(ctx, h, conn, metadata) -} - type vmessDialer VMess func (h *vmessDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { diff --git a/sing-box/outbound/wireguard.go b/sing-box/outbound/wireguard.go index 3ae3f63b36..8eb043f476 100644 --- a/sing-box/outbound/wireguard.go +++ b/sing-box/outbound/wireguard.go @@ -234,10 +234,14 @@ func (w *WireGuard) ListenPacket(ctx context.Context, destination M.Socksaddr) ( return w.tunDevice.ListenPacket(ctx, destination) } +// TODO +// Deprecated func (w *WireGuard) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { return NewDirectConnection(ctx, w.router, w, conn, metadata, dns.DomainStrategyAsIS) } +// TODO +// Deprecated func (w *WireGuard) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { return NewDirectPacketConnection(ctx, w.router, w, conn, metadata, dns.DomainStrategyAsIS) } diff --git a/sing-box/route/router_geo_resources.go b/sing-box/route/geo_resources.go similarity index 98% rename from sing-box/route/router_geo_resources.go rename to sing-box/route/geo_resources.go index 42de84d00a..9193da3366 100644 --- a/sing-box/route/router_geo_resources.go +++ b/sing-box/route/geo_resources.go @@ -14,6 +14,7 @@ import ( "github.com/sagernet/sing-box/common/geosite" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/experimental/deprecated" + R "github.com/sagernet/sing-box/route/rule" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" "github.com/sagernet/sing/common/rw" @@ -33,7 +34,7 @@ func (r *Router) LoadGeosite(code string) (adapter.Rule, error) { if err != nil { return nil, err } - rule, err = NewDefaultRule(r, nil, geosite.Compile(items)) + rule, err = R.NewDefaultRule(r, nil, geosite.Compile(items)) if err != nil { return nil, err } diff --git a/sing-box/route/route.go b/sing-box/route/route.go new file mode 100644 index 0000000000..da3d78f8ef --- /dev/null +++ b/sing-box/route/route.go @@ -0,0 +1,573 @@ +package route + +import ( + "context" + "errors" + "net" + "net/netip" + "os" + "os/user" + "strings" + "syscall" + "time" + + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/conntrack" + "github.com/sagernet/sing-box/common/process" + "github.com/sagernet/sing-box/common/sniff" + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-box/outbound" + "github.com/sagernet/sing-box/route/rule" + "github.com/sagernet/sing-dns" + "github.com/sagernet/sing-mux" + "github.com/sagernet/sing-tun" + "github.com/sagernet/sing-vmess" + "github.com/sagernet/sing/common" + "github.com/sagernet/sing/common/buf" + "github.com/sagernet/sing/common/bufio" + "github.com/sagernet/sing/common/bufio/deadline" + E "github.com/sagernet/sing/common/exceptions" + F "github.com/sagernet/sing/common/format" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" + "github.com/sagernet/sing/common/uot" +) + +// Deprecated: use RouteConnectionEx instead. +func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { + err := r.routeConnection(ctx, conn, metadata, nil) + if err != nil { + conn.Close() + r.logger.ErrorContext(ctx, err) + } + return nil +} + +func (r *Router) RouteConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := r.routeConnection(ctx, conn, metadata, onClose) + if err != nil { + N.CloseOnHandshakeFailure(conn, onClose, err) + r.logger.ErrorContext(ctx, err) + } +} + +func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error { + if r.pauseManager.IsDevicePaused() { + return E.New("reject connection to ", metadata.Destination, " while device paused") + } + + if metadata.InboundDetour != "" { + if metadata.LastInbound == metadata.InboundDetour { + return E.New("routing loop on detour: ", metadata.InboundDetour) + } + detour := r.inboundByTag[metadata.InboundDetour] + if detour == nil { + return E.New("inbound detour not found: ", metadata.InboundDetour) + } + injectable, isInjectable := detour.(adapter.TCPInjectableInbound) + if !isInjectable { + return E.New("inbound detour is not TCP injectable: ", metadata.InboundDetour) + } + metadata.LastInbound = metadata.Inbound + metadata.Inbound = metadata.InboundDetour + metadata.InboundDetour = "" + injectable.NewConnectionEx(ctx, conn, metadata, onClose) + return nil + } + conntrack.KillerCheck() + metadata.Network = N.NetworkTCP + switch metadata.Destination.Fqdn { + case mux.Destination.Fqdn: + return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in inbound options instead.") + case vmess.MuxDestination.Fqdn: + return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.") + case uot.MagicAddress: + return E.New("global UoT not supported since sing-box v1.7.0.") + case uot.LegacyMagicAddress: + return E.New("global UoT (legacy) not supported since sing-box v1.7.0.") + } + if deadline.NeedAdditionalReadDeadline(conn) { + conn = deadline.NewConn(conn) + } + selectedRule, selectedRuleIndex, buffers, err := r.matchRule(ctx, &metadata, conn, nil, -1) + if err != nil { + return err + } + var selectedOutbound adapter.Outbound + var selectReturn bool + if selectedRule != nil { + r.logger.DebugContext(ctx, "match[", selectedRuleIndex, "] ", selectedRule.String(), " => ", selectedRule.Action().String()) + switch action := selectedRule.Action().(type) { + case *rule.RuleActionRoute: + var loaded bool + selectedOutbound, loaded = r.Outbound(action.Outbound) + if !loaded { + buf.ReleaseMulti(buffers) + return E.New("outbound not found: ", action.Outbound) + } + case *rule.RuleActionReturn: + selectReturn = true + case *rule.RuleActionReject: + buf.ReleaseMulti(buffers) + var rejectErr error + switch action.Method { + case C.RuleActionRejectMethodDefault: + rejectErr = os.ErrClosed + case C.RuleActionRejectMethodPortUnreachable: + rejectErr = syscall.ECONNREFUSED + case C.RuleActionRejectMethodDrop: + rejectErr = tun.ErrDrop + } + N.CloseOnHandshakeFailure(conn, onClose, rejectErr) + return nil + } + } + if selectedRule == nil || selectReturn { + if r.defaultOutboundForConnection == nil { + buf.ReleaseMulti(buffers) + return E.New("missing default outbound with TCP support") + } + selectedOutbound = r.defaultOutboundForConnection + } + if !common.Contains(selectedOutbound.Network(), N.NetworkTCP) { + buf.ReleaseMulti(buffers) + return E.New("TCP is not supported by outbound: ", selectedOutbound.Tag()) + } + for _, buffer := range common.Reverse(buffers) { + conn = bufio.NewCachedConn(conn, buffer) + } + if r.clashServer != nil { + trackerConn, tracker := r.clashServer.RoutedConnection(ctx, conn, metadata, selectedRule) + defer tracker.Leave() + conn = trackerConn + } + if r.v2rayServer != nil { + if statsService := r.v2rayServer.StatsService(); statsService != nil { + conn = statsService.RoutedConnection(metadata.Inbound, selectedOutbound.Tag(), metadata.User, conn) + } + } + legacyOutbound, isLegacy := selectedOutbound.(adapter.ConnectionHandler) + if isLegacy { + err = legacyOutbound.NewConnection(ctx, conn, metadata) + if err != nil { + conn.Close() + if onClose != nil { + onClose(err) + } + return E.Cause(err, "outbound/", selectedOutbound.Type(), "[", selectedOutbound.Tag(), "]") + } else { + if onClose != nil { + onClose(nil) + } + } + return nil + } + // TODO + err = outbound.NewConnection(ctx, selectedOutbound, conn, metadata) + if err != nil { + conn.Close() + if onClose != nil { + onClose(err) + } + return E.Cause(err, "outbound/", selectedOutbound.Type(), "[", selectedOutbound.Tag(), "]") + } else { + if onClose != nil { + onClose(nil) + } + } + return nil +} + +func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { + err := r.routePacketConnection(ctx, conn, metadata, nil) + if err != nil { + conn.Close() + r.logger.ErrorContext(ctx, err) + } + return nil +} + +func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { + err := r.routePacketConnection(ctx, conn, metadata, onClose) + if err != nil { + N.CloseOnHandshakeFailure(conn, onClose, err) + r.logger.ErrorContext(ctx, err) + } else if onClose != nil { + onClose(nil) + } +} + +func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error { + if r.pauseManager.IsDevicePaused() { + return E.New("reject packet connection to ", metadata.Destination, " while device paused") + } + if metadata.InboundDetour != "" { + if metadata.LastInbound == metadata.InboundDetour { + return E.New("routing loop on detour: ", metadata.InboundDetour) + } + detour := r.inboundByTag[metadata.InboundDetour] + if detour == nil { + return E.New("inbound detour not found: ", metadata.InboundDetour) + } + injectable, isInjectable := detour.(adapter.UDPInjectableInbound) + if !isInjectable { + return E.New("inbound detour is not UDP injectable: ", metadata.InboundDetour) + } + metadata.LastInbound = metadata.Inbound + metadata.Inbound = metadata.InboundDetour + metadata.InboundDetour = "" + injectable.NewPacketConnectionEx(ctx, conn, metadata, onClose) + return nil + } + conntrack.KillerCheck() + + // TODO: move to UoT + metadata.Network = N.NetworkUDP + + // Currently we don't have deadline usages for UDP connections + /*if deadline.NeedAdditionalReadDeadline(conn) { + conn = deadline.NewPacketConn(bufio.NewNetPacketConn(conn)) + }*/ + + selectedRule, selectedRuleIndex, buffers, err := r.matchRule(ctx, &metadata, nil, conn, -1) + if err != nil { + return err + } + var selectedOutbound adapter.Outbound + if selectedRule != nil { + r.logger.DebugContext(ctx, "match[", selectedRuleIndex, "] ", selectedRule.String(), " => ", selectedRule.Action().String()) + switch action := selectedRule.Action().(type) { + case *rule.RuleActionRoute: + var loaded bool + selectedOutbound, loaded = r.Outbound(action.Outbound) + if !loaded { + buf.ReleaseMulti(buffers) + return E.New("outbound not found: ", action.Outbound) + } + metadata.UDPDisableDomainUnmapping = action.UDPDisableDomainUnmapping + case *rule.RuleActionReturn: + if r.defaultOutboundForPacketConnection == nil { + buf.ReleaseMulti(buffers) + return E.New("missing default outbound with UDP support") + } + selectedOutbound = r.defaultOutboundForPacketConnection + case *rule.RuleActionReject: + buf.ReleaseMulti(buffers) + N.CloseOnHandshakeFailure(conn, onClose, syscall.ECONNREFUSED) + return nil + } + } + if !common.Contains(selectedOutbound.Network(), N.NetworkUDP) { + buf.ReleaseMulti(buffers) + return E.New("UDP is not supported by outbound: ", selectedOutbound.Tag()) + } + for _, buffer := range common.Reverse(buffers) { + // TODO: check if metadata.Destination == packet destination + conn = bufio.NewCachedPacketConn(conn, buffer, metadata.Destination) + } + if r.clashServer != nil { + trackerConn, tracker := r.clashServer.RoutedPacketConnection(ctx, conn, metadata, selectedRule) + defer tracker.Leave() + conn = trackerConn + } + if r.v2rayServer != nil { + if statsService := r.v2rayServer.StatsService(); statsService != nil { + conn = statsService.RoutedPacketConnection(metadata.Inbound, selectedOutbound.Tag(), metadata.User, conn) + } + } + if metadata.FakeIP { + conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination) + } + legacyOutbound, isLegacy := selectedOutbound.(adapter.PacketConnectionHandler) + if isLegacy { + err = legacyOutbound.NewPacketConnection(ctx, conn, metadata) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + return E.Cause(err, "outbound/", selectedOutbound.Type(), "[", selectedOutbound.Tag(), "]") + } + return nil + } + // TODO + err = outbound.NewPacketConnection(ctx, selectedOutbound, conn, metadata) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + return E.Cause(err, "outbound/", selectedOutbound.Type(), "[", selectedOutbound.Tag(), "]") + } + return nil +} + +func (r *Router) matchRule( + ctx context.Context, metadata *adapter.InboundContext, + inputConn net.Conn, inputPacketConn N.PacketConn, ruleIndex int, +) (selectedRule adapter.Rule, selectedRuleIndex int, buffers []*buf.Buffer, fatalErr error) { + if r.processSearcher != nil && metadata.ProcessInfo == nil { + var originDestination netip.AddrPort + if metadata.OriginDestination.IsValid() { + originDestination = metadata.OriginDestination.AddrPort() + } else if metadata.Destination.IsIP() { + originDestination = metadata.Destination.AddrPort() + } + processInfo, fErr := process.FindProcessInfo(r.processSearcher, ctx, metadata.Network, metadata.Source.AddrPort(), originDestination) + if fErr != nil { + r.logger.InfoContext(ctx, "failed to search process: ", fErr) + } else { + if processInfo.ProcessPath != "" { + r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath) + } else if processInfo.PackageName != "" { + r.logger.InfoContext(ctx, "found package name: ", processInfo.PackageName) + } else if processInfo.UserId != -1 { + if /*needUserName &&*/ true { + osUser, _ := user.LookupId(F.ToString(processInfo.UserId)) + if osUser != nil { + processInfo.User = osUser.Username + } + } + if processInfo.User != "" { + r.logger.InfoContext(ctx, "found user: ", processInfo.User) + } else { + r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId) + } + } + metadata.ProcessInfo = processInfo + } + } + if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) { + domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr) + if !loaded { + fatalErr = E.New("missing fakeip record, try to configure experimental.cache_file") + return + } + metadata.OriginDestination = metadata.Destination + metadata.Destination = M.Socksaddr{ + Fqdn: domain, + Port: metadata.Destination.Port, + } + metadata.FakeIP = true + r.logger.DebugContext(ctx, "found fakeip domain: ", domain) + } + if r.dnsReverseMapping != nil && metadata.Domain == "" { + domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr) + if loaded { + metadata.Domain = domain + r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain) + } + } + if metadata.Destination.IsIPv4() { + metadata.IPVersion = 4 + } else if metadata.Destination.IsIPv6() { + metadata.IPVersion = 6 + } + + //goland:noinspection GoDeprecation + if metadata.InboundOptions != common.DefaultValue[option.InboundOptions]() { + if metadata.InboundOptions.SniffEnabled { + newBuffers, newErr := r.actionSniff(ctx, metadata, &rule.RuleActionSniff{ + OverrideDestination: metadata.InboundOptions.SniffOverrideDestination, + Timeout: time.Duration(metadata.InboundOptions.SniffTimeout), + }, inputConn, inputPacketConn) + if newErr != nil { + fatalErr = newErr + return + } + buffers = append(buffers, newBuffers...) + } + if dns.DomainStrategy(metadata.InboundOptions.DomainStrategy) != dns.DomainStrategyAsIS { + fatalErr = r.actionResolve(ctx, metadata, &rule.RuleActionResolve{ + Strategy: dns.DomainStrategy(metadata.InboundOptions.DomainStrategy), + }) + if fatalErr != nil { + return + } + } + if metadata.InboundOptions.UDPDisableDomainUnmapping { + metadata.UDPDisableDomainUnmapping = true + } + metadata.InboundOptions = option.InboundOptions{} + } + +match: + for ruleIndex < len(r.rules) { + rules := r.rules + if ruleIndex != -1 { + rules = rules[ruleIndex+1:] + } + var ( + currentRule adapter.Rule + currentRuleIndex int + matched bool + ) + for currentRuleIndex, currentRule = range rules { + if currentRule.Match(metadata) { + matched = true + break + } + } + if !matched { + break + } + switch action := currentRule.Action().(type) { + case *rule.RuleActionSniff: + newBuffers, newErr := r.actionSniff(ctx, metadata, action, inputConn, inputPacketConn) + if newErr != nil { + fatalErr = newErr + return + } + buffers = append(buffers, newBuffers...) + case *rule.RuleActionResolve: + fatalErr = r.actionResolve(ctx, metadata, action) + if fatalErr != nil { + return + } + default: + selectedRule = currentRule + selectedRuleIndex = currentRuleIndex + break match + } + ruleIndex = currentRuleIndex + } + if metadata.Destination.Addr.IsUnspecified() { + newBuffers, newErr := r.actionSniff(ctx, metadata, &rule.RuleActionSniff{}, inputConn, inputPacketConn) + if newErr != nil { + fatalErr = newErr + return + } + buffers = append(buffers, newBuffers...) + } + return +} + +func (r *Router) actionSniff( + ctx context.Context, metadata *adapter.InboundContext, action *rule.RuleActionSniff, + inputConn net.Conn, inputPacketConn N.PacketConn, +) (buffers []*buf.Buffer, fatalErr error) { + if sniff.Skip(metadata) { + return + } else if inputConn != nil && len(action.StreamSniffers) > 0 { + buffer := buf.NewPacket() + err := sniff.PeekStream( + ctx, + metadata, + inputConn, + buffer, + action.Timeout, + action.StreamSniffers..., + ) + if err == nil { + //goland:noinspection GoDeprecation + if action.OverrideDestination && M.IsDomainName(metadata.Domain) { + metadata.Destination = M.Socksaddr{ + Fqdn: metadata.Domain, + Port: metadata.Destination.Port, + } + } + if metadata.Domain != "" && metadata.Client != "" { + r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client) + } else if metadata.Domain != "" { + r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain) + } else { + r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol) + } + } + if !buffer.IsEmpty() { + buffers = append(buffers, buffer) + } else { + buffer.Release() + } + } else if inputPacketConn != nil && len(action.PacketSniffers) > 0 { + for { + var ( + buffer = buf.NewPacket() + destination M.Socksaddr + done = make(chan struct{}) + err error + ) + go func() { + sniffTimeout := C.ReadPayloadTimeout + if action.Timeout > 0 { + sniffTimeout = action.Timeout + } + inputPacketConn.SetReadDeadline(time.Now().Add(sniffTimeout)) + destination, err = inputPacketConn.ReadPacket(buffer) + inputPacketConn.SetReadDeadline(time.Time{}) + close(done) + }() + select { + case <-done: + case <-ctx.Done(): + inputPacketConn.Close() + fatalErr = ctx.Err() + return + } + if err != nil { + buffer.Release() + if !errors.Is(err, os.ErrDeadlineExceeded) { + fatalErr = err + return + } + } else { + // TODO: maybe always override destination + if metadata.Destination.Addr.IsUnspecified() { + metadata.Destination = destination + } + if len(buffers) > 0 { + err = sniff.PeekPacket( + ctx, + metadata, + buffer.Bytes(), + sniff.QUICClientHello, + ) + } else { + err = sniff.PeekPacket( + ctx, metadata, + buffer.Bytes(), + action.PacketSniffers..., + ) + } + buffers = append(buffers, buffer) + if E.IsMulti(err, sniff.ErrClientHelloFragmented) && len(buffers) == 0 { + r.logger.DebugContext(ctx, "attempt to sniff fragmented QUIC client hello") + continue + } + if metadata.Protocol != "" { + //goland:noinspection GoDeprecation + if action.OverrideDestination && M.IsDomainName(metadata.Domain) { + metadata.Destination = M.Socksaddr{ + Fqdn: metadata.Domain, + Port: metadata.Destination.Port, + } + } + if metadata.Domain != "" && metadata.Client != "" { + r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client) + } else if metadata.Domain != "" { + r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain) + } else if metadata.Client != "" { + r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", client: ", metadata.Client) + } else { + r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol) + } + } + } + break + } + } + return +} + +func (r *Router) actionResolve(ctx context.Context, metadata *adapter.InboundContext, action *rule.RuleActionResolve) error { + if metadata.Destination.IsFqdn() { + // TODO: check if WithContext is necessary + addresses, err := r.Lookup(adapter.WithContext(ctx, metadata), metadata.Destination.Fqdn, action.Strategy) + if err != nil { + return err + } + metadata.DestinationAddresses = addresses + r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]") + if metadata.Destination.IsIPv4() { + metadata.IPVersion = 4 + } else if metadata.Destination.IsIPv6() { + metadata.IPVersion = 6 + } + } + return nil +} diff --git a/sing-box/route/router_dns.go b/sing-box/route/route_dns.go similarity index 75% rename from sing-box/route/router_dns.go rename to sing-box/route/route_dns.go index ead8c28943..43eb61e6df 100644 --- a/sing-box/route/router_dns.go +++ b/sing-box/route/route_dns.go @@ -8,6 +8,7 @@ import ( "time" "github.com/sagernet/sing-box/adapter" + R "github.com/sagernet/sing-box/route/rule" "github.com/sagernet/sing-dns" "github.com/sagernet/sing/common/cache" E "github.com/sagernet/sing/common/exceptions" @@ -36,15 +37,16 @@ func (m *DNSReverseMapping) Query(address netip.Addr) (string, bool) { return domain, loaded } -func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, index int, isAddressQuery bool) (context.Context, dns.Transport, dns.DomainStrategy, adapter.DNSRule, int) { +func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, ruleIndex int, isAddressQuery bool) (dns.Transport, dns.QueryOptions, adapter.DNSRule, int) { metadata := adapter.ContextFrom(ctx) if metadata == nil { panic("no context") } - if index < len(r.dnsRules) { + var options dns.QueryOptions + if ruleIndex < len(r.dnsRules) { dnsRules := r.dnsRules - if index != -1 { - dnsRules = dnsRules[index+1:] + if ruleIndex != -1 { + dnsRules = dnsRules[ruleIndex+1:] } for currentRuleIndex, rule := range dnsRules { if rule.WithAddressLimit() && !isAddressQuery { @@ -52,43 +54,42 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, index int, isAd } metadata.ResetRuleCache() if rule.Match(metadata) { - detour := rule.Outbound() - transport, loaded := r.transportMap[detour] - if !loaded { - r.dnsLogger.ErrorContext(ctx, "transport not found: ", detour) - continue + displayRuleIndex := currentRuleIndex + if displayRuleIndex != -1 { + displayRuleIndex += displayRuleIndex + 1 } - _, isFakeIP := transport.(adapter.FakeIPTransport) - if isFakeIP && !allowFakeIP { - continue - } - ruleIndex := currentRuleIndex - if index != -1 { - ruleIndex += index + 1 - } - r.dnsLogger.DebugContext(ctx, "match[", ruleIndex, "] ", rule.String(), " => ", detour) - if isFakeIP || rule.DisableCache() { - ctx = dns.ContextWithDisableCache(ctx, true) - } - if rewriteTTL := rule.RewriteTTL(); rewriteTTL != nil { - ctx = dns.ContextWithRewriteTTL(ctx, *rewriteTTL) - } - if clientSubnet := rule.ClientSubnet(); clientSubnet != nil { - ctx = dns.ContextWithClientSubnet(ctx, *clientSubnet) - } - if domainStrategy, dsLoaded := r.transportDomainStrategy[transport]; dsLoaded { - return ctx, transport, domainStrategy, rule, ruleIndex + if routeAction, isRoute := rule.Action().(*R.RuleActionDNSRoute); isRoute { + transport, loaded := r.transportMap[routeAction.Server] + if !loaded { + r.dnsLogger.ErrorContext(ctx, "transport not found: ", routeAction.Server) + continue + } + _, isFakeIP := transport.(adapter.FakeIPTransport) + if isFakeIP && !allowFakeIP { + continue + } + options.DisableCache = isFakeIP || routeAction.DisableCache + options.RewriteTTL = routeAction.RewriteTTL + options.ClientSubnet = routeAction.ClientSubnet + if domainStrategy, dsLoaded := r.transportDomainStrategy[transport]; dsLoaded { + options.Strategy = domainStrategy + } else { + options.Strategy = r.defaultDomainStrategy + } + r.dnsLogger.DebugContext(ctx, "match[", displayRuleIndex, "] ", rule.String(), " => ", rule.Action()) + return transport, options, rule, currentRuleIndex } else { - return ctx, transport, r.defaultDomainStrategy, rule, ruleIndex + return nil, options, rule, currentRuleIndex } } } } if domainStrategy, dsLoaded := r.transportDomainStrategy[r.defaultTransport]; dsLoaded { - return ctx, r.defaultTransport, domainStrategy, nil, -1 + options.Strategy = domainStrategy } else { - return ctx, r.defaultTransport, r.defaultDomainStrategy, nil, -1 + options.Strategy = r.defaultDomainStrategy } + return r.defaultTransport, options, nil, -1 } func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) { @@ -117,21 +118,18 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er metadata.Domain = fqdnToDomain(message.Question[0].Name) } var ( - strategy dns.DomainStrategy + options dns.QueryOptions rule adapter.DNSRule ruleIndex int ) ruleIndex = -1 for { - var ( - dnsCtx context.Context - addressLimit bool - ) - dnsCtx, transport, strategy, rule, ruleIndex = r.matchDNS(ctx, true, ruleIndex, isAddressQuery(message)) - dnsCtx = adapter.OverrideContext(dnsCtx) + dnsCtx := adapter.OverrideContext(ctx) + var addressLimit bool + transport, options, rule, ruleIndex = r.matchDNS(ctx, true, ruleIndex, isAddressQuery(message)) if rule != nil && rule.WithAddressLimit() { addressLimit = true - response, err = r.dnsClient.ExchangeWithResponseCheck(dnsCtx, transport, message, strategy, func(response *mDNS.Msg) bool { + response, err = r.dnsClient.ExchangeWithResponseCheck(dnsCtx, transport, message, options, func(response *mDNS.Msg) bool { addresses, addrErr := dns.MessageToAddresses(response) if addrErr != nil { return false @@ -141,7 +139,7 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er }) } else { addressLimit = false - response, err = r.dnsClient.Exchange(dnsCtx, transport, message, strategy) + response, err = r.dnsClient.Exchange(dnsCtx, transport, message, options) } var rejected bool if err != nil { @@ -199,31 +197,28 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS metadata.Destination = M.Socksaddr{} metadata.Domain = domain var ( - transport dns.Transport - transportStrategy dns.DomainStrategy - rule adapter.DNSRule - ruleIndex int + transport dns.Transport + options dns.QueryOptions + rule adapter.DNSRule + ruleIndex int ) ruleIndex = -1 for { - var ( - dnsCtx context.Context - addressLimit bool - ) - dnsCtx, transport, transportStrategy, rule, ruleIndex = r.matchDNS(ctx, false, ruleIndex, true) - dnsCtx = adapter.OverrideContext(dnsCtx) - if strategy == dns.DomainStrategyAsIS { - strategy = transportStrategy + dnsCtx := adapter.OverrideContext(ctx) + var addressLimit bool + transport, options, rule, ruleIndex = r.matchDNS(ctx, false, ruleIndex, true) + if strategy != dns.DomainStrategyAsIS { + options.Strategy = strategy } if rule != nil && rule.WithAddressLimit() { addressLimit = true - responseAddrs, err = r.dnsClient.LookupWithResponseCheck(dnsCtx, transport, domain, strategy, func(responseAddrs []netip.Addr) bool { + responseAddrs, err = r.dnsClient.LookupWithResponseCheck(dnsCtx, transport, domain, options, func(responseAddrs []netip.Addr) bool { metadata.DestinationAddresses = responseAddrs return rule.MatchAddressLimit(metadata) }) } else { addressLimit = false - responseAddrs, err = r.dnsClient.Lookup(dnsCtx, transport, domain, strategy) + responseAddrs, err = r.dnsClient.Lookup(dnsCtx, transport, domain, options) } if err != nil { if errors.Is(err, dns.ErrResponseRejectedCached) { diff --git a/sing-box/route/router.go b/sing-box/route/router.go index c8fe94be5b..835c15369c 100644 --- a/sing-box/route/router.go +++ b/sing-box/route/router.go @@ -3,11 +3,9 @@ package route import ( "context" "errors" - "net" "net/netip" "net/url" "os" - "os/user" "runtime" "strings" "time" @@ -18,22 +16,16 @@ import ( "github.com/sagernet/sing-box/common/geoip" "github.com/sagernet/sing-box/common/geosite" "github.com/sagernet/sing-box/common/process" - "github.com/sagernet/sing-box/common/sniff" "github.com/sagernet/sing-box/common/taskmonitor" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" - "github.com/sagernet/sing-box/outbound" + R "github.com/sagernet/sing-box/route/rule" "github.com/sagernet/sing-box/transport/fakeip" "github.com/sagernet/sing-dns" - "github.com/sagernet/sing-mux" "github.com/sagernet/sing-tun" - "github.com/sagernet/sing-vmess" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/buf" - "github.com/sagernet/sing/common/bufio" - "github.com/sagernet/sing/common/bufio/deadline" "github.com/sagernet/sing/common/control" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" @@ -41,7 +33,6 @@ import ( N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/ntp" "github.com/sagernet/sing/common/task" - "github.com/sagernet/sing/common/uot" "github.com/sagernet/sing/common/winpowrprof" "github.com/sagernet/sing/service" "github.com/sagernet/sing/service/pause" @@ -153,14 +144,14 @@ func NewRouter( Logger: router.dnsLogger, }) for i, ruleOptions := range options.Rules { - routeRule, err := NewRule(router, router.logger, ruleOptions, true) + routeRule, err := R.NewRule(router, router.logger, ruleOptions, true) if err != nil { return nil, E.Cause(err, "parse rule[", i, "]") } router.rules = append(router.rules, routeRule) } for i, dnsRuleOptions := range dnsOptions.Rules { - dnsRule, err := NewDNSRule(router, router.logger, dnsRuleOptions, true) + dnsRule, err := R.NewDNSRule(router, router.logger, dnsRuleOptions, true) if err != nil { return nil, E.Cause(err, "parse dns rule[", i, "]") } @@ -170,7 +161,7 @@ func NewRouter( if _, exists := router.ruleSetMap[ruleSetOptions.Tag]; exists { return nil, E.New("duplicate rule-set tag: ", ruleSetOptions.Tag) } - ruleSet, err := NewRuleSet(ctx, router, router.logger, ruleSetOptions) + ruleSet, err := R.NewRuleSet(ctx, router, router.logger, ruleSetOptions) if err != nil { return nil, E.Cause(err, "parse rule-set[", i, "]") } @@ -429,8 +420,12 @@ func (r *Router) Initialize(inbounds []adapter.Inbound, outbounds []adapter.Outb r.defaultOutboundForPacketConnection = defaultOutboundForPacketConnection r.outboundByTag = outboundByTag for i, rule := range r.rules { - if _, loaded := outboundByTag[rule.Outbound()]; !loaded { - return E.New("outbound not found for rule[", i, "]: ", rule.Outbound()) + routeAction, isRoute := rule.Action().(*R.RuleActionRoute) + if !isRoute { + continue + } + if _, loaded := outboundByTag[routeAction.Outbound]; !loaded { + return E.New("outbound not found for rule[", i, "]: ", routeAction.Outbound) } } return nil @@ -661,7 +656,7 @@ func (r *Router) PostStart() error { monitor := taskmonitor.New(r.logger, C.StopTimeout) if len(r.ruleSets) > 0 { monitor.Start("initialize rule-set") - ruleSetStartContext := NewRuleSetStartContext() + ruleSetStartContext := R.NewRuleSetStartContext() var ruleSetStartGroup task.Group for i, ruleSet := range r.ruleSets { ruleSetInPlace := ruleSet @@ -793,375 +788,6 @@ func (r *Router) NeedWIFIState() bool { return r.needWIFIState } -func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - if r.pauseManager.IsDevicePaused() { - return E.New("reject connection to ", metadata.Destination, " while device paused") - } - - if metadata.InboundDetour != "" { - if metadata.LastInbound == metadata.InboundDetour { - return E.New("routing loop on detour: ", metadata.InboundDetour) - } - detour := r.inboundByTag[metadata.InboundDetour] - if detour == nil { - return E.New("inbound detour not found: ", metadata.InboundDetour) - } - injectable, isInjectable := detour.(adapter.InjectableInbound) - if !isInjectable { - return E.New("inbound detour is not injectable: ", metadata.InboundDetour) - } - if !common.Contains(injectable.Network(), N.NetworkTCP) { - return E.New("inject: TCP unsupported") - } - metadata.LastInbound = metadata.Inbound - metadata.Inbound = metadata.InboundDetour - metadata.InboundDetour = "" - err := injectable.NewConnection(ctx, conn, metadata) - if err != nil { - return E.Cause(err, "inject ", detour.Tag()) - } - return nil - } - conntrack.KillerCheck() - metadata.Network = N.NetworkTCP - switch metadata.Destination.Fqdn { - case mux.Destination.Fqdn: - return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in inbound options instead.") - case vmess.MuxDestination.Fqdn: - return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.") - case uot.MagicAddress: - return E.New("global UoT not supported since sing-box v1.7.0.") - case uot.LegacyMagicAddress: - return E.New("global UoT (legacy) not supported since sing-box v1.7.0.") - } - - if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) { - domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr) - if !loaded { - return E.New("missing fakeip context") - } - metadata.OriginDestination = metadata.Destination - metadata.Destination = M.Socksaddr{ - Fqdn: domain, - Port: metadata.Destination.Port, - } - metadata.FakeIP = true - r.logger.DebugContext(ctx, "found fakeip domain: ", domain) - } - - if deadline.NeedAdditionalReadDeadline(conn) { - conn = deadline.NewConn(conn) - } - - if metadata.InboundOptions.SniffEnabled && !sniff.Skip(metadata) { - buffer := buf.NewPacket() - err := sniff.PeekStream( - ctx, - &metadata, - conn, - buffer, - time.Duration(metadata.InboundOptions.SniffTimeout), - sniff.TLSClientHello, - sniff.HTTPHost, - sniff.StreamDomainNameQuery, - sniff.SSH, - sniff.BitTorrent, - ) - if err == nil { - if metadata.InboundOptions.SniffOverrideDestination && M.IsDomainName(metadata.Domain) { - metadata.Destination = M.Socksaddr{ - Fqdn: metadata.Domain, - Port: metadata.Destination.Port, - } - } - if metadata.Domain != "" { - r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain) - } else { - r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol) - } - } - if !buffer.IsEmpty() { - conn = bufio.NewCachedConn(conn, buffer) - } else { - buffer.Release() - } - } - - if r.dnsReverseMapping != nil && metadata.Domain == "" { - domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr) - if loaded { - metadata.Domain = domain - r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain) - } - } - - if metadata.Destination.IsFqdn() && dns.DomainStrategy(metadata.InboundOptions.DomainStrategy) != dns.DomainStrategyAsIS { - addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, dns.DomainStrategy(metadata.InboundOptions.DomainStrategy)) - if err != nil { - return err - } - metadata.DestinationAddresses = addresses - r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]") - } - if metadata.Destination.IsIPv4() { - metadata.IPVersion = 4 - } else if metadata.Destination.IsIPv6() { - metadata.IPVersion = 6 - } - ctx, matchedRule, detour, err := r.match(ctx, &metadata, r.defaultOutboundForConnection) - if err != nil { - return err - } - if !common.Contains(detour.Network(), N.NetworkTCP) { - return E.New("missing supported outbound, closing connection") - } - if r.clashServer != nil { - trackerConn, tracker := r.clashServer.RoutedConnection(ctx, conn, metadata, matchedRule) - defer tracker.Leave() - conn = trackerConn - } - if r.v2rayServer != nil { - if statsService := r.v2rayServer.StatsService(); statsService != nil { - conn = statsService.RoutedConnection(metadata.Inbound, detour.Tag(), metadata.User, conn) - } - } - return detour.NewConnection(ctx, conn, metadata) -} - -func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - if r.pauseManager.IsDevicePaused() { - return E.New("reject packet connection to ", metadata.Destination, " while device paused") - } - if metadata.InboundDetour != "" { - if metadata.LastInbound == metadata.InboundDetour { - return E.New("routing loop on detour: ", metadata.InboundDetour) - } - detour := r.inboundByTag[metadata.InboundDetour] - if detour == nil { - return E.New("inbound detour not found: ", metadata.InboundDetour) - } - injectable, isInjectable := detour.(adapter.InjectableInbound) - if !isInjectable { - return E.New("inbound detour is not injectable: ", metadata.InboundDetour) - } - if !common.Contains(injectable.Network(), N.NetworkUDP) { - return E.New("inject: UDP unsupported") - } - metadata.LastInbound = metadata.Inbound - metadata.Inbound = metadata.InboundDetour - metadata.InboundDetour = "" - err := injectable.NewPacketConnection(ctx, conn, metadata) - if err != nil { - return E.Cause(err, "inject ", detour.Tag()) - } - return nil - } - conntrack.KillerCheck() - metadata.Network = N.NetworkUDP - - if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) { - domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr) - if !loaded { - return E.New("missing fakeip context") - } - metadata.OriginDestination = metadata.Destination - metadata.Destination = M.Socksaddr{ - Fqdn: domain, - Port: metadata.Destination.Port, - } - metadata.FakeIP = true - r.logger.DebugContext(ctx, "found fakeip domain: ", domain) - } - - // Currently we don't have deadline usages for UDP connections - /*if deadline.NeedAdditionalReadDeadline(conn) { - conn = deadline.NewPacketConn(bufio.NewNetPacketConn(conn)) - }*/ - - if metadata.InboundOptions.SniffEnabled || metadata.Destination.Addr.IsUnspecified() { - var bufferList []*buf.Buffer - for { - var ( - buffer = buf.NewPacket() - destination M.Socksaddr - done = make(chan struct{}) - err error - ) - go func() { - sniffTimeout := C.ReadPayloadTimeout - if metadata.InboundOptions.SniffTimeout > 0 { - sniffTimeout = time.Duration(metadata.InboundOptions.SniffTimeout) - } - conn.SetReadDeadline(time.Now().Add(sniffTimeout)) - destination, err = conn.ReadPacket(buffer) - conn.SetReadDeadline(time.Time{}) - close(done) - }() - select { - case <-done: - case <-ctx.Done(): - conn.Close() - return ctx.Err() - } - if err != nil { - buffer.Release() - if !errors.Is(err, os.ErrDeadlineExceeded) { - return err - } - } else { - if metadata.Destination.Addr.IsUnspecified() { - metadata.Destination = destination - } - if metadata.InboundOptions.SniffEnabled { - if len(bufferList) > 0 { - err = sniff.PeekPacket( - ctx, - &metadata, - buffer.Bytes(), - sniff.QUICClientHello, - ) - } else { - err = sniff.PeekPacket( - ctx, &metadata, - buffer.Bytes(), - sniff.DomainNameQuery, - sniff.QUICClientHello, - sniff.STUNMessage, - sniff.UTP, - sniff.UDPTracker, - sniff.DTLSRecord) - } - if E.IsMulti(err, sniff.ErrClientHelloFragmented) && len(bufferList) == 0 { - bufferList = append(bufferList, buffer) - r.logger.DebugContext(ctx, "attempt to sniff fragmented QUIC client hello") - continue - } - if metadata.Protocol != "" { - if metadata.InboundOptions.SniffOverrideDestination && M.IsDomainName(metadata.Domain) { - metadata.Destination = M.Socksaddr{ - Fqdn: metadata.Domain, - Port: metadata.Destination.Port, - } - } - if metadata.Domain != "" && metadata.Client != "" { - r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client) - } else if metadata.Domain != "" { - r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain) - } else if metadata.Client != "" { - r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", client: ", metadata.Client) - } else { - r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol) - } - } - } - conn = bufio.NewCachedPacketConn(conn, buffer, destination) - } - for _, cachedBuffer := range common.Reverse(bufferList) { - conn = bufio.NewCachedPacketConn(conn, cachedBuffer, destination) - } - break - } - } - if r.dnsReverseMapping != nil && metadata.Domain == "" { - domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr) - if loaded { - metadata.Domain = domain - r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain) - } - } - if metadata.Destination.IsFqdn() && dns.DomainStrategy(metadata.InboundOptions.DomainStrategy) != dns.DomainStrategyAsIS { - addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, dns.DomainStrategy(metadata.InboundOptions.DomainStrategy)) - if err != nil { - return err - } - metadata.DestinationAddresses = addresses - r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]") - } - if metadata.Destination.IsIPv4() { - metadata.IPVersion = 4 - } else if metadata.Destination.IsIPv6() { - metadata.IPVersion = 6 - } - ctx, matchedRule, detour, err := r.match(ctx, &metadata, r.defaultOutboundForPacketConnection) - if err != nil { - return err - } - if !common.Contains(detour.Network(), N.NetworkUDP) { - return E.New("missing supported outbound, closing packet connection") - } - if r.clashServer != nil { - trackerConn, tracker := r.clashServer.RoutedPacketConnection(ctx, conn, metadata, matchedRule) - defer tracker.Leave() - conn = trackerConn - } - if r.v2rayServer != nil { - if statsService := r.v2rayServer.StatsService(); statsService != nil { - conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), metadata.User, conn) - } - } - if metadata.FakeIP { - conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination) - } - return detour.NewPacketConnection(ctx, conn, metadata) -} - -func (r *Router) match(ctx context.Context, metadata *adapter.InboundContext, defaultOutbound adapter.Outbound) (context.Context, adapter.Rule, adapter.Outbound, error) { - matchRule, matchOutbound := r.match0(ctx, metadata, defaultOutbound) - if contextOutbound, loaded := outbound.TagFromContext(ctx); loaded { - if contextOutbound == matchOutbound.Tag() { - return nil, nil, nil, E.New("connection loopback in outbound/", matchOutbound.Type(), "[", matchOutbound.Tag(), "]") - } - } - ctx = outbound.ContextWithTag(ctx, matchOutbound.Tag()) - return ctx, matchRule, matchOutbound, nil -} - -func (r *Router) match0(ctx context.Context, metadata *adapter.InboundContext, defaultOutbound adapter.Outbound) (adapter.Rule, adapter.Outbound) { - if r.processSearcher != nil { - var originDestination netip.AddrPort - if metadata.OriginDestination.IsValid() { - originDestination = metadata.OriginDestination.AddrPort() - } else if metadata.Destination.IsIP() { - originDestination = metadata.Destination.AddrPort() - } - processInfo, err := process.FindProcessInfo(r.processSearcher, ctx, metadata.Network, metadata.Source.AddrPort(), originDestination) - if err != nil { - r.logger.InfoContext(ctx, "failed to search process: ", err) - } else { - if processInfo.ProcessPath != "" { - r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath) - } else if processInfo.PackageName != "" { - r.logger.InfoContext(ctx, "found package name: ", processInfo.PackageName) - } else if processInfo.UserId != -1 { - if /*needUserName &&*/ true { - osUser, _ := user.LookupId(F.ToString(processInfo.UserId)) - if osUser != nil { - processInfo.User = osUser.Username - } - } - if processInfo.User != "" { - r.logger.InfoContext(ctx, "found user: ", processInfo.User) - } else { - r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId) - } - } - metadata.ProcessInfo = processInfo - } - } - for i, rule := range r.rules { - metadata.ResetRuleCache() - if rule.Match(metadata) { - detour := rule.Outbound() - r.logger.DebugContext(ctx, "match[", i, "] ", rule.String(), " => ", detour) - if outbound, loaded := r.Outbound(detour); loaded { - return rule, outbound - } - r.logger.ErrorContext(ctx, "outbound not found: ", detour) - } - } - return nil, defaultOutbound -} - func (r *Router) InterfaceFinder() control.InterfaceFinder { return r.interfaceFinder } diff --git a/sing-box/route/rule_abstract.go b/sing-box/route/rule/rule_abstract.go similarity index 94% rename from sing-box/route/rule_abstract.go rename to sing-box/route/rule/rule_abstract.go index 9ef2e93277..6a56934188 100644 --- a/sing-box/route/rule_abstract.go +++ b/sing-box/route/rule/rule_abstract.go @@ -1,4 +1,4 @@ -package route +package rule import ( "io" @@ -20,7 +20,7 @@ type abstractDefaultRule struct { allItems []RuleItem ruleSetItem RuleItem invert bool - outbound string + action adapter.RuleAction } func (r *abstractDefaultRule) Type() string { @@ -150,8 +150,8 @@ func (r *abstractDefaultRule) Match(metadata *adapter.InboundContext) bool { return !r.invert } -func (r *abstractDefaultRule) Outbound() string { - return r.outbound +func (r *abstractDefaultRule) Action() adapter.RuleAction { + return r.action } func (r *abstractDefaultRule) String() string { @@ -163,10 +163,10 @@ func (r *abstractDefaultRule) String() string { } type abstractLogicalRule struct { - rules []adapter.HeadlessRule - mode string - invert bool - outbound string + rules []adapter.HeadlessRule + mode string + invert bool + action adapter.RuleAction } func (r *abstractLogicalRule) Type() string { @@ -231,8 +231,8 @@ func (r *abstractLogicalRule) Match(metadata *adapter.InboundContext) bool { } } -func (r *abstractLogicalRule) Outbound() string { - return r.outbound +func (r *abstractLogicalRule) Action() adapter.RuleAction { + return r.action } func (r *abstractLogicalRule) String() string { diff --git a/sing-box/route/rule/rule_action.go b/sing-box/route/rule/rule_action.go new file mode 100644 index 0000000000..e85fc76381 --- /dev/null +++ b/sing-box/route/rule/rule_action.go @@ -0,0 +1,228 @@ +package rule + +import ( + "net/netip" + "strings" + "time" + + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/sniff" + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-dns" + E "github.com/sagernet/sing/common/exceptions" + F "github.com/sagernet/sing/common/format" +) + +func NewRuleAction(action option.RuleAction) (adapter.RuleAction, error) { + switch action.Action { + case C.RuleActionTypeRoute: + return &RuleActionRoute{ + Outbound: action.RouteOptions.Outbound, + UDPDisableDomainUnmapping: action.RouteOptions.UDPDisableDomainUnmapping, + }, nil + case C.RuleActionTypeReturn: + return &RuleActionReject{}, nil + case C.RuleActionTypeReject: + return &RuleActionReject{ + Method: string(action.RejectOptions.Method), + }, nil + case C.RuleActionTypeHijackDNS: + return &RuleActionHijackDNS{}, nil + case C.RuleActionTypeSniff: + sniffAction := &RuleActionSniff{ + snifferNames: action.SniffOptions.Sniffer, + Timeout: time.Duration(action.SniffOptions.Timeout), + } + return sniffAction, sniffAction.build() + case C.RuleActionTypeResolve: + return &RuleActionResolve{ + Strategy: dns.DomainStrategy(action.ResolveOptions.Strategy), + Server: action.ResolveOptions.Server, + }, nil + default: + panic(F.ToString("unknown rule action: ", action.Action)) + } +} + +func NewDNSRuleAction(action option.DNSRuleAction) adapter.RuleAction { + switch action.Action { + case C.RuleActionTypeRoute: + return &RuleActionDNSRoute{ + Server: action.RouteOptions.Server, + DisableCache: action.RouteOptions.DisableCache, + RewriteTTL: action.RouteOptions.RewriteTTL, + ClientSubnet: action.RouteOptions.ClientSubnet.Build(), + } + case C.RuleActionTypeReturn: + return &RuleActionReturn{} + case C.RuleActionTypeReject: + return &RuleActionReject{ + Method: string(action.RejectOptions.Method), + } + default: + panic(F.ToString("unknown rule action: ", action.Action)) + } +} + +type RuleActionRoute struct { + Outbound string + UDPDisableDomainUnmapping bool +} + +func (r *RuleActionRoute) Type() string { + return C.RuleActionTypeRoute +} + +func (r *RuleActionRoute) String() string { + return F.ToString("route(", r.Outbound, ")") +} + +type RuleActionDNSRoute struct { + Server string + DisableCache bool + RewriteTTL *uint32 + ClientSubnet netip.Prefix +} + +func (r *RuleActionDNSRoute) Type() string { + return C.RuleActionTypeRoute +} + +func (r *RuleActionDNSRoute) String() string { + return F.ToString("route(", r.Server, ")") +} + +type RuleActionReturn struct{} + +func (r *RuleActionReturn) Type() string { + return C.RuleActionTypeReturn +} + +func (r *RuleActionReturn) String() string { + return "return" +} + +type RuleActionReject struct { + Method string +} + +func (r *RuleActionReject) Type() string { + return C.RuleActionTypeReject +} + +func (r *RuleActionReject) String() string { + if r.Method == C.RuleActionRejectMethodDefault { + return "reject" + } + return F.ToString("reject(", r.Method, ")") +} + +type RuleActionHijackDNS struct{} + +func (r *RuleActionHijackDNS) Type() string { + return C.RuleActionTypeHijackDNS +} + +func (r *RuleActionHijackDNS) String() string { + return "hijack-dns" +} + +type RuleActionSniff struct { + snifferNames []string + StreamSniffers []sniff.StreamSniffer + PacketSniffers []sniff.PacketSniffer + Timeout time.Duration + // Deprecated + OverrideDestination bool +} + +func (r *RuleActionSniff) Type() string { + return C.RuleActionTypeSniff +} + +func (r *RuleActionSniff) build() error { + if len(r.StreamSniffers) > 0 || len(r.PacketSniffers) > 0 { + return nil + } + if len(r.snifferNames) > 0 { + for _, name := range r.snifferNames { + switch name { + case C.ProtocolTLS: + r.StreamSniffers = append(r.StreamSniffers, sniff.TLSClientHello) + case C.ProtocolHTTP: + r.StreamSniffers = append(r.StreamSniffers, sniff.HTTPHost) + case C.ProtocolQUIC: + r.PacketSniffers = append(r.PacketSniffers, sniff.QUICClientHello) + case C.ProtocolDNS: + r.StreamSniffers = append(r.StreamSniffers, sniff.StreamDomainNameQuery) + r.PacketSniffers = append(r.PacketSniffers, sniff.DomainNameQuery) + case C.ProtocolSTUN: + r.PacketSniffers = append(r.PacketSniffers, sniff.STUNMessage) + case C.ProtocolBitTorrent: + r.StreamSniffers = append(r.StreamSniffers, sniff.BitTorrent) + r.PacketSniffers = append(r.PacketSniffers, sniff.UTP) + r.PacketSniffers = append(r.PacketSniffers, sniff.UDPTracker) + case C.ProtocolDTLS: + r.PacketSniffers = append(r.PacketSniffers, sniff.DTLSRecord) + case C.ProtocolSSH: + r.StreamSniffers = append(r.StreamSniffers, sniff.SSH) + case C.ProtocolRDP: + r.StreamSniffers = append(r.StreamSniffers, sniff.RDP) + default: + return E.New("unknown sniffer: ", name) + } + } + } else { + r.StreamSniffers = []sniff.StreamSniffer{ + sniff.TLSClientHello, + sniff.HTTPHost, + sniff.StreamDomainNameQuery, + sniff.BitTorrent, + sniff.SSH, + sniff.RDP, + } + r.PacketSniffers = []sniff.PacketSniffer{ + sniff.DomainNameQuery, + sniff.QUICClientHello, + sniff.STUNMessage, + sniff.UTP, + sniff.UDPTracker, + sniff.DTLSRecord, + } + } + return nil +} + +func (r *RuleActionSniff) String() string { + if len(r.snifferNames) == 0 && r.Timeout == 0 { + return "sniff" + } else if len(r.snifferNames) > 0 && r.Timeout == 0 { + return F.ToString("sniff(", strings.Join(r.snifferNames, ","), ")") + } else if len(r.snifferNames) == 0 && r.Timeout > 0 { + return F.ToString("sniff(", r.Timeout.String(), ")") + } else { + return F.ToString("sniff(", strings.Join(r.snifferNames, ","), ",", r.Timeout.String(), ")") + } +} + +type RuleActionResolve struct { + Strategy dns.DomainStrategy + Server string +} + +func (r *RuleActionResolve) Type() string { + return C.RuleActionTypeResolve +} + +func (r *RuleActionResolve) String() string { + if r.Strategy == dns.DomainStrategyAsIS && r.Server == "" { + return F.ToString("resolve") + } else if r.Strategy != dns.DomainStrategyAsIS && r.Server == "" { + return F.ToString("resolve(", option.DomainStrategy(r.Strategy).String(), ")") + } else if r.Strategy == dns.DomainStrategyAsIS && r.Server != "" { + return F.ToString("resolve(", r.Server, ")") + } else { + return F.ToString("resolve(", option.DomainStrategy(r.Strategy).String(), ",", r.Server, ")") + } +} diff --git a/sing-box/route/rule_default.go b/sing-box/route/rule/rule_default.go similarity index 88% rename from sing-box/route/rule_default.go rename to sing-box/route/rule/rule_default.go index 40b93e5f96..20667f3898 100644 --- a/sing-box/route/rule_default.go +++ b/sing-box/route/rule/rule_default.go @@ -1,4 +1,4 @@ -package route +package rule import ( "github.com/sagernet/sing-box/adapter" @@ -14,16 +14,22 @@ func NewRule(router adapter.Router, logger log.ContextLogger, options option.Rul if !options.DefaultOptions.IsValid() { return nil, E.New("missing conditions") } - if options.DefaultOptions.Outbound == "" && checkOutbound { - return nil, E.New("missing outbound field") + switch options.DefaultOptions.Action { + case "", C.RuleActionTypeRoute: + if options.DefaultOptions.RouteOptions.Outbound == "" && checkOutbound { + return nil, E.New("missing outbound field") + } } return NewDefaultRule(router, logger, options.DefaultOptions) case C.RuleTypeLogical: if !options.LogicalOptions.IsValid() { return nil, E.New("missing conditions") } - if options.LogicalOptions.Outbound == "" && checkOutbound { - return nil, E.New("missing outbound field") + switch options.LogicalOptions.Action { + case "", C.RuleActionTypeRoute: + if options.LogicalOptions.RouteOptions.Outbound == "" && checkOutbound { + return nil, E.New("missing outbound field") + } } return NewLogicalRule(router, logger, options.LogicalOptions) default: @@ -43,10 +49,14 @@ type RuleItem interface { } func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) { + action, err := NewRuleAction(options.RuleAction) + if err != nil { + return nil, E.Cause(err, "action") + } rule := &DefaultRule{ abstractDefaultRule{ - invert: options.Invert, - outbound: options.Outbound, + invert: options.Invert, + action: action, }, } if len(options.Inbound) > 0 { @@ -232,27 +242,31 @@ type LogicalRule struct { } func NewLogicalRule(router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) { - r := &LogicalRule{ + action, err := NewRuleAction(options.RuleAction) + if err != nil { + return nil, E.Cause(err, "action") + } + rule := &LogicalRule{ abstractLogicalRule{ - rules: make([]adapter.HeadlessRule, len(options.Rules)), - invert: options.Invert, - outbound: options.Outbound, + rules: make([]adapter.HeadlessRule, len(options.Rules)), + invert: options.Invert, + action: action, }, } switch options.Mode { case C.LogicalTypeAnd: - r.mode = C.LogicalTypeAnd + rule.mode = C.LogicalTypeAnd case C.LogicalTypeOr: - r.mode = C.LogicalTypeOr + rule.mode = C.LogicalTypeOr default: return nil, E.New("unknown logical mode: ", options.Mode) } - for i, subRule := range options.Rules { - rule, err := NewRule(router, logger, subRule, false) + for i, subOptions := range options.Rules { + subRule, err := NewRule(router, logger, subOptions, false) if err != nil { return nil, E.Cause(err, "sub rule[", i, "]") } - r.rules[i] = rule + rule.rules[i] = subRule } - return r, nil + return rule, nil } diff --git a/sing-box/route/rule_dns.go b/sing-box/route/rule/rule_dns.go similarity index 88% rename from sing-box/route/rule_dns.go rename to sing-box/route/rule/rule_dns.go index 616f956aaf..381f4e0d51 100644 --- a/sing-box/route/rule_dns.go +++ b/sing-box/route/rule/rule_dns.go @@ -1,8 +1,6 @@ -package route +package rule import ( - "net/netip" - "github.com/sagernet/sing-box/adapter" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" @@ -17,16 +15,22 @@ func NewDNSRule(router adapter.Router, logger log.ContextLogger, options option. if !options.DefaultOptions.IsValid() { return nil, E.New("missing conditions") } - if options.DefaultOptions.Server == "" && checkServer { - return nil, E.New("missing server field") + switch options.DefaultOptions.Action { + case "", C.RuleActionTypeRoute: + if options.DefaultOptions.RouteOptions.Server == "" && checkServer { + return nil, E.New("missing server field") + } } return NewDefaultDNSRule(router, logger, options.DefaultOptions) case C.RuleTypeLogical: if !options.LogicalOptions.IsValid() { return nil, E.New("missing conditions") } - if options.LogicalOptions.Server == "" && checkServer { - return nil, E.New("missing server field") + switch options.LogicalOptions.Action { + case "", C.RuleActionTypeRoute: + if options.LogicalOptions.RouteOptions.Server == "" && checkServer { + return nil, E.New("missing server field") + } } return NewLogicalDNSRule(router, logger, options.LogicalOptions) default: @@ -38,20 +42,14 @@ var _ adapter.DNSRule = (*DefaultDNSRule)(nil) type DefaultDNSRule struct { abstractDefaultRule - disableCache bool - rewriteTTL *uint32 - clientSubnet *netip.Prefix } func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) { rule := &DefaultDNSRule{ abstractDefaultRule: abstractDefaultRule{ - invert: options.Invert, - outbound: options.Server, + invert: options.Invert, + action: NewDNSRuleAction(options.DNSRuleAction), }, - disableCache: options.DisableCache, - rewriteTTL: options.RewriteTTL, - clientSubnet: (*netip.Prefix)(options.ClientSubnet), } if len(options.Inbound) > 0 { item := NewInboundRule(options.Inbound) @@ -234,16 +232,8 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options return rule, nil } -func (r *DefaultDNSRule) DisableCache() bool { - return r.disableCache -} - -func (r *DefaultDNSRule) RewriteTTL() *uint32 { - return r.rewriteTTL -} - -func (r *DefaultDNSRule) ClientSubnet() *netip.Prefix { - return r.clientSubnet +func (r *DefaultDNSRule) Action() adapter.RuleAction { + return r.action } func (r *DefaultDNSRule) WithAddressLimit() bool { @@ -278,21 +268,15 @@ var _ adapter.DNSRule = (*LogicalDNSRule)(nil) type LogicalDNSRule struct { abstractLogicalRule - disableCache bool - rewriteTTL *uint32 - clientSubnet *netip.Prefix } func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) { r := &LogicalDNSRule{ abstractLogicalRule: abstractLogicalRule{ - rules: make([]adapter.HeadlessRule, len(options.Rules)), - invert: options.Invert, - outbound: options.Server, + rules: make([]adapter.HeadlessRule, len(options.Rules)), + invert: options.Invert, + action: NewDNSRuleAction(options.DNSRuleAction), }, - disableCache: options.DisableCache, - rewriteTTL: options.RewriteTTL, - clientSubnet: (*netip.Prefix)(options.ClientSubnet), } switch options.Mode { case C.LogicalTypeAnd: @@ -312,16 +296,8 @@ func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options return r, nil } -func (r *LogicalDNSRule) DisableCache() bool { - return r.disableCache -} - -func (r *LogicalDNSRule) RewriteTTL() *uint32 { - return r.rewriteTTL -} - -func (r *LogicalDNSRule) ClientSubnet() *netip.Prefix { - return r.clientSubnet +func (r *LogicalDNSRule) Action() adapter.RuleAction { + return r.action } func (r *LogicalDNSRule) WithAddressLimit() bool { diff --git a/sing-box/route/rule_headless.go b/sing-box/route/rule/rule_headless.go similarity index 99% rename from sing-box/route/rule_headless.go rename to sing-box/route/rule/rule_headless.go index 23a98c7237..9ea357af8c 100644 --- a/sing-box/route/rule_headless.go +++ b/sing-box/route/rule/rule_headless.go @@ -1,4 +1,4 @@ -package route +package rule import ( "github.com/sagernet/sing-box/adapter" diff --git a/sing-box/route/rule_item_adguard.go b/sing-box/route/rule/rule_item_adguard.go similarity index 98% rename from sing-box/route/rule_item_adguard.go rename to sing-box/route/rule/rule_item_adguard.go index bdbb3b75fd..84252e606d 100644 --- a/sing-box/route/rule_item_adguard.go +++ b/sing-box/route/rule/rule_item_adguard.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_auth_user.go b/sing-box/route/rule/rule_item_auth_user.go similarity index 98% rename from sing-box/route/rule_item_auth_user.go rename to sing-box/route/rule/rule_item_auth_user.go index fbe053e6be..5799e3c718 100644 --- a/sing-box/route/rule_item_auth_user.go +++ b/sing-box/route/rule/rule_item_auth_user.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_cidr.go b/sing-box/route/rule/rule_item_cidr.go similarity index 99% rename from sing-box/route/rule_item_cidr.go rename to sing-box/route/rule/rule_item_cidr.go index be0bb1369c..c823dcf30a 100644 --- a/sing-box/route/rule_item_cidr.go +++ b/sing-box/route/rule/rule_item_cidr.go @@ -1,4 +1,4 @@ -package route +package rule import ( "net/netip" diff --git a/sing-box/route/rule_item_clash_mode.go b/sing-box/route/rule/rule_item_clash_mode.go similarity index 97% rename from sing-box/route/rule_item_clash_mode.go rename to sing-box/route/rule/rule_item_clash_mode.go index 70141f1116..aa5126cbde 100644 --- a/sing-box/route/rule_item_clash_mode.go +++ b/sing-box/route/rule/rule_item_clash_mode.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_client.go b/sing-box/route/rule/rule_item_client.go similarity index 98% rename from sing-box/route/rule_item_client.go rename to sing-box/route/rule/rule_item_client.go index eeab440240..63ff410355 100644 --- a/sing-box/route/rule_item_client.go +++ b/sing-box/route/rule/rule_item_client.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_domain.go b/sing-box/route/rule/rule_item_domain.go similarity index 99% rename from sing-box/route/rule_item_domain.go rename to sing-box/route/rule/rule_item_domain.go index c77890df24..b7655a7942 100644 --- a/sing-box/route/rule_item_domain.go +++ b/sing-box/route/rule/rule_item_domain.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_domain_keyword.go b/sing-box/route/rule/rule_item_domain_keyword.go similarity index 98% rename from sing-box/route/rule_item_domain_keyword.go rename to sing-box/route/rule/rule_item_domain_keyword.go index c6ca1e8c28..6e19a10ccd 100644 --- a/sing-box/route/rule_item_domain_keyword.go +++ b/sing-box/route/rule/rule_item_domain_keyword.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_domain_regex.go b/sing-box/route/rule/rule_item_domain_regex.go similarity index 99% rename from sing-box/route/rule_item_domain_regex.go rename to sing-box/route/rule/rule_item_domain_regex.go index b3555168a2..b9752a45ad 100644 --- a/sing-box/route/rule_item_domain_regex.go +++ b/sing-box/route/rule/rule_item_domain_regex.go @@ -1,4 +1,4 @@ -package route +package rule import ( "regexp" diff --git a/sing-box/route/rule_item_geoip.go b/sing-box/route/rule/rule_item_geoip.go similarity index 99% rename from sing-box/route/rule_item_geoip.go rename to sing-box/route/rule/rule_item_geoip.go index 3611613a48..3c967fec5f 100644 --- a/sing-box/route/rule_item_geoip.go +++ b/sing-box/route/rule/rule_item_geoip.go @@ -1,4 +1,4 @@ -package route +package rule import ( "net/netip" diff --git a/sing-box/route/rule_item_geosite.go b/sing-box/route/rule/rule_item_geosite.go similarity index 98% rename from sing-box/route/rule_item_geosite.go rename to sing-box/route/rule/rule_item_geosite.go index 5fdbfe5962..9e5e03c819 100644 --- a/sing-box/route/rule_item_geosite.go +++ b/sing-box/route/rule/rule_item_geosite.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_inbound.go b/sing-box/route/rule/rule_item_inbound.go similarity index 98% rename from sing-box/route/rule_item_inbound.go rename to sing-box/route/rule/rule_item_inbound.go index 7e28781f00..87e84740c9 100644 --- a/sing-box/route/rule_item_inbound.go +++ b/sing-box/route/rule/rule_item_inbound.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_ip_is_private.go b/sing-box/route/rule/rule_item_ip_is_private.go similarity index 98% rename from sing-box/route/rule_item_ip_is_private.go rename to sing-box/route/rule/rule_item_ip_is_private.go index 6592a9d3fe..e185db1db4 100644 --- a/sing-box/route/rule_item_ip_is_private.go +++ b/sing-box/route/rule/rule_item_ip_is_private.go @@ -1,4 +1,4 @@ -package route +package rule import ( "net/netip" diff --git a/sing-box/route/rule_item_ipversion.go b/sing-box/route/rule/rule_item_ipversion.go similarity index 97% rename from sing-box/route/rule_item_ipversion.go rename to sing-box/route/rule/rule_item_ipversion.go index 3d8762b417..8ab6494270 100644 --- a/sing-box/route/rule_item_ipversion.go +++ b/sing-box/route/rule/rule_item_ipversion.go @@ -1,4 +1,4 @@ -package route +package rule import ( "github.com/sagernet/sing-box/adapter" diff --git a/sing-box/route/rule_item_network.go b/sing-box/route/rule/rule_item_network.go similarity index 98% rename from sing-box/route/rule_item_network.go rename to sing-box/route/rule/rule_item_network.go index fc54f425da..bfb334d310 100644 --- a/sing-box/route/rule_item_network.go +++ b/sing-box/route/rule/rule_item_network.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_outbound.go b/sing-box/route/rule/rule_item_outbound.go similarity index 98% rename from sing-box/route/rule_item_outbound.go rename to sing-box/route/rule/rule_item_outbound.go index 4b3e16fc6b..3f37dee7fb 100644 --- a/sing-box/route/rule_item_outbound.go +++ b/sing-box/route/rule/rule_item_outbound.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_package_name.go b/sing-box/route/rule/rule_item_package_name.go similarity index 98% rename from sing-box/route/rule_item_package_name.go rename to sing-box/route/rule/rule_item_package_name.go index d1ca09eb2d..0066735c30 100644 --- a/sing-box/route/rule_item_package_name.go +++ b/sing-box/route/rule/rule_item_package_name.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_port.go b/sing-box/route/rule/rule_item_port.go similarity index 98% rename from sing-box/route/rule_item_port.go rename to sing-box/route/rule/rule_item_port.go index 6247893364..af166ee640 100644 --- a/sing-box/route/rule_item_port.go +++ b/sing-box/route/rule/rule_item_port.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_port_range.go b/sing-box/route/rule/rule_item_port_range.go similarity index 99% rename from sing-box/route/rule_item_port_range.go rename to sing-box/route/rule/rule_item_port_range.go index f87575f2ce..980f7d2391 100644 --- a/sing-box/route/rule_item_port_range.go +++ b/sing-box/route/rule/rule_item_port_range.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strconv" diff --git a/sing-box/route/rule_item_process_name.go b/sing-box/route/rule/rule_item_process_name.go similarity index 98% rename from sing-box/route/rule_item_process_name.go rename to sing-box/route/rule/rule_item_process_name.go index ce051666d0..fa0f71651d 100644 --- a/sing-box/route/rule_item_process_name.go +++ b/sing-box/route/rule/rule_item_process_name.go @@ -1,4 +1,4 @@ -package route +package rule import ( "path/filepath" diff --git a/sing-box/route/rule_item_process_path.go b/sing-box/route/rule/rule_item_process_path.go similarity index 98% rename from sing-box/route/rule_item_process_path.go rename to sing-box/route/rule/rule_item_process_path.go index feae4b2756..75dee476d6 100644 --- a/sing-box/route/rule_item_process_path.go +++ b/sing-box/route/rule/rule_item_process_path.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_process_path_regex.go b/sing-box/route/rule/rule_item_process_path_regex.go similarity index 98% rename from sing-box/route/rule_item_process_path_regex.go rename to sing-box/route/rule/rule_item_process_path_regex.go index 01b2723cc6..76cf67b9f5 100644 --- a/sing-box/route/rule_item_process_path_regex.go +++ b/sing-box/route/rule/rule_item_process_path_regex.go @@ -1,4 +1,4 @@ -package route +package rule import ( "regexp" diff --git a/sing-box/route/rule_item_protocol.go b/sing-box/route/rule/rule_item_protocol.go similarity index 98% rename from sing-box/route/rule_item_protocol.go rename to sing-box/route/rule/rule_item_protocol.go index 1988f8ade1..319b81d50d 100644 --- a/sing-box/route/rule_item_protocol.go +++ b/sing-box/route/rule/rule_item_protocol.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_query_type.go b/sing-box/route/rule/rule_item_query_type.go similarity index 98% rename from sing-box/route/rule_item_query_type.go rename to sing-box/route/rule/rule_item_query_type.go index 7b6efdd044..36b615f3af 100644 --- a/sing-box/route/rule_item_query_type.go +++ b/sing-box/route/rule/rule_item_query_type.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_rule_set.go b/sing-box/route/rule/rule_item_rule_set.go similarity index 99% rename from sing-box/route/rule_item_rule_set.go rename to sing-box/route/rule/rule_item_rule_set.go index b80fca995c..a0115a044a 100644 --- a/sing-box/route/rule_item_rule_set.go +++ b/sing-box/route/rule/rule_item_rule_set.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_user.go b/sing-box/route/rule/rule_item_user.go similarity index 98% rename from sing-box/route/rule_item_user.go rename to sing-box/route/rule/rule_item_user.go index bed97fbaa6..d635fa165b 100644 --- a/sing-box/route/rule_item_user.go +++ b/sing-box/route/rule/rule_item_user.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_user_id.go b/sing-box/route/rule/rule_item_user_id.go similarity index 98% rename from sing-box/route/rule_item_user_id.go rename to sing-box/route/rule/rule_item_user_id.go index 43ab704e3a..57372de003 100644 --- a/sing-box/route/rule_item_user_id.go +++ b/sing-box/route/rule/rule_item_user_id.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_wifi_bssid.go b/sing-box/route/rule/rule_item_wifi_bssid.go similarity index 98% rename from sing-box/route/rule_item_wifi_bssid.go rename to sing-box/route/rule/rule_item_wifi_bssid.go index 3b1ff9c852..ae94bd6df2 100644 --- a/sing-box/route/rule_item_wifi_bssid.go +++ b/sing-box/route/rule/rule_item_wifi_bssid.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_item_wifi_ssid.go b/sing-box/route/rule/rule_item_wifi_ssid.go similarity index 98% rename from sing-box/route/rule_item_wifi_ssid.go rename to sing-box/route/rule/rule_item_wifi_ssid.go index 62cf935eb0..3a928f77e5 100644 --- a/sing-box/route/rule_item_wifi_ssid.go +++ b/sing-box/route/rule/rule_item_wifi_ssid.go @@ -1,4 +1,4 @@ -package route +package rule import ( "strings" diff --git a/sing-box/route/rule_set.go b/sing-box/route/rule/rule_set.go similarity index 75% rename from sing-box/route/rule_set.go rename to sing-box/route/rule/rule_set.go index 39d51e6f54..377ba545e7 100644 --- a/sing-box/route/rule_set.go +++ b/sing-box/route/rule/rule_set.go @@ -1,4 +1,4 @@ -package route +package rule import ( "context" @@ -86,3 +86,31 @@ func (c *RuleSetStartContext) Close() { client.CloseIdleConnections() } } + +func hasHeadlessRule(rules []option.HeadlessRule, cond func(rule option.DefaultHeadlessRule) bool) bool { + for _, rule := range rules { + switch rule.Type { + case C.RuleTypeDefault: + if cond(rule.DefaultOptions) { + return true + } + case C.RuleTypeLogical: + if hasHeadlessRule(rule.LogicalOptions.Rules, cond) { + return true + } + } + } + return false +} + +func isProcessHeadlessRule(rule option.DefaultHeadlessRule) bool { + return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.PackageName) > 0 +} + +func isWIFIHeadlessRule(rule option.DefaultHeadlessRule) bool { + return len(rule.WIFISSID) > 0 || len(rule.WIFIBSSID) > 0 +} + +func isIPCIDRHeadlessRule(rule option.DefaultHeadlessRule) bool { + return len(rule.IPCIDR) > 0 || rule.IPSet != nil +} diff --git a/sing-box/route/rule_set_local.go b/sing-box/route/rule/rule_set_local.go similarity index 99% rename from sing-box/route/rule_set_local.go rename to sing-box/route/rule/rule_set_local.go index 893842d5cc..af16619bfe 100644 --- a/sing-box/route/rule_set_local.go +++ b/sing-box/route/rule/rule_set_local.go @@ -1,4 +1,4 @@ -package route +package rule import ( "context" diff --git a/sing-box/route/rule_set_remote.go b/sing-box/route/rule/rule_set_remote.go similarity index 99% rename from sing-box/route/rule_set_remote.go rename to sing-box/route/rule/rule_set_remote.go index 03662ee42c..6991e92d17 100644 --- a/sing-box/route/rule_set_remote.go +++ b/sing-box/route/rule/rule_set_remote.go @@ -1,4 +1,4 @@ -package route +package rule import ( "bytes" diff --git a/sing-box/route/router_rule.go b/sing-box/route/rule_conds.go similarity index 78% rename from sing-box/route/router_rule.go rename to sing-box/route/rule_conds.go index 4a99a31cc3..76ed84a2e3 100644 --- a/sing-box/route/router_rule.go +++ b/sing-box/route/rule_conds.go @@ -38,22 +38,6 @@ func hasDNSRule(rules []option.DNSRule, cond func(rule option.DefaultDNSRule) bo return false } -func hasHeadlessRule(rules []option.HeadlessRule, cond func(rule option.DefaultHeadlessRule) bool) bool { - for _, rule := range rules { - switch rule.Type { - case C.RuleTypeDefault: - if cond(rule.DefaultOptions) { - return true - } - case C.RuleTypeLogical: - if hasHeadlessRule(rule.LogicalOptions.Rules, cond) { - return true - } - } - } - return false -} - func isGeoIPRule(rule option.DefaultRule) bool { return len(rule.SourceGeoIP) > 0 && common.Any(rule.SourceGeoIP, notPrivateNode) || len(rule.GeoIP) > 0 && common.Any(rule.GeoIP, notPrivateNode) } @@ -93,11 +77,3 @@ func isWIFIRule(rule option.DefaultRule) bool { func isWIFIDNSRule(rule option.DefaultDNSRule) bool { return len(rule.WIFISSID) > 0 || len(rule.WIFIBSSID) > 0 } - -func isWIFIHeadlessRule(rule option.DefaultHeadlessRule) bool { - return len(rule.WIFISSID) > 0 || len(rule.WIFIBSSID) > 0 -} - -func isIPCIDRHeadlessRule(rule option.DefaultHeadlessRule) bool { - return len(rule.IPCIDR) > 0 || rule.IPSet != nil -} diff --git a/sing-box/test/brutal_test.go b/sing-box/test/brutal_test.go index bfe4d1fc02..18aae2e201 100644 --- a/sing-box/test/brutal_test.go +++ b/sing-box/test/brutal_test.go @@ -76,9 +76,18 @@ func TestBrutalShadowsocks(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, @@ -165,9 +174,18 @@ func TestBrutalTrojan(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, @@ -238,9 +256,18 @@ func TestBrutalVMess(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, @@ -342,9 +369,18 @@ func TestBrutalVLESS(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, diff --git a/sing-box/test/direct_test.go b/sing-box/test/direct_test.go index ec3cf88c07..1dbf1de1b6 100644 --- a/sing-box/test/direct_test.go +++ b/sing-box/test/direct_test.go @@ -50,9 +50,18 @@ func _TestProxyProtocol(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "proxy-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "proxy-out", + }, + }, }, }, }, diff --git a/sing-box/test/domain_inbound_test.go b/sing-box/test/domain_inbound_test.go index f22fe24982..1ca2121dae 100644 --- a/sing-box/test/domain_inbound_test.go +++ b/sing-box/test/domain_inbound_test.go @@ -75,9 +75,18 @@ func TestTUICDomainUDP(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "tuic-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "tuic-out", + }, + }, }, }, }, diff --git a/sing-box/test/ech_test.go b/sing-box/test/ech_test.go index 35d5d89158..90eae1f48c 100644 --- a/sing-box/test/ech_test.go +++ b/sing-box/test/ech_test.go @@ -85,9 +85,18 @@ func TestECH(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "trojan-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "trojan-out", + }, + }, }, }, }, @@ -166,9 +175,18 @@ func TestECHQUIC(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "tuic-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "tuic-out", + }, + }, }, }, }, @@ -249,8 +267,16 @@ func TestECHHysteria2(t *testing.T) { { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "hy2-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "hy2-out", + }, + }, }, }, }, diff --git a/sing-box/test/go.mod b/sing-box/test/go.mod index 6caf6240d4..00f4cf62ac 100644 --- a/sing-box/test/go.mod +++ b/sing-box/test/go.mod @@ -1,25 +1,27 @@ module test -go 1.20 +go 1.23 + +toolchain go1.23.2 require github.com/sagernet/sing-box v0.0.0 replace github.com/sagernet/sing-box => ../ require ( - github.com/docker/docker v24.0.7+incompatible - github.com/docker/go-connections v0.4.0 - github.com/gofrs/uuid/v5 v5.2.0 - github.com/sagernet/quic-go v0.45.1-beta.2 - github.com/sagernet/sing v0.4.2 - github.com/sagernet/sing-dns v0.2.3 - github.com/sagernet/sing-quic v0.2.0-beta.12 + github.com/docker/docker v27.3.1+incompatible + github.com/docker/go-connections v0.5.0 + github.com/gofrs/uuid/v5 v5.3.0 + github.com/sagernet/quic-go v0.48.0-beta.1 + github.com/sagernet/sing v0.5.0-rc.4.0.20241021153852-cf58af1a4627 + github.com/sagernet/sing-dns v0.3.0-rc.2.0.20241021154031-a59e0fbba3ce + github.com/sagernet/sing-quic v0.3.0-rc.1 github.com/sagernet/sing-shadowsocks v0.2.7 github.com/sagernet/sing-shadowsocks2 v0.2.0 - github.com/spyzhov/ajson v0.9.0 + github.com/spyzhov/ajson v0.9.4 github.com/stretchr/testify v1.9.0 go.uber.org/goleak v1.3.0 - golang.org/x/net v0.25.0 + golang.org/x/net v0.30.0 ) require ( @@ -28,30 +30,38 @@ require ( github.com/andybalholm/brotli v1.0.6 // indirect github.com/caddyserver/certmagic v0.20.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect + github.com/containerd/log v0.1.0 // indirect github.com/cretz/bine v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.5.0 // indirect - github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gaukas/godicttls v0.0.4 // indirect - github.com/go-chi/chi/v5 v5.0.12 // indirect + github.com/go-chi/chi/v5 v5.1.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/btree v1.1.2 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect - github.com/hashicorp/yamux v0.1.1 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect + github.com/josharian/native v1.1.0 // indirect github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/libdns/alidns v1.0.3 // indirect github.com/libdns/cloudflare v0.1.1 // indirect github.com/libdns/libdns v0.2.2 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/mdlayher/netlink v1.7.2 // indirect + github.com/mdlayher/socket v0.4.1 // indirect + github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa // indirect github.com/mholt/acmez v1.2.0 // indirect - github.com/miekg/dns v1.1.59 // indirect + github.com/miekg/dns v1.1.62 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/onsi/ginkgo/v2 v2.9.7 // indirect @@ -65,34 +75,41 @@ require ( github.com/quic-go/qtls-go1-20 v0.4.1 // indirect github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect - github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect - github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect + github.com/sagernet/fswatch v0.1.1 // indirect + github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3 // indirect + github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect + github.com/sagernet/nftables v0.3.0-beta.4 // indirect github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect - github.com/sagernet/sing-mux v0.2.0 // indirect + github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec // indirect github.com/sagernet/sing-shadowtls v0.1.4 // indirect - github.com/sagernet/sing-tun v0.3.2 // indirect + github.com/sagernet/sing-tun v0.4.0-rc.4.0.20241021153919-9ae45181180d // indirect github.com/sagernet/sing-vmess v0.1.12 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect - github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 // indirect - github.com/sagernet/utls v1.5.4 // indirect + github.com/sagernet/utls v1.6.7 // indirect github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect - github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect + github.com/vishvananda/netns v0.0.4 // indirect github.com/zeebo/blake3 v0.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect + go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.31.0 // indirect + go.opentelemetry.io/otel/trace v1.31.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/grpc v1.63.2 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.24.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect lukechampine.com/blake3 v1.3.0 // indirect diff --git a/sing-box/test/go.sum b/sing-box/test/go.sum index f482438e37..a567074c3f 100644 --- a/sing-box/test/go.sum +++ b/sing-box/test/go.sum @@ -1,14 +1,19 @@ berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw= berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc= github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo= github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI= @@ -17,21 +22,23 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= -github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= -github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= -github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= -github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= +github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -40,18 +47,26 @@ github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM= -github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= +github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= @@ -60,6 +75,7 @@ github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuOb github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE= github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054= @@ -69,18 +85,28 @@ github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= +github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4= +github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= -github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= -github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= +github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= +github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= +github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= github.com/ooni/go-libtor v1.1.8 h1:Wo3V3DVTxl5vZdxtQakqYP+DAHx7pPtAFSl1bnAa08w= github.com/ooni/go-libtor v1.1.8/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -101,53 +127,57 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY= github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k= -github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I= -github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0= -github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk= -github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/quic-go v0.45.1-beta.2 h1:zkEeCbhdFFkrxKcuIRBtXNKci/1t2J/39QSG/sPvlmc= -github.com/sagernet/quic-go v0.45.1-beta.2/go.mod h1:+N3FqM9DAzOWfe64uxXuBejVJwX7DeW7BslzLO6N/xI= +github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs= +github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= +github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3 h1:RxEz7LhPNiF/gX/Hg+OXr5lqsM9iVAgmaK1L1vzlDRM= +github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3/go.mod h1:ehZwnT2UpmOWAHFL48XdBhnd4Qu4hN2O3Ji0us3ZHMw= +github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= +github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= +github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I= +github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8= +github.com/sagernet/quic-go v0.48.0-beta.1 h1:86hQZrmuoARI3BpDRkQaP0iAVpywA4YsRrzJPYuPKWg= +github.com/sagernet/quic-go v0.48.0-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/+or9YMLaG5VeTk4k= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.4.2 h1:jzGNJdZVRI0xlAfFugsIQUPvyB9SuWvbJK7zQCXc4QM= -github.com/sagernet/sing v0.4.2/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= -github.com/sagernet/sing-dns v0.2.3 h1:YzeBUn2tR38F7HtvGEQ0kLRLmZWMEgi/+7wqa4Twb1k= -github.com/sagernet/sing-dns v0.2.3/go.mod h1:BJpJv6XLnrUbSyIntOT6DG9FW0f4fETmPAHvNjOprLg= -github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo= -github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ= -github.com/sagernet/sing-quic v0.2.0-beta.12 h1:BhvA5mmrDFEyDUQB5eeu+9UhF+ieyuNJ5Rsb0dAG3QY= -github.com/sagernet/sing-quic v0.2.0-beta.12/go.mod h1:YVpLfVi8BvYM7NMrjmnvcRm3E8iMETf1gFQmTQDN9jI= +github.com/sagernet/sing v0.5.0-rc.4.0.20241021153852-cf58af1a4627 h1:wWRmqHPHfyWRPUIGsjAmYshvXF+pC/csl9pAmo/vGpo= +github.com/sagernet/sing v0.5.0-rc.4.0.20241021153852-cf58af1a4627/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing-dns v0.3.0-rc.2.0.20241021154031-a59e0fbba3ce h1:OfpxE5qnXMyU/9LtNgX4M7bGP11lJx4s+KZ3Sijb0HE= +github.com/sagernet/sing-dns v0.3.0-rc.2.0.20241021154031-a59e0fbba3ce/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M= +github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec h1:6Fd/VsEsw9qIjaGi1IBTZSb4b4v5JYtNcoiBtGsQC48= +github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec/go.mod h1:RSwqqHwbtTOX3vs6ms8vMtBGH/0ZNyLm/uwt6TlmR84= +github.com/sagernet/sing-quic v0.3.0-rc.1 h1:SlzL1yfEAKJyRduub8vzOVtbyTLAX7RZEEBZxO5utts= +github.com/sagernet/sing-quic v0.3.0-rc.1/go.mod h1:uX+aUHA0fgIN6U3WViseDpSdTQriViZ7qz0Wbsf1mNQ= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.3.2 h1:z0bLUT/YXH9RrJS9DsIpB0Bb9afl2hVJOmHd0zA3HJY= -github.com/sagernet/sing-tun v0.3.2/go.mod h1:DxLIyhjWU/HwGYoX0vNGg2c5QgTQIakphU1MuERR5tQ= +github.com/sagernet/sing-tun v0.4.0-rc.4.0.20241021153919-9ae45181180d h1:zWcIQM3eAKJGzy7zhqkO7zm7ZI890OdR4vSwx2mevS0= +github.com/sagernet/sing-tun v0.4.0-rc.4.0.20241021153919-9ae45181180d/go.mod h1:Xhv+Mz2nE7HZTwResni8EtTa7AMJz/S6uQLT5lV23M8= github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg= github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= -github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 h1:z3SJQhVyU63FT26Wn/UByW6b7q8QKB0ZkPqsyqcz2PI= -github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6/go.mod h1:73xRZuxwkFk4aiLw28hG8W6o9cr2UPrGL9pdY2UTbvY= -github.com/sagernet/utls v1.5.4 h1:KmsEGbB2dKUtCNC+44NwAdNAqnqQ6GA4pTO0Yik56co= -github.com/sagernet/utls v1.5.4/go.mod h1:CTGxPWExIloRipK3XFpYv0OVyhO8kk3XCGW/ieyTh1s= +github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8= +github.com/sagernet/utls v1.6.7/go.mod h1:Uua1TKO/FFuAhLr9rkaVnnrTmmiItzDjv1BUb2+ERwM= github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYAScomNAVpTfbHFpxqJpvwuhxSRi+g6z7gZhABs= github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8/go.mod h1:K4J7/npM+VAMUeUmTa2JaA02JmyheP0GpRBOUvn3ecc= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= -github.com/spyzhov/ajson v0.9.0 h1:tF46gJGOenYVj+k9K1U1XpCxVWhmiyY5PsVCAs1+OJ0= -github.com/spyzhov/ajson v0.9.0/go.mod h1:a6oSw0MMb7Z5aD2tPoPO+jq11ETKgXUr2XktHdT8Wt8= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spyzhov/ajson v0.9.4 h1:MVibcTCgO7DY4IlskdqIlCmDOsUOZ9P7oKj8ifdcf84= +github.com/spyzhov/ajson v0.9.4/go.mod h1:a6oSw0MMb7Z5aD2tPoPO+jq11ETKgXUr2XktHdT8Wt8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= +github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= @@ -156,6 +186,22 @@ github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -169,31 +215,30 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= -golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -201,35 +246,39 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= +google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sing-box/test/http_test.go b/sing-box/test/http_test.go index 4b5fe70fc9..88385c2757 100644 --- a/sing-box/test/http_test.go +++ b/sing-box/test/http_test.go @@ -49,9 +49,18 @@ func TestHTTPSelf(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "http-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "http-out", + }, + }, }, }, }, diff --git a/sing-box/test/hysteria2_test.go b/sing-box/test/hysteria2_test.go index f549442811..9ca2f5d38d 100644 --- a/sing-box/test/hysteria2_test.go +++ b/sing-box/test/hysteria2_test.go @@ -94,8 +94,16 @@ func testHysteria2Self(t *testing.T, salamanderPassword string) { { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "hy2-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "hy2-out", + }, + }, }, }, }, diff --git a/sing-box/test/hysteria_test.go b/sing-box/test/hysteria_test.go index 90ff62dd10..bde1b9fa73 100644 --- a/sing-box/test/hysteria_test.go +++ b/sing-box/test/hysteria_test.go @@ -75,9 +75,18 @@ func TestHysteriaSelf(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "hy-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "hy-out", + }, + }, }, }, }, diff --git a/sing-box/test/inbound_detour_test.go b/sing-box/test/inbound_detour_test.go index c2ef57a56c..9505c217ff 100644 --- a/sing-box/test/inbound_detour_test.go +++ b/sing-box/test/inbound_detour_test.go @@ -80,9 +80,18 @@ func TestChainedInbound(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, diff --git a/sing-box/test/mux_cool_test.go b/sing-box/test/mux_cool_test.go index ef47695a50..81130fad9a 100644 --- a/sing-box/test/mux_cool_test.go +++ b/sing-box/test/mux_cool_test.go @@ -159,9 +159,18 @@ func TestMuxCoolSelf(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "vmess-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "vmess-out", + }, + }, }, }, }, diff --git a/sing-box/test/mux_test.go b/sing-box/test/mux_test.go index c02f270878..8d75518554 100644 --- a/sing-box/test/mux_test.go +++ b/sing-box/test/mux_test.go @@ -102,9 +102,18 @@ func testShadowsocksMux(t *testing.T, options option.OutboundMultiplexOptions) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, @@ -166,9 +175,18 @@ func testVMessMux(t *testing.T, options option.OutboundMultiplexOptions) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "vmess-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "vmess-out", + }, + }, }, }, }, diff --git a/sing-box/test/shadowsocks_test.go b/sing-box/test/shadowsocks_test.go index 7d063d9a96..4ef1ee9d93 100644 --- a/sing-box/test/shadowsocks_test.go +++ b/sing-box/test/shadowsocks_test.go @@ -197,9 +197,18 @@ func testShadowsocksSelf(t *testing.T, method string, password string) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, @@ -258,9 +267,18 @@ func TestShadowsocksUoT(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, @@ -319,9 +337,18 @@ func testShadowsocks2022EIH(t *testing.T, method string, password string) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, diff --git a/sing-box/test/shadowtls_test.go b/sing-box/test/shadowtls_test.go index 2f53d46ada..6f9ee1e566 100644 --- a/sing-box/test/shadowtls_test.go +++ b/sing-box/test/shadowtls_test.go @@ -118,12 +118,23 @@ func testShadowTLS(t *testing.T, version int, password string, utlsEanbled bool) }, }, Route: &option.RouteOptions{ - Rules: []option.Rule{{ - DefaultOptions: option.DefaultRule{ - Inbound: []string{"detour"}, - Outbound: "direct", + Rules: []option.Rule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"detour"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "direct", + }, + }, + }, }, - }}, + }, }, }) testTCP(t, clientPort, testPort) @@ -239,12 +250,23 @@ func TestShadowTLSInbound(t *testing.T) { }, }, Route: &option.RouteOptions{ - Rules: []option.Rule{{ - DefaultOptions: option.DefaultRule{ - Inbound: []string{"in"}, - Outbound: "out", + Rules: []option.Rule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "out", + }, + }, + }, }, - }}, + }, }, }) testTCP(t, clientPort, testPort) @@ -319,12 +341,23 @@ func TestShadowTLSOutbound(t *testing.T) { }, }, Route: &option.RouteOptions{ - Rules: []option.Rule{{ - DefaultOptions: option.DefaultRule{ - Inbound: []string{"detour"}, - Outbound: "direct", + Rules: []option.Rule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"detour"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "direct", + }, + }, + }, }, - }}, + }, }, }) testTCP(t, clientPort, testPort) diff --git a/sing-box/test/tfo_test.go b/sing-box/test/tfo_test.go index cc97e189d1..7bd34e2db7 100644 --- a/sing-box/test/tfo_test.go +++ b/sing-box/test/tfo_test.go @@ -60,9 +60,18 @@ func TestTCPSlowOpen(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "ss-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "ss-out", + }, + }, }, }, }, diff --git a/sing-box/test/tls_test.go b/sing-box/test/tls_test.go index da55faf5bf..cfc6c1a50b 100644 --- a/sing-box/test/tls_test.go +++ b/sing-box/test/tls_test.go @@ -76,9 +76,18 @@ func TestUTLS(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "trojan-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "trojan-out", + }, + }, }, }, }, diff --git a/sing-box/test/trojan_test.go b/sing-box/test/trojan_test.go index d8659b2e4f..f88ec88502 100644 --- a/sing-box/test/trojan_test.go +++ b/sing-box/test/trojan_test.go @@ -118,9 +118,18 @@ func TestTrojanSelf(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "trojan-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "trojan-out", + }, + }, }, }, }, @@ -177,9 +186,18 @@ func TestTrojanPlainSelf(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "trojan-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "trojan-out", + }, + }, }, }, }, diff --git a/sing-box/test/tuic_test.go b/sing-box/test/tuic_test.go index c2b71111f0..5b838f22f7 100644 --- a/sing-box/test/tuic_test.go +++ b/sing-box/test/tuic_test.go @@ -90,9 +90,18 @@ func testTUICSelf(t *testing.T, udpStream bool, zeroRTTHandshake bool) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "tuic-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "tuic-out", + }, + }, }, }, }, diff --git a/sing-box/test/v2ray_transport_test.go b/sing-box/test/v2ray_transport_test.go index 2f39d18aed..c7362f345f 100644 --- a/sing-box/test/v2ray_transport_test.go +++ b/sing-box/test/v2ray_transport_test.go @@ -108,9 +108,18 @@ func testVMessTransportSelf(t *testing.T, server *option.V2RayTransportOptions, Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "vmess-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "vmess-out", + }, + }, }, }, }, @@ -187,9 +196,18 @@ func testTrojanTransportSelf(t *testing.T, server *option.V2RayTransportOptions, Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "vmess-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "vmess-out", + }, + }, }, }, }, @@ -270,9 +288,18 @@ func TestVMessQUICSelf(t *testing.T) { Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "vmess-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "vmess-out", + }, + }, }, }, }, @@ -334,9 +361,18 @@ func testV2RayTransportNOTLSSelf(t *testing.T, transport *option.V2RayTransportO Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "vmess-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + + RouteOptions: option.RouteActionOptions{ + Outbound: "vmess-out", + }, + }, }, }, }, diff --git a/sing-box/test/vmess_test.go b/sing-box/test/vmess_test.go index cc7879ab84..fcf7bf8f47 100644 --- a/sing-box/test/vmess_test.go +++ b/sing-box/test/vmess_test.go @@ -315,9 +315,17 @@ func testVMessSelf(t *testing.T, security string, alterId int, globalPadding boo Route: &option.RouteOptions{ Rules: []option.Rule{ { + Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Inbound: []string{"mixed-in"}, - Outbound: "vmess-out", + RawDefaultRule: option.RawDefaultRule{ + Inbound: []string{"mixed-in"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: "vmess-out", + }, + }, }, }, }, diff --git a/sing-box/transport/wireguard/device_stack.go b/sing-box/transport/wireguard/device_stack.go index d5770419e2..61286e6a9a 100644 --- a/sing-box/transport/wireguard/device_stack.go +++ b/sing-box/transport/wireguard/device_stack.go @@ -252,6 +252,9 @@ func (ep *wireEndpoint) MTU() uint32 { return ep.mtu } +func (ep *wireEndpoint) SetMTU(mtu uint32) { +} + func (ep *wireEndpoint) MaxHeaderLength() uint16 { return 0 } @@ -260,6 +263,9 @@ func (ep *wireEndpoint) LinkAddress() tcpip.LinkAddress { return "" } +func (ep *wireEndpoint) SetLinkAddress(addr tcpip.LinkAddress) { +} + func (ep *wireEndpoint) Capabilities() stack.LinkEndpointCapabilities { return stack.CapabilityRXChecksumOffload } @@ -297,3 +303,9 @@ func (ep *wireEndpoint) WritePackets(list stack.PacketBufferList) (int, tcpip.Er } return list.Len(), nil } + +func (ep *wireEndpoint) Close() { +} + +func (ep *wireEndpoint) SetOnCloseAction(f func()) { +} diff --git a/small/luci-app-mihomo/Makefile b/small/luci-app-mihomo/Makefile index 4ec97e119e..92c028b061 100644 --- a/small/luci-app-mihomo/Makefile +++ b/small/luci-app-mihomo/Makefile @@ -1,6 +1,6 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=1.8.7 +PKG_VERSION:=1.9.0 LUCI_TITLE:=LuCI Support for mihomo LUCI_DEPENDS:=+luci-base +mihomo diff --git a/small/mihomo/Makefile b/small/mihomo/Makefile index 8f84fdc5d1..9113cf8e43 100644 --- a/small/mihomo/Makefile +++ b/small/mihomo/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/MetaCubeX/mihomo.git -PKG_SOURCE_DATE:=2024-10-19 -PKG_SOURCE_VERSION:=95af5f7325fcd9c945b3ad52e617e6ee5ae12d50 -PKG_MIRROR_HASH:=bf8168695e5d6a595dfaa7aab7fcfb9cd70ccc8ff1f7e08ef103104c020e4863 +PKG_SOURCE_DATE:=2024-10-20 +PKG_SOURCE_VERSION:=3e966e82c793ca99e3badc84bf3f2907b100edae +PKG_MIRROR_HASH:=e6e06037239e50a9d458e530b53b5b745224db8f1fafa9c2aa3a61eb6e91e783 PKG_LICENSE:=MIT PKG_MAINTAINER:=Joseph Mory @@ -16,7 +16,7 @@ PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 PKG_BUILD_FLAGS:=no-mips16 -PKG_BUILD_VERSION:=alpha-95af5f7 +PKG_BUILD_VERSION:=alpha-3e966e8 PKG_BUILD_TIME:=$(shell date -u -Iseconds) GO_PKG:=github.com/metacubex/mihomo @@ -31,8 +31,8 @@ define Package/mihomo CATEGORY:=Network TITLE:=A rule based proxy in Go. URL:=https://wiki.metacubex.one - DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +curl +yq firewall4 +kmod-nft-tproxy +ip-full +kmod-tun +procd-ujail - USERID:=mihomo=7890:mihomo=7890 + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +curl +yq firewall4 +ip-full +kmod-inet-diag +kmod-nft-tproxy +kmod-tun + USERID:=root:mihomo=7890 endef define Package/mihomo/description @@ -79,9 +79,6 @@ define Package/mihomo/install $(INSTALL_BIN) $(CURDIR)/files/uci-defaults/init.sh $(1)/etc/uci-defaults/99_init_mihomo $(INSTALL_BIN) $(CURDIR)/files/uci-defaults/migrate.sh $(1)/etc/uci-defaults/99_migrate_mihomo - $(INSTALL_DIR) $(1)/etc/capabilities - $(INSTALL_DATA) $(CURDIR)/files/capabilities.json $(1)/etc/capabilities/mihomo.json - $(INSTALL_DIR) $(1)/lib/upgrade/keep.d $(INSTALL_DATA) $(CURDIR)/files/mihomo.upgrade $(1)/lib/upgrade/keep.d/mihomo endef diff --git a/small/mihomo/files/capabilities.json b/small/mihomo/files/capabilities.json deleted file mode 100644 index 7e765aa47f..0000000000 --- a/small/mihomo/files/capabilities.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "permitted": [ - "CAP_FOWNER", - "CAP_DAC_OVERRIDE", - "CAP_DAC_READ_SEARCH", - "CAP_SYS_PTRACE", - "CAP_NET_ADMIN", - "CAP_NET_BIND_SERVICE", - "CAP_NET_RAW" - ], - "effective": [ - "CAP_FOWNER", - "CAP_DAC_OVERRIDE", - "CAP_DAC_READ_SEARCH", - "CAP_SYS_PTRACE", - "CAP_NET_ADMIN", - "CAP_NET_BIND_SERVICE", - "CAP_NET_RAW" - ], - "bounding": [ - "CAP_FOWNER", - "CAP_DAC_OVERRIDE", - "CAP_DAC_READ_SEARCH", - "CAP_SYS_PTRACE", - "CAP_NET_ADMIN", - "CAP_NET_BIND_SERVICE", - "CAP_NET_RAW" - ], - "inheritable": [ - "CAP_FOWNER", - "CAP_DAC_OVERRIDE", - "CAP_DAC_READ_SEARCH", - "CAP_SYS_PTRACE", - "CAP_NET_ADMIN", - "CAP_NET_BIND_SERVICE", - "CAP_NET_RAW" - ], - "ambient": [ - "CAP_FOWNER", - "CAP_DAC_OVERRIDE", - "CAP_DAC_READ_SEARCH", - "CAP_SYS_PTRACE", - "CAP_NET_ADMIN", - "CAP_NET_BIND_SERVICE", - "CAP_NET_RAW" - ] -} \ No newline at end of file diff --git a/small/mihomo/files/mihomo.init b/small/mihomo/files/mihomo.init index 65abdf038e..54d6a715b7 100644 --- a/small/mihomo/files/mihomo.init +++ b/small/mihomo/files/mihomo.init @@ -246,12 +246,6 @@ start_service() { procd_set_param limits core="unlimited" procd_set_param limits nofile="1048576 1048576" - procd_add_jail mihomo requirejail procfs - procd_add_jail_mount "$PROG" /etc/TZ /etc/localtime /etc/hosts /etc/ssl/certs - procd_add_jail_mount_rw "$RUN_DIR" "$LOG_DIR" /dev/net - procd_set_param capabilities /etc/capabilities/mihomo.json - procd_set_param no_new_privs 1 - procd_close_instance # transparent proxy if [ "$transparent_proxy" == 1 ]; then @@ -305,9 +299,10 @@ start_service() { ip -6 rule add pref "$UDP_RULE_PREF" fwmark "$FW_MARK/$FW_MARK_MASK" ipproto udp table "$udp_route_table" fi fi - nft -f "$HIJACK_NFT" -D FW_MARK="$FW_MARK" -D FW_MARK_MASK="$FW_MARK_MASK" -D MIHOMO_USER="$MIHOMO_USER" -D TUN_DEVICE="$TUN_DEVICE" -D DNS_PORT="$dns_port" -D REDIR_PORT="$redir_port" -D TPROXY_PORT="$tproxy_port" + nft -f "$HIJACK_NFT" -D FW_MARK="$FW_MARK" -D FW_MARK_MASK="$FW_MARK_MASK" -D TUN_DEVICE="$TUN_DEVICE" -D DNS_PORT="$dns_port" -D REDIR_PORT="$redir_port" -D TPROXY_PORT="$tproxy_port" nft -f "$RESERVED_IP_NFT" nft -f "$RESERVED_IP6_NFT" + nft add element inet "$FW_TABLE" bypass_group \{ "$MIHOMO_GROUP" \} nft add element inet "$FW_TABLE" fake_ip \{ "$fake_ip_range" \} # dns hijack if [ "$ipv4_dns_hijack" == 1 ]; then diff --git a/small/mihomo/files/nftables/hijack.nft b/small/mihomo/files/nftables/hijack.nft index 699d7e7664..4cc55544be 100644 --- a/small/mihomo/files/nftables/hijack.nft +++ b/small/mihomo/files/nftables/hijack.nft @@ -1,6 +1,17 @@ #!/usr/sbin/nft -f table inet mihomo { + set bypass_group { + type gid + flags interval + auto-merge + elements = { + ntp, + dnsmasq, + logd + } + } + set dns_hijack_nfproto { type nf_proto flags interval @@ -63,7 +74,7 @@ table inet mihomo { } chain router_dns_hijack { - meta skuid $MIHOMO_USER counter return + meta skgid @bypass_group counter return meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 oifname lo counter redirect to :$DNS_PORT } @@ -157,7 +168,7 @@ table inet mihomo { chain nat_output { type nat hook output priority filter; policy accept; - meta skuid $MIHOMO_USER counter return + meta skgid @bypass_group counter return fib daddr type local counter return ct direction reply counter return ip daddr @reserved_ip counter return @@ -185,7 +196,7 @@ table inet mihomo { chain mangle_output { type route hook output priority mangle; policy accept; - meta skuid $MIHOMO_USER counter return + meta skgid @bypass_group counter return fib daddr type local counter return ct direction reply counter return ip daddr @reserved_ip counter return diff --git a/small/mihomo/files/scripts/constants.sh b/small/mihomo/files/scripts/constants.sh index 97d2e17134..22b43aed3e 100644 --- a/small/mihomo/files/scripts/constants.sh +++ b/small/mihomo/files/scripts/constants.sh @@ -1,7 +1,7 @@ #!/bin/sh # permission -MIHOMO_USER="mihomo" +MIHOMO_USER="root" MIHOMO_GROUP="mihomo" # routing diff --git a/small/v2ray-geodata/Makefile b/small/v2ray-geodata/Makefile index e48758b9f0..62cd19e0c1 100644 --- a/small/v2ray-geodata/Makefile +++ b/small/v2ray-geodata/Makefile @@ -30,7 +30,7 @@ define Download/geosite HASH:=f820556ed3aa02eb7eadba7a3743d7e6df8e9234785d0d82d2d1edce20fe4b3c endef -GEOSITE_IRAN_VER:=202410190822 +GEOSITE_IRAN_VER:=202410210035 GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER) define Download/geosite-ir URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/ diff --git a/v2rayn/v2rayN/ServiceLib/Common/SqliteHelper.cs b/v2rayn/v2rayN/ServiceLib/Common/SqliteHelper.cs index 8c9a151b65..3fc84e6a09 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/SqliteHelper.cs +++ b/v2rayn/v2rayN/ServiceLib/Common/SqliteHelper.cs @@ -64,21 +64,11 @@ namespace ServiceLib.Common return await _dbAsync.ExecuteAsync(sql); } - public List Query(string sql) where T : new() - { - return _db.Query(sql); - } - public async Task> QueryAsync(string sql) where T : new() { return await _dbAsync.QueryAsync(sql); } - public TableQuery Table() where T : new() - { - return _db.Table(); - } - public AsyncTableQuery TableAsync() where T : new() { return _dbAsync.Table(); diff --git a/v2rayn/v2rayN/ServiceLib/Global.cs b/v2rayn/v2rayN/ServiceLib/Global.cs index f9e955dae2..1c76cae3a9 100644 --- a/v2rayn/v2rayN/ServiceLib/Global.cs +++ b/v2rayn/v2rayN/ServiceLib/Global.cs @@ -126,12 +126,12 @@ public static readonly List RoutingRulesSources = new() { "", - @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/template.json", + @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json", }; public static readonly List DNSTemplateSources = new() { "", - @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/", + @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/", }; public static readonly Dictionary UserAgentTexts = new() diff --git a/v2rayn/v2rayN/ServiceLib/Handler/AppHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/AppHandler.cs index 3ef7eaf45b..3f585339f7 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/AppHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/AppHandler.cs @@ -102,41 +102,45 @@ #region SqliteHelper - public List SubItems() + public async Task> SubItems() { - return SQLiteHelper.Instance.Table().ToList(); + return await SQLiteHelper.Instance.TableAsync().OrderBy(t => t.sort).ToListAsync(); } - public SubItem GetSubItem(string subid) + public async Task GetSubItem(string subid) { - return SQLiteHelper.Instance.Table().FirstOrDefault(t => t.id == subid); + return await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(t => t.id == subid); } - public List ProfileItems(string subid) + public async Task> ProfileItems(string subid) { if (Utils.IsNullOrEmpty(subid)) { - return SQLiteHelper.Instance.Table().ToList(); + return await SQLiteHelper.Instance.TableAsync().ToListAsync(); } else { - return SQLiteHelper.Instance.Table().Where(t => t.subid == subid).ToList(); + return await SQLiteHelper.Instance.TableAsync().Where(t => t.subid == subid).ToListAsync(); } } - public List ProfileItemIndexes(string subid) + public async Task> ProfileItemIndexes(string subid) { if (Utils.IsNullOrEmpty(subid)) { - return SQLiteHelper.Instance.Table().Select(t => t.indexId).ToList(); + return (await SQLiteHelper.Instance.TableAsync().ToListAsync()) + .Select(t => t.indexId) + .ToList(); } else { - return SQLiteHelper.Instance.Table().Where(t => t.subid == subid).Select(t => t.indexId).ToList(); + return (await SQLiteHelper.Instance.TableAsync().Where(t => t.subid == subid).ToListAsync()) + .Select(t => t.indexId) + .ToList(); } } - public List ProfileItems(string subid, string filter) + public async Task> ProfileItems(string subid, string filter) { var sql = @$"select a.* ,b.remarks subRemarks @@ -156,14 +160,14 @@ sql += string.Format(" and (a.remarks like '%{0}%' or a.address like '%{0}%') ", filter); } - return SQLiteHelper.Instance.Query(sql).ToList(); + return await SQLiteHelper.Instance.QueryAsync(sql); } - public List ProfileItemsEx(string subid, string filter) + public async Task> ProfileItemsEx(string subid, string filter) { - var lstModel = ProfileItems(_config.subIndexId, filter); + var lstModel = await ProfileItems(_config.subIndexId, filter); - ConfigHandler.SetDefaultServer(_config, lstModel); + await ConfigHandler.SetDefaultServer(_config, lstModel); var lstServerStat = (_config.guiItem.enableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? []; var lstProfileExs = ProfileExHandler.Instance.ProfileExs; @@ -198,42 +202,42 @@ return lstModel; } - public ProfileItem? GetProfileItem(string indexId) + public async Task GetProfileItem(string indexId) { if (Utils.IsNullOrEmpty(indexId)) { return null; } - return SQLiteHelper.Instance.Table().FirstOrDefault(it => it.indexId == indexId); + return await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(it => it.indexId == indexId); } - public ProfileItem? GetProfileItemViaRemarks(string? remarks) + public async Task GetProfileItemViaRemarks(string? remarks) { if (Utils.IsNullOrEmpty(remarks)) { return null; } - return SQLiteHelper.Instance.Table().FirstOrDefault(it => it.remarks == remarks); + return await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(it => it.remarks == remarks); } - public List RoutingItems() + public async Task> RoutingItems() { - return SQLiteHelper.Instance.Table().Where(it => it.locked == false).OrderBy(t => t.sort).ToList(); + return await SQLiteHelper.Instance.TableAsync().Where(it => it.locked == false).OrderBy(t => t.sort).ToListAsync(); } - public RoutingItem GetRoutingItem(string id) + public async Task GetRoutingItem(string id) { - return SQLiteHelper.Instance.Table().FirstOrDefault(it => it.locked == false && it.id == id); + return await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(it => it.locked == false && it.id == id); } - public List DNSItems() + public async Task> DNSItems() { - return SQLiteHelper.Instance.Table().ToList(); + return await SQLiteHelper.Instance.TableAsync().ToListAsync(); } - public DNSItem GetDNSItem(ECoreType eCoreType) + public async Task GetDNSItem(ECoreType eCoreType) { - return SQLiteHelper.Instance.Table().FirstOrDefault(it => it.coreType == eCoreType); + return await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(it => it.coreType == eCoreType); } #endregion SqliteHelper diff --git a/v2rayn/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/ConfigHandler.cs index cf92d6152e..24d06e4dda 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -218,7 +218,7 @@ namespace ServiceLib.Handler public static async Task AddServer(Config config, ProfileItem profileItem) { - var item = AppHandler.Instance.GetProfileItem(profileItem.indexId); + var item = await AppHandler.Instance.GetProfileItem(profileItem.indexId); if (item is null) { item = profileItem; @@ -330,7 +330,7 @@ namespace ServiceLib.Handler { foreach (var it in indexes) { - var item = AppHandler.Instance.GetProfileItem(it.indexId); + var item = await AppHandler.Instance.GetProfileItem(it.indexId); if (item is null) { continue; @@ -382,23 +382,26 @@ namespace ServiceLib.Handler { return 0; } - if (SQLiteHelper.Instance.Table().Where(t => t.indexId == config.indexId).Any()) + var count = await SQLiteHelper.Instance.TableAsync().CountAsync(t => t.indexId == config.indexId); + if (count > 0) { return 0; } if (lstProfile.Count > 0) { - return await SetDefaultServerIndex(config, lstProfile.Where(t => t.port > 0).FirstOrDefault()?.indexId); + return await SetDefaultServerIndex(config, lstProfile.FirstOrDefault(t => t.port > 0)?.indexId); } - return await SetDefaultServerIndex(config, SQLiteHelper.Instance.Table().Where(t => t.port > 0).Select(t => t.indexId).FirstOrDefault()); + + var item = await SQLiteHelper.Instance.TableAsync().Where(t => t.port > 0).FirstOrDefaultAsync(); + return await SetDefaultServerIndex(config, item.indexId); } public static async Task GetDefaultServer(Config config) { - var item = AppHandler.Instance.GetProfileItem(config.indexId); + var item = await AppHandler.Instance.GetProfileItem(config.indexId); if (item is null) { - var item2 = SQLiteHelper.Instance.Table().FirstOrDefault(); + var item2 = await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(); await SetDefaultServerIndex(config, item2?.indexId); return item2; } @@ -531,7 +534,7 @@ namespace ServiceLib.Handler /// public static async Task EditCustomServer(Config config, ProfileItem profileItem) { - var item = AppHandler.Instance.GetProfileItem(profileItem.indexId); + var item = await AppHandler.Instance.GetProfileItem(profileItem.indexId); if (item is null) { item = profileItem; @@ -748,7 +751,7 @@ namespace ServiceLib.Handler public static async Task SortServers(Config config, string subId, string colName, bool asc) { - var lstModel = AppHandler.Instance.ProfileItems(subId, ""); + var lstModel = await AppHandler.Instance.ProfileItems(subId, ""); if (lstModel.Count <= 0) { return -1; @@ -880,7 +883,7 @@ namespace ServiceLib.Handler public static async Task> DedupServerList(Config config, string subId) { - var lstProfile = AppHandler.Instance.ProfileItems(subId); + var lstProfile = await AppHandler.Instance.ProfileItems(subId); List lstKeep = new(); List lstRemove = new(); @@ -980,7 +983,7 @@ namespace ServiceLib.Handler { try { - var item = AppHandler.Instance.GetProfileItem(indexId); + var item = await AppHandler.Instance.GetProfileItem(indexId); if (item == null) { return 0; @@ -1000,22 +1003,24 @@ namespace ServiceLib.Handler return 0; } - public static async Task> AddCustomServer4Multiple(Config config, List selecteds, ECoreType coreType) + public static async Task AddCustomServer4Multiple(Config config, List selecteds, ECoreType coreType) { var indexId = Utils.GetMd5(Global.CoreMultipleLoadConfigFileName); - string configPath = Utils.GetConfigPath(Global.CoreMultipleLoadConfigFileName); - if (CoreConfigHandler.GenerateClientMultipleLoadConfig(config, configPath, selecteds, coreType, out string msg) != 0) + var configPath = Utils.GetConfigPath(Global.CoreMultipleLoadConfigFileName); + + var result = await CoreConfigHandler.GenerateClientMultipleLoadConfig(config, configPath, selecteds, coreType); + if (result.Success != true) { - return new Tuple(-1, ""); + return result; } var fileName = configPath; if (!File.Exists(fileName)) { - return new Tuple(-1, ""); + return result; } - var profileItem = AppHandler.Instance.GetProfileItem(indexId) ?? new(); + var profileItem = await AppHandler.Instance.GetProfileItem(indexId) ?? new(); profileItem.indexId = indexId; profileItem.remarks = coreType == ECoreType.sing_box ? ResUI.menuSetDefaultMultipleServer : ResUI.menuSetDefaultLoadBalanceServer; profileItem.address = Global.CoreMultipleLoadConfigFileName; @@ -1024,7 +1029,8 @@ namespace ServiceLib.Handler await AddServerCommon(config, profileItem, true); - return new Tuple(0, indexId); + result.Data = indexId; + return result; } #endregion Server @@ -1050,7 +1056,7 @@ namespace ServiceLib.Handler if (isSub && Utils.IsNotEmpty(subid)) { await RemoveServerViaSubid(config, subid, isSub); - subFilter = AppHandler.Instance.GetSubItem(subid)?.filter ?? ""; + subFilter = (await AppHandler.Instance.GetSubItem(subid))?.filter ?? ""; } int countServers = 0; @@ -1089,7 +1095,7 @@ namespace ServiceLib.Handler //Check for duplicate indexId if (lstDbIndexId is null) { - lstDbIndexId = AppHandler.Instance.ProfileItemIndexes(""); + lstDbIndexId = await AppHandler.Instance.ProfileItemIndexes(""); } if (lstAdd.Any(t => t.indexId == existItem.indexId) || lstDbIndexId.Any(t => t == existItem.indexId)) @@ -1149,7 +1155,7 @@ namespace ServiceLib.Handler return -1; } - var subItem = AppHandler.Instance.GetSubItem(subid); + var subItem = await AppHandler.Instance.GetSubItem(subid); var subRemarks = subItem?.remarks; var preSocksPort = subItem?.preSocksPort; @@ -1284,7 +1290,7 @@ namespace ServiceLib.Handler List? lstOriSub = null; if (isSub && Utils.IsNotEmpty(subid)) { - lstOriSub = AppHandler.Instance.ProfileItems(subid); + lstOriSub = await AppHandler.Instance.ProfileItems(subid); } var counter = 0; @@ -1328,7 +1334,8 @@ namespace ServiceLib.Handler public static async Task AddSubItem(Config config, string url) { //already exists - if (SQLiteHelper.Instance.Table().Any(e => e.url == url)) + var count = await SQLiteHelper.Instance.TableAsync().CountAsync(e => e.url == url); + if (count > 0) { return 0; } @@ -1354,7 +1361,7 @@ namespace ServiceLib.Handler public static async Task AddSubItem(Config config, SubItem subItem) { - var item = AppHandler.Instance.GetSubItem(subItem.id); + var item = await AppHandler.Instance.GetSubItem(subItem.id); if (item is null) { item = subItem; @@ -1383,9 +1390,10 @@ namespace ServiceLib.Handler if (item.sort <= 0) { var maxSort = 0; - if (SQLiteHelper.Instance.Table().Count() > 0) + if (await SQLiteHelper.Instance.TableAsync().CountAsync() > 0) { - maxSort = SQLiteHelper.Instance.Table().Max(t => t == null ? 0 : t.sort); + var lstSubs = (await AppHandler.Instance.SubItems()); + maxSort = lstSubs.LastOrDefault()?.sort ?? 0; } item.sort = maxSort + 1; } @@ -1412,7 +1420,7 @@ namespace ServiceLib.Handler { return -1; } - var customProfile = SQLiteHelper.Instance.Table().Where(t => t.subid == subid && t.configType == EConfigType.Custom).ToList(); + var customProfile = await SQLiteHelper.Instance.TableAsync().Where(t => t.subid == subid && t.configType == EConfigType.Custom).ToListAsync(); if (isSub) { await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileItem where isSub = 1 and subid = '{subid}'"); @@ -1431,7 +1439,7 @@ namespace ServiceLib.Handler public static async Task DeleteSubItem(Config config, string id) { - var item = AppHandler.Instance.GetSubItem(id); + var item = await AppHandler.Instance.GetSubItem(id); if (item is null) { return 0; @@ -1594,7 +1602,7 @@ namespace ServiceLib.Handler public static async Task SetDefaultRouting(Config config, RoutingItem routingItem) { - if (SQLiteHelper.Instance.Table().Where(t => t.id == routingItem.id).Count() > 0) + if (await SQLiteHelper.Instance.TableAsync().Where(t => t.id == routingItem.id).CountAsync() > 0) { config.routingBasicItem.routingIndexId = routingItem.id; } @@ -1606,10 +1614,10 @@ namespace ServiceLib.Handler public static async Task GetDefaultRouting(Config config) { - var item = AppHandler.Instance.GetRoutingItem(config.routingBasicItem.routingIndexId); + var item = await AppHandler.Instance.GetRoutingItem(config.routingBasicItem.routingIndexId); if (item is null) { - var item2 = SQLiteHelper.Instance.Table().FirstOrDefault(t => t.locked == false); + var item2 = await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(t => t.locked == false); await SetDefaultRouting(config, item2); return item2; } @@ -1634,7 +1642,7 @@ namespace ServiceLib.Handler public static async Task InitExternalRouting(Config config, bool blImportAdvancedRules = false) { var downloadHandle = new DownloadService(); - var templateContent = Task.Run(() => downloadHandle.TryDownloadString(config.constItem.routeRulesTemplateSourceUrl, false, "")).Result; + var templateContent = await downloadHandle.TryDownloadString(config.constItem.routeRulesTemplateSourceUrl, true, ""); if (string.IsNullOrEmpty(templateContent)) return await InitBuiltinRouting(config, blImportAdvancedRules); // fallback @@ -1642,7 +1650,7 @@ namespace ServiceLib.Handler if (template == null) return await InitBuiltinRouting(config, blImportAdvancedRules); // fallback - var items = AppHandler.Instance.RoutingItems(); + var items = await AppHandler.Instance.RoutingItems(); var maxSort = items.Count; if (!blImportAdvancedRules && items.Where(t => t.remarks.StartsWith(template.version)).ToList().Count > 0) { @@ -1657,7 +1665,7 @@ namespace ServiceLib.Handler var ruleSetsString = !string.IsNullOrEmpty(item.ruleSet) ? item.ruleSet - : Task.Run(() => downloadHandle.TryDownloadString(item.url, false, "")).Result; + : await downloadHandle.TryDownloadString(item.url, true, ""); if (string.IsNullOrEmpty(ruleSetsString)) continue; @@ -1682,7 +1690,7 @@ namespace ServiceLib.Handler public static async Task InitBuiltinRouting(Config config, bool blImportAdvancedRules = false) { var ver = "V3-"; - var items = AppHandler.Instance.RoutingItems(); + var items = await AppHandler.Instance.RoutingItems(); if (!blImportAdvancedRules && items.Where(t => t.remarks.StartsWith(ver)).ToList().Count > 0) { return 0; @@ -1723,9 +1731,9 @@ namespace ServiceLib.Handler return 0; } - public static RoutingItem? GetLockedRoutingItem(Config config) + public static async Task GetLockedRoutingItem(Config config) { - return SQLiteHelper.Instance.Table().FirstOrDefault(it => it.locked == true); + return await SQLiteHelper.Instance.TableAsync().FirstOrDefaultAsync(it => it.locked == true); } public static async Task RemoveRoutingItem(RoutingItem routingItem) @@ -1739,7 +1747,7 @@ namespace ServiceLib.Handler public static async Task InitBuiltinDNS(Config config) { - var items = AppHandler.Instance.DNSItems(); + var items = await AppHandler.Instance.DNSItems(); if (items.Count <= 0) { var item = new DNSItem() @@ -1782,12 +1790,12 @@ namespace ServiceLib.Handler } } - public static DNSItem GetExternalDNSItem(ECoreType type, string url) + public static async Task GetExternalDNSItem(ECoreType type, string url) { - var currentItem = AppHandler.Instance.GetDNSItem(type); + var currentItem = await AppHandler.Instance.GetDNSItem(type); var downloadHandle = new DownloadService(); - var templateContent = Task.Run(() => downloadHandle.TryDownloadString(url, true, "")).Result; + var templateContent = await downloadHandle.TryDownloadString(url, true, ""); if (string.IsNullOrEmpty(templateContent)) return currentItem; @@ -1796,10 +1804,10 @@ namespace ServiceLib.Handler return currentItem; if (!string.IsNullOrEmpty(template.normalDNS)) - template.normalDNS = Task.Run(() => downloadHandle.TryDownloadString(template.normalDNS, true, "")).Result; + template.normalDNS = await downloadHandle.TryDownloadString(template.normalDNS, true, ""); if (!string.IsNullOrEmpty(template.tunDNS)) - template.tunDNS = Task.Run(() => downloadHandle.TryDownloadString(template.tunDNS, true, "")).Result; + template.tunDNS = await downloadHandle.TryDownloadString(template.tunDNS, true, ""); template.id = currentItem.id; template.enabled = currentItem.enabled; @@ -1832,8 +1840,8 @@ namespace ServiceLib.Handler config.constItem.srsSourceUrl = Global.SingboxRulesetSources[1]; config.constItem.routeRulesTemplateSourceUrl = Global.RoutingRulesSources[1]; - await SaveDNSItems(config, GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json")); - await SaveDNSItems(config, GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json")); + await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json")); + await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json")); return true; } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/CoreConfigHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/CoreConfigHandler.cs index 43fdc6c233..40c0099203 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/CoreConfigHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/CoreConfigHandler.cs @@ -5,86 +5,55 @@ /// public class CoreConfigHandler { - public static int GenerateClientConfig(ProfileItem node, string? fileName, out string msg, out string content) + public static async Task GenerateClientConfig(ProfileItem node, string? fileName) { - content = string.Empty; - try - { - if (node == null) - { - msg = ResUI.CheckServerSettings; - return -1; - } - var config = AppHandler.Instance.Config; + var config = AppHandler.Instance.Config; + var result = new RetResult(); - msg = ResUI.InitialConfiguration; - if (node.configType == EConfigType.Custom) + if (node.configType == EConfigType.Custom) + { + if (node.coreType is ECoreType.mihomo) { - if (node.coreType is ECoreType.mihomo) - { - var configGenClash = new CoreConfigClashService(config); - return configGenClash.GenerateClientCustomConfig(node, fileName, out msg); - } - if (node.coreType is ECoreType.sing_box) - { - var configGenSingbox = new CoreConfigSingboxService(config); - return configGenSingbox.GenerateClientCustomConfig(node, fileName, out msg); - } - else - { - return GenerateClientCustomConfig(node, fileName, out msg); - } + result = await new CoreConfigClashService(config).GenerateClientCustomConfig(node, fileName); } - else if (AppHandler.Instance.GetCoreType(node, node.configType) == ECoreType.sing_box) + if (node.coreType is ECoreType.sing_box) { - var configGenSingbox = new CoreConfigSingboxService(config); - if (configGenSingbox.GenerateClientConfigContent(node, out SingboxConfig? singboxConfig, out msg) != 0) - { - return -1; - } - if (Utils.IsNullOrEmpty(fileName)) - { - content = JsonUtils.Serialize(singboxConfig); - } - else - { - JsonUtils.ToFile(singboxConfig, fileName, false); - } + result = await new CoreConfigSingboxService(config).GenerateClientCustomConfig(node, fileName); } else { - var coreConfigV2ray = new CoreConfigV2rayService(config); - if (coreConfigV2ray.GenerateClientConfigContent(node, out V2rayConfig? v2rayConfig, out msg) != 0) - { - return -1; - } - if (Utils.IsNullOrEmpty(fileName)) - { - content = JsonUtils.Serialize(v2rayConfig); - } - else - { - JsonUtils.ToFile(v2rayConfig, fileName, false); - } + result = await GenerateClientCustomConfig(node, fileName); } } - catch (Exception ex) + else if (AppHandler.Instance.GetCoreType(node, node.configType) == ECoreType.sing_box) { - Logging.SaveLog("GenerateClientConfig", ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + result = await new CoreConfigSingboxService(config).GenerateClientConfigContent(node); } - return 0; + else + { + result = await new CoreConfigV2rayService(config).GenerateClientConfigContent(node); + } + if (result.Success != true) + { + return result; + } + if (Utils.IsNotEmpty(fileName) && result.Data != null) + { + await File.WriteAllTextAsync(fileName, result.Data.ToString()); + } + + return result; } - private static int GenerateClientCustomConfig(ProfileItem node, string? fileName, out string msg) + private static async Task GenerateClientCustomConfig(ProfileItem node, string? fileName) { + var ret = new RetResult(); try { if (node == null || fileName is null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } if (File.Exists(fileName)) @@ -100,8 +69,8 @@ } if (!File.Exists(addressFileName)) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } File.Copy(addressFileName, fileName); File.SetAttributes(fileName, FileAttributes.Normal); //Copy will keep the attributes of addressFileName, so we need to add write permissions to fileName just in case of addressFileName is a read-only file. @@ -109,63 +78,59 @@ //check again if (!File.Exists(fileName)) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Success = true; + return ret; } catch (Exception ex) { Logging.SaveLog("GenerateClientCustomConfig", ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - return 0; } - public static int GenerateClientSpeedtestConfig(Config config, string fileName, List selecteds, ECoreType coreType, out string msg) + public static async Task GenerateClientSpeedtestConfig(Config config, string fileName, List selecteds, ECoreType coreType) { + var result = new RetResult(); if (coreType == ECoreType.sing_box) { - if (new CoreConfigSingboxService(config).GenerateClientSpeedtestConfig(selecteds, out SingboxConfig? singboxConfig, out msg) != 0) - { - return -1; - } - JsonUtils.ToFile(singboxConfig, fileName, false); - } - else - { - if (new CoreConfigV2rayService(config).GenerateClientSpeedtestConfig(selecteds, out V2rayConfig? v2rayConfig, out msg) != 0) - { - return -1; - } - JsonUtils.ToFile(v2rayConfig, fileName, false); - } - return 0; - } - - public static int GenerateClientMultipleLoadConfig(Config config, string fileName, List selecteds, ECoreType coreType, out string msg) - { - msg = ResUI.CheckServerSettings; - if (coreType == ECoreType.sing_box) - { - if (new CoreConfigSingboxService(config).GenerateClientMultipleLoadConfig(selecteds, out SingboxConfig? singboxConfig, out msg) != 0) - { - return -1; - } - JsonUtils.ToFile(singboxConfig, fileName, false); + result = await new CoreConfigSingboxService(config).GenerateClientSpeedtestConfig(selecteds); } else if (coreType == ECoreType.Xray) { - if (new CoreConfigV2rayService(config).GenerateClientMultipleLoadConfig(selecteds, out V2rayConfig? v2rayConfig, out msg) != 0) - { - return -1; - } - JsonUtils.ToFile(v2rayConfig, fileName, false); + result = await new CoreConfigV2rayService(config).GenerateClientSpeedtestConfig(selecteds); + } + if (result.Success != true) + { + return result; + } + await File.WriteAllTextAsync(fileName, result.Data.ToString()); + return result; + } + + public static async Task GenerateClientMultipleLoadConfig(Config config, string fileName, List selecteds, ECoreType coreType) + { + var result = new RetResult(); + if (coreType == ECoreType.sing_box) + { + result = await new CoreConfigSingboxService(config).GenerateClientMultipleLoadConfig(selecteds); + } + else if (coreType == ECoreType.Xray) + { + result = await new CoreConfigV2rayService(config).GenerateClientMultipleLoadConfig(selecteds); } - return 0; + if (result.Success != true) + { + return result; + } + await File.WriteAllTextAsync(fileName, result.Data.ToString()); + return result; } } } \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs index 3c2667e250..f843aaf7d1 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs @@ -24,7 +24,7 @@ namespace ServiceLib.Handler Environment.SetEnvironmentVariable("xray.location.asset", Utils.GetBinPath(""), EnvironmentVariableTarget.Process); } - public void LoadCore(ProfileItem? node) + public async Task LoadCore(ProfileItem? node) { if (node == null) { @@ -32,18 +32,18 @@ namespace ServiceLib.Handler return; } - string fileName = Utils.GetConfigPath(Global.CoreConfigFileName); - if (CoreConfigHandler.GenerateClientConfig(node, fileName, out string msg, out string content) != 0) + var fileName = Utils.GetConfigPath(Global.CoreConfigFileName); + var result = await CoreConfigHandler.GenerateClientConfig(node, fileName); + ShowMsg(false, result.Msg); + if (result.Success != true) { - ShowMsg(false, msg); return; } else { - ShowMsg(false, msg); ShowMsg(true, $"{node.GetSummary()}"); CoreStop(); - CoreStart(node); + await CoreStart(node); //In tun mode, do a delay check and restart the core //if (_config.tunModeItem.enableTun) @@ -65,18 +65,15 @@ namespace ServiceLib.Handler } } - public int LoadCoreConfigSpeedtest(List selecteds) + public async Task LoadCoreConfigSpeedtest(List selecteds) { - int pid = -1; - var coreType = selecteds.Exists(t => t.ConfigType == EConfigType.Hysteria2 || t.ConfigType == EConfigType.TUIC || t.ConfigType == EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray; - string configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName); - if (CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType, out string msg) != 0) + var pid = -1; + var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray; + var configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName); + var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType); + ShowMsg(false, result.Msg); + if (result.Success) { - ShowMsg(false, msg); - } - else - { - ShowMsg(false, msg); pid = CoreStartSpeedtest(configPath, coreType); } return pid; @@ -170,7 +167,7 @@ namespace ServiceLib.Handler return fileName; } - private void CoreStart(ProfileItem node) + private async Task CoreStart(ProfileItem node) { ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}"); ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"))); @@ -227,7 +224,8 @@ namespace ServiceLib.Handler if (itemSocks != null) { string fileName2 = Utils.GetConfigPath(Global.CorePreConfigFileName); - if (CoreConfigHandler.GenerateClientConfig(itemSocks, fileName2, out string msg2, out string configStr) == 0) + var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName2); + if (result.Success) { var coreInfo2 = CoreInfoHandler.Instance.GetCoreInfo(preCoreType); var proc2 = RunProcess(node, coreInfo2, $" -c {Global.CorePreConfigFileName}", true); diff --git a/v2rayn/v2rayN/ServiceLib/Handler/ProfileExHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/ProfileExHandler.cs index 4cf59768f9..f9c3419330 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/ProfileExHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/ProfileExHandler.cs @@ -29,7 +29,7 @@ namespace ServiceLib.Handler { await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )"); - _lstProfileEx = new(SQLiteHelper.Instance.Table()); + _lstProfileEx = new(await SQLiteHelper.Instance.TableAsync().ToListAsync()); } private void IndexIdEnqueue(string indexId) @@ -45,7 +45,7 @@ namespace ServiceLib.Handler var cnt = _queIndexIds.Count; if (cnt > 0) { - var lstExists = SQLiteHelper.Instance.Table(); + var lstExists = await SQLiteHelper.Instance.TableAsync().ToListAsync(); List lstInserts = []; List lstUpdates = []; diff --git a/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs index b0335e8f3c..ababd01f4a 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs @@ -71,7 +71,7 @@ long ticks = DateTime.Now.Date.Ticks; await SQLiteHelper.Instance.ExecuteAsync($"update ServerStatItem set todayUp = 0,todayDown=0,dateNow={ticks} where dateNow<>{ticks}"); - _lstServerStat = SQLiteHelper.Instance.Table().ToList(); + _lstServerStat = await SQLiteHelper.Instance.TableAsync().ToListAsync(); } private void UpdateServerStatHandler(ServerSpeedItem server) diff --git a/v2rayn/v2rayN/ServiceLib/Handler/TaskHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/TaskHandler.cs index b75426efd2..2166f03639 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/TaskHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/TaskHandler.cs @@ -24,7 +24,7 @@ while (true) { var updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds(); - var lstSubs = AppHandler.Instance.SubItems() + var lstSubs = (await AppHandler.Instance.SubItems()) .Where(t => t.autoUpdateInterval > 0) .Where(t => updateTime - t.updateTime >= t.autoUpdateInterval * 60) .ToList(); diff --git a/v2rayn/v2rayN/ServiceLib/Models/RetResult.cs b/v2rayn/v2rayN/ServiceLib/Models/RetResult.cs new file mode 100644 index 0000000000..9c6122c074 --- /dev/null +++ b/v2rayn/v2rayN/ServiceLib/Models/RetResult.cs @@ -0,0 +1,27 @@ +namespace ServiceLib.Models +{ + public class RetResult + { + public bool Success { get; set; } + public string? Msg { get; set; } + public object? Data { get; set; } + + public RetResult(bool success = false) + { + Success = success; + } + + public RetResult(bool success, string? msg) + { + Success = success; + Msg = msg; + } + + public RetResult(bool success, string? msg, object? data) + { + Success = success; + Msg = msg; + Data = data; + } + } +} \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs index 36a97529d3..58e03603cc 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs @@ -19,22 +19,23 @@ /// /// /// - public int GenerateClientCustomConfig(ProfileItem node, string? fileName, out string msg) + public async Task GenerateClientCustomConfig(ProfileItem node, string? fileName) { + var ret = new RetResult(); if (node == null || fileName is null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } - msg = ResUI.InitialConfiguration; + ret.Msg = ResUI.InitialConfiguration; try { if (node == null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } if (File.Exists(fileName)) @@ -45,8 +46,8 @@ string addressFileName = node.address; if (Utils.IsNullOrEmpty(addressFileName)) { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; } if (!File.Exists(addressFileName)) { @@ -54,8 +55,8 @@ } if (!File.Exists(addressFileName)) { - msg = ResUI.FailedReadConfiguration + "1"; - return -1; + ret.Msg = ResUI.FailedReadConfiguration + "1"; + return ret; } string tagYamlStr1 = "!"; @@ -73,8 +74,8 @@ var fileContent = YamlUtils.FromYaml>(txtFile); if (fileContent == null) { - msg = ResUI.FailedConversionConfiguration; - return -1; + ret.Msg = ResUI.FailedConversionConfiguration; + return ret; } //port @@ -136,25 +137,26 @@ } var txtFileNew = YamlUtils.ToYaml(fileContent).Replace(tagYamlStr2, tagYamlStr3); - File.WriteAllText(fileName, txtFileNew); + await File.WriteAllTextAsync(fileName, txtFileNew); //check again if (!File.Exists(fileName)) { - msg = ResUI.FailedReadConfiguration + "2"; - return -1; + ret.Msg = ResUI.FailedReadConfiguration + "2"; + return ret; } ClashApiHandler.Instance.ProfileContent = fileContent; - msg = string.Format(ResUI.SuccessfulConfiguration, $"{node.GetSummary()}"); + ret.Msg = string.Format(ResUI.SuccessfulConfiguration, $"{node.GetSummary()}"); + ret.Success = true; + return ret; } catch (Exception ex) { Logging.SaveLog("GenerateClientConfigClash", ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - return 0; } private void MixinContent(Dictionary fileContent, ProfileItem node) diff --git a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs index 7b978794d6..93575e33ce 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs @@ -15,92 +15,94 @@ namespace ServiceLib.Services.CoreConfig #region public gen function - public int GenerateClientConfigContent(ProfileItem node, out SingboxConfig? singboxConfig, out string msg) + public async Task GenerateClientConfigContent(ProfileItem node) { - singboxConfig = null; + var ret = new RetResult(); try { if (node == null || node.port <= 0) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.splithttp)) { - msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}"; - return -1; + ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}"; + return ret; } - msg = ResUI.InitialConfiguration; + ret.Msg = ResUI.InitialConfiguration; string result = Utils.GetEmbedText(Global.SingboxSampleClient); if (Utils.IsNullOrEmpty(result)) { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; } - singboxConfig = JsonUtils.Deserialize(result); + var singboxConfig = JsonUtils.Deserialize(result); if (singboxConfig == null) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - GenLog(singboxConfig); + await GenLog(singboxConfig); - GenInbounds(singboxConfig); + await GenInbounds(singboxConfig); - GenOutbound(node, singboxConfig.outbounds[0]); + await GenOutbound(node, singboxConfig.outbounds[0]); - GenMoreOutbounds(node, singboxConfig); + await GenMoreOutbounds(node, singboxConfig); - GenRouting(singboxConfig); + await GenRouting(singboxConfig); - GenDns(node, singboxConfig); + await GenDns(node, singboxConfig); - GenExperimental(singboxConfig); + await GenExperimental(singboxConfig); - ConvertGeo2Ruleset(singboxConfig); + await ConvertGeo2Ruleset(singboxConfig); - msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Success = true; + ret.Data = JsonUtils.Serialize(singboxConfig); + return ret; } catch (Exception ex) { Logging.SaveLog("GenerateClientConfig4Singbox", ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - return 0; } - public int GenerateClientSpeedtestConfig(List selecteds, out SingboxConfig? singboxConfig, out string msg) + public async Task GenerateClientSpeedtestConfig(List selecteds) { - singboxConfig = null; + var ret = new RetResult(); try { if (_config == null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } - msg = ResUI.InitialConfiguration; + ret.Msg = ResUI.InitialConfiguration; string result = Utils.GetEmbedText(Global.SingboxSampleClient); string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; } - singboxConfig = JsonUtils.Deserialize(result); + var singboxConfig = JsonUtils.Deserialize(result); if (singboxConfig == null) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } List lstIpEndPoints = new(); List lstTcpConns = new(); @@ -115,7 +117,7 @@ namespace ServiceLib.Services.CoreConfig Logging.SaveLog(ex.Message, ex); } - GenLog(singboxConfig); + await GenLog(singboxConfig); //GenDns(new(), singboxConfig); singboxConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts. singboxConfig.outbounds.RemoveAt(0); @@ -132,7 +134,7 @@ namespace ServiceLib.Services.CoreConfig { continue; } - var item = AppHandler.Instance.GetProfileItem(it.IndexId); + var item = await AppHandler.Instance.GetProfileItem(it.IndexId); if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) { if (item is null || Utils.IsNullOrEmpty(item.id) || !Utils.IsGuidByParse(item.id)) @@ -200,7 +202,7 @@ namespace ServiceLib.Services.CoreConfig } var outbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(item, outbound); + await GenOutbound(item, outbound); outbound.tag = Global.ProxyTag + inbound.listen_port.ToString(); singboxConfig.outbounds.Add(outbound); @@ -213,7 +215,7 @@ namespace ServiceLib.Services.CoreConfig singboxConfig.route.rules.Add(rule); } - GenDnsDomains(null, singboxConfig, null); + await GenDnsDomains(null, singboxConfig, null); //var dnsServer = singboxConfig.dns?.servers.FirstOrDefault(); //if (dnsServer != null) //{ @@ -226,49 +228,51 @@ namespace ServiceLib.Services.CoreConfig // singboxConfig.dns.rules.Add(dnsRule); //} - //msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); - return 0; + //ret.Msg =string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); + ret.Success = true; + ret.Data = JsonUtils.Serialize(singboxConfig); + return ret; } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } } - public int GenerateClientMultipleLoadConfig(List selecteds, out SingboxConfig? singboxConfig, out string msg) + public async Task GenerateClientMultipleLoadConfig(List selecteds) { - singboxConfig = null; + var ret = new RetResult(); try { if (_config == null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } - msg = ResUI.InitialConfiguration; + ret.Msg = ResUI.InitialConfiguration; string result = Utils.GetEmbedText(Global.SingboxSampleClient); string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; } - singboxConfig = JsonUtils.Deserialize(result); + var singboxConfig = JsonUtils.Deserialize(result); if (singboxConfig == null) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - GenLog(singboxConfig); - GenInbounds(singboxConfig); - GenRouting(singboxConfig); - GenExperimental(singboxConfig); + await GenLog(singboxConfig); + await GenInbounds(singboxConfig); + await GenRouting(singboxConfig); + await GenExperimental(singboxConfig); singboxConfig.outbounds.RemoveAt(0); var tagProxy = new List(); @@ -282,7 +286,7 @@ namespace ServiceLib.Services.CoreConfig { continue; } - var item = AppHandler.Instance.GetProfileItem(it.indexId); + var item = await AppHandler.Instance.GetProfileItem(it.indexId); if (item is null) { continue; @@ -306,19 +310,19 @@ namespace ServiceLib.Services.CoreConfig //outbound var outbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(item, outbound); + await GenOutbound(item, outbound); outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}"; singboxConfig.outbounds.Add(outbound); tagProxy.Add(outbound.tag); } if (tagProxy.Count <= 0) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - GenDns(null, singboxConfig); - ConvertGeo2Ruleset(singboxConfig); + await GenDns(null, singboxConfig); + await ConvertGeo2Ruleset(singboxConfig); //add urltest outbound var outUrltest = new Outbound4Sbox @@ -341,32 +345,35 @@ namespace ServiceLib.Services.CoreConfig outSelector.outbounds.Insert(0, outUrltest.tag); singboxConfig.outbounds.Add(outSelector); - return 0; + ret.Success = true; + ret.Data = JsonUtils.Serialize(singboxConfig); + return ret; } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } } - public int GenerateClientCustomConfig(ProfileItem node, string? fileName, out string msg) + public async Task GenerateClientCustomConfig(ProfileItem node, string? fileName) { + var ret = new RetResult(); if (node == null || fileName is null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } - msg = ResUI.InitialConfiguration; + ret.Msg = ResUI.InitialConfiguration; try { if (node == null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } if (File.Exists(fileName)) @@ -377,8 +384,8 @@ namespace ServiceLib.Services.CoreConfig string addressFileName = node.address; if (Utils.IsNullOrEmpty(addressFileName)) { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; } if (!File.Exists(addressFileName)) { @@ -386,8 +393,8 @@ namespace ServiceLib.Services.CoreConfig } if (!File.Exists(addressFileName)) { - msg = ResUI.FailedReadConfiguration + "1"; - return -1; + ret.Msg = ResUI.FailedReadConfiguration + "1"; + return ret; } if (node.address == Global.CoreMultipleLoadConfigFileName) @@ -400,8 +407,8 @@ namespace ServiceLib.Services.CoreConfig } else { - GenInbounds(singboxConfig); - GenExperimental(singboxConfig); + await GenInbounds(singboxConfig); + await GenExperimental(singboxConfig); JsonUtils.ToFile(singboxConfig, fileName, false); } } @@ -413,26 +420,27 @@ namespace ServiceLib.Services.CoreConfig //check again if (!File.Exists(fileName)) { - msg = ResUI.FailedReadConfiguration + "2"; - return -1; + ret.Msg = ResUI.FailedReadConfiguration + "2"; + return ret; } - msg = string.Format(ResUI.SuccessfulConfiguration, $"{node.GetSummary()}"); + ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Success = true; + return ret; } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - return 0; } #endregion public gen function #region private gen function - private int GenLog(SingboxConfig singboxConfig) + public async Task GenLog(SingboxConfig singboxConfig) { try { @@ -572,7 +580,7 @@ namespace ServiceLib.Services.CoreConfig return inbound; } - private int GenOutbound(ProfileItem node, Outbound4Sbox outbound) + public async Task GenOutbound(ProfileItem node, Outbound4Sbox outbound) { try { @@ -595,7 +603,7 @@ namespace ServiceLib.Services.CoreConfig outbound.security = Global.DefaultSecurity; } - GenOutboundMux(node, outbound); + await GenOutboundMux(node, outbound); break; } case EConfigType.Shadowsocks: @@ -603,7 +611,7 @@ namespace ServiceLib.Services.CoreConfig outbound.method = AppHandler.Instance.GetShadowsocksSecurities(node).Contains(node.security) ? node.security : Global.None; outbound.password = node.id; - GenOutboundMux(node, outbound); + await GenOutboundMux(node, outbound); break; } case EConfigType.SOCKS: @@ -635,7 +643,7 @@ namespace ServiceLib.Services.CoreConfig if (Utils.IsNullOrEmpty(node.flow)) { - GenOutboundMux(node, outbound); + await GenOutboundMux(node, outbound); } else { @@ -647,7 +655,7 @@ namespace ServiceLib.Services.CoreConfig { outbound.password = node.id; - GenOutboundMux(node, outbound); + await GenOutboundMux(node, outbound); break; } case EConfigType.Hysteria2: @@ -685,9 +693,9 @@ namespace ServiceLib.Services.CoreConfig } } - GenOutboundTls(node, outbound); + await GenOutboundTls(node, outbound); - GenOutboundTransport(node, outbound); + await GenOutboundTransport(node, outbound); } catch (Exception ex) { @@ -696,7 +704,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenOutboundMux(ProfileItem node, Outbound4Sbox outbound) + public async Task GenOutboundMux(ProfileItem node, Outbound4Sbox outbound) { try { @@ -719,7 +727,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenOutboundTls(ProfileItem node, Outbound4Sbox outbound) + public async Task GenOutboundTls(ProfileItem node, Outbound4Sbox outbound) { try { @@ -769,7 +777,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound) + public async Task GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound) { try { @@ -846,7 +854,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenMoreOutbounds(ProfileItem node, SingboxConfig singboxConfig) + private async Task GenMoreOutbounds(ProfileItem node, SingboxConfig singboxConfig) { if (node.subid.IsNullOrEmpty()) { @@ -854,7 +862,7 @@ namespace ServiceLib.Services.CoreConfig } try { - var subItem = AppHandler.Instance.GetSubItem(node.subid); + var subItem = await AppHandler.Instance.GetSubItem(node.subid); if (subItem is null) { return 0; @@ -865,12 +873,12 @@ namespace ServiceLib.Services.CoreConfig var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); //Previous proxy - var prevNode = AppHandler.Instance.GetProfileItemViaRemarks(subItem.prevProfile); + var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.prevProfile); if (prevNode is not null && prevNode.configType != EConfigType.Custom) { var prevOutbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(prevNode, prevOutbound); + await GenOutbound(prevNode, prevOutbound); prevOutbound.tag = $"{Global.ProxyTag}2"; singboxConfig.outbounds.Add(prevOutbound); @@ -878,12 +886,12 @@ namespace ServiceLib.Services.CoreConfig } //Next proxy - var nextNode = AppHandler.Instance.GetProfileItemViaRemarks(subItem.nextProfile); + var nextNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.nextProfile); if (nextNode is not null && nextNode.configType != EConfigType.Custom) { var nextOutbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(nextNode, nextOutbound); + await GenOutbound(nextNode, nextOutbound); nextOutbound.tag = Global.ProxyTag; singboxConfig.outbounds.Insert(0, nextOutbound); @@ -960,20 +968,20 @@ namespace ServiceLib.Services.CoreConfig { if (item.enabled) { - GenRoutingUserRule(item, singboxConfig.route.rules); + await GenRoutingUserRule(item, singboxConfig.route.rules); } } } } else { - var lockedItem = ConfigHandler.GetLockedRoutingItem(_config); + var lockedItem = await ConfigHandler.GetLockedRoutingItem(_config); if (lockedItem != null) { var rules = JsonUtils.Deserialize>(lockedItem.ruleSet); foreach (var item in rules ?? []) { - GenRoutingUserRule(item, singboxConfig.route.rules); + await GenRoutingUserRule(item, singboxConfig.route.rules); } } } @@ -1011,7 +1019,7 @@ namespace ServiceLib.Services.CoreConfig } } - private int GenRoutingUserRule(RulesItem item, List rules) + public async Task GenRoutingUserRule(RulesItem item, List rules) { try { @@ -1169,11 +1177,11 @@ namespace ServiceLib.Services.CoreConfig return true; } - private int GenDns(ProfileItem? node, SingboxConfig singboxConfig) + public async Task GenDns(ProfileItem? node, SingboxConfig singboxConfig) { try { - var item = AppHandler.Instance.GetDNSItem(ECoreType.sing_box); + var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); var strDNS = string.Empty; if (_config.tunModeItem.enableTun) { @@ -1191,7 +1199,7 @@ namespace ServiceLib.Services.CoreConfig } singboxConfig.dns = dns4Sbox; - GenDnsDomains(node, singboxConfig, item); + await GenDnsDomains(node, singboxConfig, item); } catch (Exception ex) { @@ -1200,7 +1208,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem) + public async Task GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem) { var dns4Sbox = singboxConfig.dns ?? new(); dns4Sbox.servers ??= []; @@ -1253,7 +1261,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenExperimental(SingboxConfig singboxConfig) + public async Task GenExperimental(SingboxConfig singboxConfig) { //if (_config.guiItem.enableStatistics) { diff --git a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs index b32e8ed0c9..9b7cf9c7dd 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs @@ -15,92 +15,95 @@ namespace ServiceLib.Services.CoreConfig #region public gen function - public int GenerateClientConfigContent(ProfileItem node, out V2rayConfig? v2rayConfig, out string msg) + public async Task GenerateClientConfigContent(ProfileItem node) { - v2rayConfig = null; + var ret = new RetResult(); try { if (node == null || node.port <= 0) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } - msg = ResUI.InitialConfiguration; + ret.Msg = ResUI.InitialConfiguration; - string result = Utils.GetEmbedText(Global.V2raySampleClient); + var result = Utils.GetEmbedText(Global.V2raySampleClient); if (Utils.IsNullOrEmpty(result)) { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; } - v2rayConfig = JsonUtils.Deserialize(result); + var v2rayConfig = JsonUtils.Deserialize(result); if (v2rayConfig == null) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - GenLog(v2rayConfig); + await GenLog(v2rayConfig); - GenInbounds(v2rayConfig); + await GenInbounds(v2rayConfig); - GenRouting(v2rayConfig); + await GenRouting(v2rayConfig); - GenOutbound(node, v2rayConfig.outbounds[0]); + await GenOutbound(node, v2rayConfig.outbounds[0]); - GenMoreOutbounds(node, v2rayConfig); + await GenMoreOutbounds(node, v2rayConfig); - GenDns(node, v2rayConfig); + await GenDns(node, v2rayConfig); - GenStatistic(v2rayConfig); + await GenStatistic(v2rayConfig); - msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Success = true; + ret.Data = JsonUtils.Serialize(v2rayConfig); + return ret; } catch (Exception ex) { Logging.SaveLog("GenerateClientConfig4V2ray", ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - return 0; } - public int GenerateClientMultipleLoadConfig(List selecteds, out V2rayConfig? v2rayConfig, out string msg) + public async Task GenerateClientMultipleLoadConfig(List selecteds) { - v2rayConfig = null; + var ret = new RetResult(); + try { if (_config == null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } - msg = ResUI.InitialConfiguration; + ret.Msg = ResUI.InitialConfiguration; string result = Utils.GetEmbedText(Global.V2raySampleClient); string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound); if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; } - v2rayConfig = JsonUtils.Deserialize(result); + var v2rayConfig = JsonUtils.Deserialize(result); if (v2rayConfig == null) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } - GenLog(v2rayConfig); - GenInbounds(v2rayConfig); - GenRouting(v2rayConfig); - GenDns(null, v2rayConfig); - GenStatistic(v2rayConfig); + await GenLog(v2rayConfig); + await GenInbounds(v2rayConfig); + await GenRouting(v2rayConfig); + await GenDns(null, v2rayConfig); + await GenStatistic(v2rayConfig); v2rayConfig.outbounds.RemoveAt(0); var tagProxy = new List(); @@ -118,7 +121,7 @@ namespace ServiceLib.Services.CoreConfig { continue; } - var item = AppHandler.Instance.GetProfileItem(it.indexId); + var item = await AppHandler.Instance.GetProfileItem(it.indexId); if (item is null) { continue; @@ -142,15 +145,15 @@ namespace ServiceLib.Services.CoreConfig //outbound var outbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(item, outbound); + await GenOutbound(item, outbound); outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}"; v2rayConfig.outbounds.Add(outbound); tagProxy.Add(outbound.tag); } if (tagProxy.Count <= 0) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } //add balancers @@ -182,42 +185,44 @@ namespace ServiceLib.Services.CoreConfig }); } - return 0; + ret.Success = true; + ret.Data = JsonUtils.Serialize(v2rayConfig); + return ret; } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } } - public int GenerateClientSpeedtestConfig(List selecteds, out V2rayConfig? v2rayConfig, out string msg) + public async Task GenerateClientSpeedtestConfig(List selecteds) { - v2rayConfig = null; + var ret = new RetResult(); try { if (_config == null) { - msg = ResUI.CheckServerSettings; - return -1; + ret.Msg = ResUI.CheckServerSettings; + return ret; } - msg = ResUI.InitialConfiguration; + ret.Msg = ResUI.InitialConfiguration; string result = Utils.GetEmbedText(Global.V2raySampleClient); string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound); if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; } - v2rayConfig = JsonUtils.Deserialize(result); + var v2rayConfig = JsonUtils.Deserialize(result); if (v2rayConfig == null) { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } List lstIpEndPoints = new(); List lstTcpConns = new(); @@ -232,7 +237,7 @@ namespace ServiceLib.Services.CoreConfig Logging.SaveLog(ex.Message, ex); } - GenLog(v2rayConfig); + await GenLog(v2rayConfig); v2rayConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts. v2rayConfig.outbounds.RemoveAt(0); @@ -248,7 +253,7 @@ namespace ServiceLib.Services.CoreConfig { continue; } - var item = AppHandler.Instance.GetProfileItem(it.IndexId); + var item = await AppHandler.Instance.GetProfileItem(it.IndexId); if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) { if (item is null || Utils.IsNullOrEmpty(item.id) || !Utils.IsGuidByParse(item.id)) @@ -316,7 +321,7 @@ namespace ServiceLib.Services.CoreConfig } var outbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(item, outbound); + await GenOutbound(item, outbound); outbound.tag = Global.ProxyTag + inbound.port.ToString(); v2rayConfig.outbounds.Add(outbound); @@ -330,14 +335,16 @@ namespace ServiceLib.Services.CoreConfig v2rayConfig.routing.rules.Add(rule); } - //msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); - return 0; + //ret.Msg =string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); + ret.Success = true; + ret.Data = JsonUtils.Serialize(v2rayConfig); + return ret; } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; } } @@ -345,7 +352,7 @@ namespace ServiceLib.Services.CoreConfig #region private gen function - private int GenLog(V2rayConfig v2rayConfig) + public async Task GenLog(V2rayConfig v2rayConfig) { try { @@ -370,7 +377,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenInbounds(V2rayConfig v2rayConfig) + public async Task GenInbounds(V2rayConfig v2rayConfig) { try { @@ -468,21 +475,21 @@ namespace ServiceLib.Services.CoreConfig if (item.enabled) { var item2 = JsonUtils.Deserialize(JsonUtils.Serialize(item)); - GenRoutingUserRule(item2, v2rayConfig); + await GenRoutingUserRule(item2, v2rayConfig); } } } } else { - var lockedItem = ConfigHandler.GetLockedRoutingItem(_config); + var lockedItem = await ConfigHandler.GetLockedRoutingItem(_config); if (lockedItem != null) { var rules = JsonUtils.Deserialize>(lockedItem.ruleSet); foreach (var item in rules) { var item2 = JsonUtils.Deserialize(JsonUtils.Serialize(item)); - GenRoutingUserRule(item2, v2rayConfig); + await GenRoutingUserRule(item2, v2rayConfig); } } } @@ -495,7 +502,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenRoutingUserRule(RulesItem4Ray? rule, V2rayConfig v2rayConfig) + public async Task GenRoutingUserRule(RulesItem4Ray? rule, V2rayConfig v2rayConfig) { try { @@ -573,7 +580,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenOutbound(ProfileItem node, Outbounds4Ray outbound) + public async Task GenOutbound(ProfileItem node, Outbounds4Ray outbound) { try { @@ -617,7 +624,7 @@ namespace ServiceLib.Services.CoreConfig usersItem.security = Global.DefaultSecurity; } - GenOutboundMux(node, outbound, _config.coreBasicItem.muxEnabled); + await GenOutboundMux(node, outbound, _config.coreBasicItem.muxEnabled); outbound.settings.servers = null; break; @@ -642,7 +649,7 @@ namespace ServiceLib.Services.CoreConfig serversItem.ota = false; serversItem.level = 1; - GenOutboundMux(node, outbound, false); + await GenOutboundMux(node, outbound, false); outbound.settings.vnext = null; break; @@ -678,7 +685,7 @@ namespace ServiceLib.Services.CoreConfig serversItem.users = new List() { socksUsersItem }; } - GenOutboundMux(node, outbound, false); + await GenOutboundMux(node, outbound, false); outbound.settings.vnext = null; break; @@ -712,7 +719,7 @@ namespace ServiceLib.Services.CoreConfig usersItem.email = Global.UserEMail; usersItem.encryption = node.security; - GenOutboundMux(node, outbound, _config.coreBasicItem.muxEnabled); + await GenOutboundMux(node, outbound, _config.coreBasicItem.muxEnabled); if (node.streamSecurity == Global.StreamSecurityReality || node.streamSecurity == Global.StreamSecurity) @@ -721,12 +728,12 @@ namespace ServiceLib.Services.CoreConfig { usersItem.flow = node.flow; - GenOutboundMux(node, outbound, false); + await GenOutboundMux(node, outbound, false); } } if (node.streamSecurity == Global.StreamSecurityReality && Utils.IsNullOrEmpty(node.flow)) { - GenOutboundMux(node, outbound, _config.coreBasicItem.muxEnabled); + await GenOutboundMux(node, outbound, _config.coreBasicItem.muxEnabled); } outbound.settings.servers = null; @@ -751,7 +758,7 @@ namespace ServiceLib.Services.CoreConfig serversItem.ota = false; serversItem.level = 1; - GenOutboundMux(node, outbound, false); + await GenOutboundMux(node, outbound, false); outbound.settings.vnext = null; break; @@ -759,7 +766,7 @@ namespace ServiceLib.Services.CoreConfig } outbound.protocol = Global.ProtocolTypes[node.configType]; - GenBoundStreamSettings(node, outbound.streamSettings); + await GenBoundStreamSettings(node, outbound.streamSettings); } catch (Exception ex) { @@ -768,7 +775,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenOutboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabled) + public async Task GenOutboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabled) { try { @@ -792,7 +799,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenBoundStreamSettings(ProfileItem node, StreamSettings4Ray streamSettings) + public async Task GenBoundStreamSettings(ProfileItem node, StreamSettings4Ray streamSettings) { try { @@ -1025,11 +1032,11 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenDns(ProfileItem? node, V2rayConfig v2rayConfig) + public async Task GenDns(ProfileItem? node, V2rayConfig v2rayConfig) { try { - var item = AppHandler.Instance.GetDNSItem(ECoreType.Xray); + var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); var normalDNS = item?.normalDNS; var domainStrategy4Freedom = item?.domainStrategy4Freedom; if (Utils.IsNullOrEmpty(normalDNS)) @@ -1077,7 +1084,7 @@ namespace ServiceLib.Services.CoreConfig } } - GenDnsDomains(node, obj, item); + await GenDnsDomains(node, obj, item); v2rayConfig.dns = obj; } @@ -1088,7 +1095,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem) + public async Task GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem) { if (node == null) { return 0; } @@ -1108,7 +1115,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenStatistic(V2rayConfig v2rayConfig) + public async Task GenStatistic(V2rayConfig v2rayConfig) { if (_config.guiItem.enableStatistics) { @@ -1158,7 +1165,7 @@ namespace ServiceLib.Services.CoreConfig return 0; } - private int GenMoreOutbounds(ProfileItem node, V2rayConfig v2rayConfig) + private async Task GenMoreOutbounds(ProfileItem node, V2rayConfig v2rayConfig) { //fragment proxy if (_config.coreBasicItem.enableFragment @@ -1193,7 +1200,7 @@ namespace ServiceLib.Services.CoreConfig } try { - var subItem = AppHandler.Instance.GetSubItem(node.subid); + var subItem = await AppHandler.Instance.GetSubItem(node.subid); if (subItem is null) { return 0; @@ -1204,7 +1211,7 @@ namespace ServiceLib.Services.CoreConfig var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound); //Previous proxy - var prevNode = AppHandler.Instance.GetProfileItemViaRemarks(subItem.prevProfile); + var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.prevProfile); if (prevNode is not null && prevNode.configType != EConfigType.Custom && prevNode.configType != EConfigType.Hysteria2 @@ -1212,7 +1219,7 @@ namespace ServiceLib.Services.CoreConfig && prevNode.configType != EConfigType.WireGuard) { var prevOutbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(prevNode, prevOutbound); + await GenOutbound(prevNode, prevOutbound); prevOutbound.tag = $"{Global.ProxyTag}2"; v2rayConfig.outbounds.Add(prevOutbound); @@ -1223,7 +1230,7 @@ namespace ServiceLib.Services.CoreConfig } //Next proxy - var nextNode = AppHandler.Instance.GetProfileItemViaRemarks(subItem.nextProfile); + var nextNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.nextProfile); if (nextNode is not null && nextNode.configType != EConfigType.Custom && nextNode.configType != EConfigType.Hysteria2 @@ -1231,7 +1238,7 @@ namespace ServiceLib.Services.CoreConfig && nextNode.configType != EConfigType.WireGuard) { var nextOutbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(nextNode, nextOutbound); + await GenOutbound(nextNode, nextOutbound); nextOutbound.tag = Global.ProxyTag; v2rayConfig.outbounds.Insert(0, nextOutbound); diff --git a/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs b/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs index 0a6c5ec7f5..db28ea7213 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs @@ -10,22 +10,10 @@ namespace ServiceLib.Services /// public class DownloadService { - public event EventHandler? UpdateCompleted; + public event EventHandler? UpdateCompleted; public event ErrorEventHandler? Error; - public class ResultEventArgs : EventArgs - { - public bool Success; - public string Msg; - - public ResultEventArgs(bool success, string msg) - { - Success = success; - Msg = msg; - } - } - public async Task DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action updateFunc) { try @@ -63,12 +51,12 @@ namespace ServiceLib.Services try { SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13); - UpdateCompleted?.Invoke(this, new ResultEventArgs(false, $"{ResUI.Downloading} {url}")); + UpdateCompleted?.Invoke(this, new RetResult(false, $"{ResUI.Downloading} {url}")); var progress = new Progress(); progress.ProgressChanged += (sender, value) => { - UpdateCompleted?.Invoke(this, new ResultEventArgs(value > 100, $"...{value}%")); + UpdateCompleted?.Invoke(this, new RetResult(value > 100, $"...{value}%")); }; var webProxy = GetWebProxy(blProxy); @@ -107,6 +95,7 @@ namespace ServiceLib.Services } else { + Error?.Invoke(this, new ErrorEventArgs(new Exception("StatusCode error: " + response.StatusCode))); Logging.SaveLog("StatusCode error: " + url); return null; } diff --git a/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs b/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs index 52330266f0..eaee4e4f9e 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs @@ -134,7 +134,7 @@ namespace ServiceLib.Services { string msg = string.Empty; - pid = CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds); + pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds); if (pid < 0) { UpdateFunc("", ResUI.FailedToRunCore); @@ -196,7 +196,7 @@ namespace ServiceLib.Services // _selecteds = _selecteds.OrderBy(t => t.delay).ToList(); //} - pid = CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds); + pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds); if (pid < 0) { UpdateFunc("", ResUI.FailedToRunCore); @@ -231,7 +231,7 @@ namespace ServiceLib.Services ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "-1"); UpdateFunc(it.IndexId, "", ResUI.Speedtesting); - var item = AppHandler.Instance.GetProfileItem(it.IndexId); + var item = await AppHandler.Instance.GetProfileItem(it.IndexId); if (item is null) continue; WebProxy webProxy = new(Global.Loopback, it.Port); @@ -252,13 +252,13 @@ namespace ServiceLib.Services CoreHandler.Instance.CoreStopPid(pid); } UpdateFunc("", ResUI.SpeedtestingCompleted); - ProfileExHandler.Instance.SaveTo(); + await ProfileExHandler.Instance.SaveTo(); } private async Task RunSpeedTestMulti() { int pid = -1; - pid = CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds); + pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds); if (pid < 0) { UpdateFunc("", ResUI.FailedToRunCore); @@ -294,7 +294,7 @@ namespace ServiceLib.Services ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "-1"); UpdateFunc(it.IndexId, "", ResUI.Speedtesting); - var item = AppHandler.Instance.GetProfileItem(it.IndexId); + var item = await AppHandler.Instance.GetProfileItem(it.IndexId); if (item is null) continue; WebProxy webProxy = new(Global.Loopback, it.Port); diff --git a/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs index d4f1e6f06a..179da11c43 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs @@ -9,20 +9,6 @@ namespace ServiceLib.Services private Config _config; private int _timeout = 30; - private class ResultEventArgs - { - public bool Success; - public string Msg; - public string Url; - - public ResultEventArgs(bool success, string msg, string url = "") - { - Success = success; - Msg = msg; - Url = url; - } - } - public async Task CheckUpdateGuiN(Config config, Action updateFunc, bool preRelease) { _config = config; @@ -49,19 +35,19 @@ namespace ServiceLib.Services }; _updateFunc?.Invoke(false, string.Format(ResUI.MsgStartUpdating, ECoreType.v2rayN)); - var args = await CheckUpdateAsync(downloadHandle, ECoreType.v2rayN, preRelease); - if (args.Success) + var result = await CheckUpdateAsync(downloadHandle, ECoreType.v2rayN, preRelease); + if (result.Success) { _updateFunc?.Invoke(false, string.Format(ResUI.MsgParsingSuccessfully, ECoreType.v2rayN)); - _updateFunc?.Invoke(false, args.Msg); + _updateFunc?.Invoke(false, result.Msg); - url = args.Url; + url = result.Data?.ToString(); fileName = Utils.GetTempPath(Utils.GetGuid()); await downloadHandle.DownloadFileAsync(url, fileName, true, _timeout); } else { - _updateFunc?.Invoke(false, args.Msg); + _updateFunc?.Invoke(false, result.Msg); } } @@ -100,22 +86,22 @@ namespace ServiceLib.Services }; _updateFunc?.Invoke(false, string.Format(ResUI.MsgStartUpdating, type)); - var args = await CheckUpdateAsync(downloadHandle, type, preRelease); - if (args.Success) + var result = await CheckUpdateAsync(downloadHandle, type, preRelease); + if (result.Success) { _updateFunc?.Invoke(false, string.Format(ResUI.MsgParsingSuccessfully, type)); - _updateFunc?.Invoke(false, args.Msg); + _updateFunc?.Invoke(false, result.Msg); - url = args.Url; + url = result.Data?.ToString(); var ext = url.Contains(".tar.gz") ? ".tar.gz" : Path.GetExtension(url); fileName = Utils.GetTempPath(Utils.GetGuid() + ext); await downloadHandle.DownloadFileAsync(url, fileName, true, _timeout); } else { - if (!args.Msg.IsNullOrEmpty()) + if (!result.Msg.IsNullOrEmpty()) { - _updateFunc?.Invoke(false, args.Msg); + _updateFunc?.Invoke(false, result.Msg); } } } @@ -126,7 +112,7 @@ namespace ServiceLib.Services _updateFunc = updateFunc; _updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart); - var subItem = AppHandler.Instance.SubItems().OrderBy(t => t.sort).ToList(); + var subItem = await AppHandler.Instance.SubItems(); if (subItem == null || subItem.Count <= 0) { @@ -264,36 +250,59 @@ namespace ServiceLib.Services updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time)); } - #region private + #region CheckUpdate private - private async Task CheckUpdateAsync(DownloadService downloadHandle, ECoreType type, bool preRelease) + private async Task CheckUpdateAsync(DownloadService downloadHandle, ECoreType type, bool preRelease) { try { - var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type); - var url = coreInfo?.ReleaseApiUrl; - - var result = await downloadHandle.TryDownloadString(url, true, Global.AppName); - if (Utils.IsNotEmpty(result)) + var result = await GetRemoteVersion(downloadHandle, type, preRelease); + if (!result.Success || result.Data is null) { - return await ParseDownloadUrl(type, result, preRelease); - } - else - { - return new ResultEventArgs(false, ""); + return result; } + return await ParseDownloadUrl(type, (SemanticVersion)result.Data); } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); _updateFunc?.Invoke(false, ex.Message); - return new ResultEventArgs(false, ex.Message); + return new RetResult(false, ex.Message); } } - /// - /// 获取Core版本 - /// + private async Task GetRemoteVersion(DownloadService downloadHandle, ECoreType type, bool preRelease) + { + var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type); + var tagName = string.Empty; + if (preRelease) + { + var url = coreInfo?.ReleaseApiUrl; + var result = await downloadHandle.TryDownloadString(url, true, Global.AppName); + if (Utils.IsNullOrEmpty(result)) + { + return new RetResult(false, ""); + } + + var gitHubReleases = JsonUtils.Deserialize>(result); + var gitHubRelease = preRelease ? gitHubReleases?.First() : gitHubReleases?.First(r => r.Prerelease == false); + tagName = gitHubRelease?.TagName; + //var body = gitHubRelease?.Body; + } + else + { + var url = Path.Combine(coreInfo.Url, "latest"); + var lastUrl = await downloadHandle.UrlRedirectAsync(url, true); + if (lastUrl == null) + { + return new RetResult(false, ""); + } + + tagName = lastUrl?.Split("/tag/").LastOrDefault(); + } + return new RetResult(true, "", new SemanticVersion(tagName)); + } + private async Task GetCoreVersion(ECoreType type) { try @@ -347,15 +356,10 @@ namespace ServiceLib.Services } } - private async Task ParseDownloadUrl(ECoreType type, string gitHubReleaseApi, bool preRelease) + private async Task ParseDownloadUrl(ECoreType type, SemanticVersion version) { try { - var gitHubReleases = JsonUtils.Deserialize>(gitHubReleaseApi); - var gitHubRelease = preRelease ? gitHubReleases?.First() : gitHubReleases?.First(r => r.Prerelease == false); - var version = new SemanticVersion(gitHubRelease?.TagName); - var body = gitHubRelease?.Body; - var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type); SemanticVersion curVersion; string message; @@ -398,16 +402,16 @@ namespace ServiceLib.Services if (curVersion >= version && version != new SemanticVersion(0, 0, 0)) { - return new ResultEventArgs(false, message); + return new RetResult(false, message); } - return new ResultEventArgs(true, body, url); + return new RetResult(true, "", url); } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); _updateFunc?.Invoke(false, ex.Message); - return new ResultEventArgs(false, ex.Message); + return new RetResult(false, ex.Message); } } @@ -419,7 +423,7 @@ namespace ServiceLib.Services if (coreInfo?.CoreType == ECoreType.v2rayN && File.Exists(Path.Combine(Utils.StartupPath(), "wpfgfx_cor3.dll")) && File.Exists(Path.Combine(Utils.StartupPath(), "D3DCompiler_47_cor3.dll")) - ) + ) { return coreInfo?.DownloadUrlWin64?.Replace(".zip", "-SelfContained.zip"); } @@ -444,6 +448,10 @@ namespace ServiceLib.Services return null; } + #endregion CheckUpdate private + + #region Geo private + private async Task UpdateGeoFile(string geoName, Config config, Action updateFunc) { _config = config; @@ -469,7 +477,7 @@ namespace ServiceLib.Services var geoSiteFiles = new List(); //Collect used files list - var routingItems = AppHandler.Instance.RoutingItems(); + var routingItems = await AppHandler.Instance.RoutingItems(); foreach (var routing in routingItems) { var rules = JsonUtils.Deserialize>(routing.ruleSet); @@ -558,6 +566,6 @@ namespace ServiceLib.Services await downloadHandle.DownloadFileAsync(url, tmpFileName, true, _timeout); } - #endregion private + #endregion Geo private } } \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs index 30a336d84d..63ac0ce8bc 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs @@ -22,30 +22,21 @@ namespace ServiceLib.ViewModels _config = AppHandler.Instance.Config; _updateView = updateView; - if (profileItem.indexId.IsNullOrEmpty()) - { - SelectedSource = profileItem; - } - else - { - SelectedSource = JsonUtils.DeepCopy(profileItem); - } - CoreType = SelectedSource?.coreType?.ToString(); - BrowseServerCmd = ReactiveCommand.CreateFromTask(async () => { _updateView?.Invoke(EViewAction.BrowseServer, null); }); - EditServerCmd = ReactiveCommand.CreateFromTask(async () => { await EditServer(); }); - SaveServerCmd = ReactiveCommand.CreateFromTask(async () => { await SaveServerAsync(); }); + + SelectedSource = profileItem.indexId.IsNullOrEmpty() ? profileItem : JsonUtils.DeepCopy(profileItem); + CoreType = SelectedSource?.coreType?.ToString(); } private async Task SaveServerAsync() @@ -82,7 +73,7 @@ namespace ServiceLib.ViewModels return; } - var item = AppHandler.Instance.GetProfileItem(SelectedSource.indexId); + var item = await AppHandler.Instance.GetProfileItem(SelectedSource.indexId); item ??= SelectedSource; item.address = fileName; if (await ConfigHandler.AddCustomServer(_config, item, false) == 0) diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs index 5bff42feeb..8ac3ebb600 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs @@ -17,9 +17,13 @@ namespace ServiceLib.ViewModels public AddServerViewModel(ProfileItem profileItem, Func>? updateView) { _config = AppHandler.Instance.Config; - _updateView = updateView; + SaveCmd = ReactiveCommand.CreateFromTask(async () => + { + await SaveServerAsync(); + }); + if (profileItem.indexId.IsNullOrEmpty()) { profileItem.network = Global.DefaultNetwork; @@ -33,11 +37,6 @@ namespace ServiceLib.ViewModels SelectedSource = JsonUtils.DeepCopy(profileItem); } CoreType = SelectedSource?.coreType?.ToString(); - - SaveCmd = ReactiveCommand.CreateFromTask(async () => - { - await SaveServerAsync(); - }); } private async Task SaveServerAsync() diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs index 2712cb3dbe..ddb808c650 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs @@ -29,7 +29,6 @@ namespace ServiceLib.ViewModels { await WebDavCheck(); }); - RemoteBackupCmd = ReactiveCommand.CreateFromTask(async () => { await RemoteBackup(); diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs index b314c79bea..13249f85dc 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs @@ -17,31 +17,25 @@ namespace ServiceLib.ViewModels public IObservableCollection CheckUpdateItems => _checkUpdateItem; public ReactiveCommand CheckUpdateCmd { get; } [Reactive] public bool EnableCheckPreReleaseUpdate { get; set; } - [Reactive] public bool IsCheckUpdate { get; set; } - [Reactive] public bool AutoRun { get; set; } public CheckUpdateViewModel(Func>? updateView) { _config = AppHandler.Instance.Config; _updateView = updateView; - RefreshSubItems(); - CheckUpdateCmd = ReactiveCommand.CreateFromTask(async () => { - await CheckUpdate() - .ContinueWith(t => - { - _ = UpdateFinished(); - }); + await CheckUpdate(); }); + EnableCheckPreReleaseUpdate = _config.guiItem.checkPreReleaseUpdate; - IsCheckUpdate = true; this.WhenAnyValue( x => x.EnableCheckPreReleaseUpdate, y => y == true) .Subscribe(c => { _config.guiItem.checkPreReleaseUpdate = EnableCheckPreReleaseUpdate; }); + + RefreshSubItems(); } private void RefreshSubItems() @@ -86,31 +80,31 @@ namespace ServiceLib.ViewModels _lstUpdated = _checkUpdateItem.Where(x => x.IsSelected == true) .Select(x => new CheckUpdateItem() { CoreType = x.CoreType }).ToList(); - for (int k = _checkUpdateItem.Count - 1; k >= 0; k--) + for (var k = _checkUpdateItem.Count - 1; k >= 0; k--) { var item = _checkUpdateItem[k]; - if (item.IsSelected == true) + if (item.IsSelected != true) continue; + + UpdateView(item.CoreType, "..."); + if (item.CoreType == _geo) { - IsCheckUpdate = false; - UpdateView(item.CoreType, "..."); - if (item.CoreType == _geo) - { - await CheckUpdateGeo(); - } - else if (item.CoreType == _v2rayN) - { - await CheckUpdateN(EnableCheckPreReleaseUpdate); - } - else if (item.CoreType == ECoreType.mihomo.ToString()) - { - await CheckUpdateCore(item, false); - } - else - { - await CheckUpdateCore(item, EnableCheckPreReleaseUpdate); - } + await CheckUpdateGeo(); + } + else if (item.CoreType == _v2rayN) + { + await CheckUpdateN(EnableCheckPreReleaseUpdate); + } + else if (item.CoreType == ECoreType.mihomo.ToString()) + { + await CheckUpdateCore(item, false); + } + else + { + await CheckUpdateCore(item, EnableCheckPreReleaseUpdate); } } + + await UpdateFinished(); } private void UpdatedPlusPlus(string coreType, string fileName) @@ -204,7 +198,6 @@ namespace ServiceLib.ViewModels { if (blReload) { - IsCheckUpdate = true; Locator.Current.GetService()?.Reload(); } else diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs index 325871f5b6..14f91385d0 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs @@ -10,7 +10,6 @@ namespace ServiceLib.ViewModels public class ClashConnectionsViewModel : MyReactiveObject { private IObservableCollection _connectionItems = new ObservableCollectionExtended(); - public IObservableCollection ConnectionItems => _connectionItems; [Reactive] @@ -42,13 +41,12 @@ namespace ServiceLib.ViewModels this.WhenAnyValue( x => x.SortingSelected, y => y >= 0) - .Subscribe(c => DoSortingSelected(c)); + .Subscribe(async c => await DoSortingSelected(c)); this.WhenAnyValue( x => x.AutoRefresh, y => y == true) .Subscribe(c => { _config.clashUIItem.connectionsAutoRefresh = AutoRefresh; }); - ConnectionCloseCmd = ReactiveCommand.CreateFromTask(async () => { await ClashConnectionClose(false); @@ -62,26 +60,12 @@ namespace ServiceLib.ViewModels Init(); } - private void DoSortingSelected(bool c) - { - if (!c) - { - return; - } - if (SortingSelected != _config.clashUIItem.connectionsSorting) - { - _config.clashUIItem.connectionsSorting = SortingSelected; - } - - GetClashConnections(); - } - - private void Init() + private async Task Init() { var lastTime = DateTime.Now; Observable.Interval(TimeSpan.FromSeconds(5)) - .Subscribe(x => + .Subscribe(async x => { if (!(AutoRefresh && _config.uiItem.showInTaskbar && _config.IsRunningCore(ECoreType.sing_box))) { @@ -92,7 +76,7 @@ namespace ServiceLib.ViewModels { if ((dtNow - lastTime).Minutes % _config.clashUIItem.connectionsRefreshInterval == 0) { - GetClashConnections(); + await GetClashConnections(); lastTime = dtNow; } Task.Delay(1000).Wait(); @@ -100,6 +84,20 @@ namespace ServiceLib.ViewModels }); } + private async Task DoSortingSelected(bool c) + { + if (!c) + { + return; + } + if (SortingSelected != _config.clashUIItem.connectionsSorting) + { + _config.clashUIItem.connectionsSorting = SortingSelected; + } + + await GetClashConnections(); + } + private async Task GetClashConnections() { var ret = await ClashApiHandler.Instance.GetClashConnectionsAsync(_config); diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs index 74e512577d..5fea4792c5 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs @@ -46,33 +46,6 @@ namespace ServiceLib.ViewModels _config = AppHandler.Instance.Config; _updateView = updateView; - SelectedGroup = new(); - SelectedDetail = new(); - - AutoRefresh = _config.clashUIItem.proxiesAutoRefresh; - SortingSelected = _config.clashUIItem.proxiesSorting; - RuleModeSelected = (int)_config.clashUIItem.ruleMode; - - this.WhenAnyValue( - x => x.SelectedGroup, - y => y != null && Utils.IsNotEmpty(y.name)) - .Subscribe(c => RefreshProxyDetails(c)); - - this.WhenAnyValue( - x => x.RuleModeSelected, - y => y >= 0) - .Subscribe(c => DoRulemodeSelected(c)); - - this.WhenAnyValue( - x => x.SortingSelected, - y => y >= 0) - .Subscribe(c => DoSortingSelected(c)); - - this.WhenAnyValue( - x => x.AutoRefresh, - y => y == true) - .Subscribe(c => { _config.clashUIItem.proxiesAutoRefresh = AutoRefresh; }); - ProxiesReloadCmd = ReactiveCommand.CreateFromTask(async () => { await ProxiesReload(); @@ -91,11 +64,42 @@ namespace ServiceLib.ViewModels await SetActiveProxy(); }); - ProxiesReload(); - DelayTestTask(); + SelectedGroup = new(); + SelectedDetail = new(); + AutoRefresh = _config.clashUIItem.proxiesAutoRefresh; + SortingSelected = _config.clashUIItem.proxiesSorting; + RuleModeSelected = (int)_config.clashUIItem.ruleMode; + + this.WhenAnyValue( + x => x.SelectedGroup, + y => y != null && Utils.IsNotEmpty(y.name)) + .Subscribe(c => RefreshProxyDetails(c)); + + this.WhenAnyValue( + x => x.RuleModeSelected, + y => y >= 0) + .Subscribe(async c => await DoRulemodeSelected(c)); + + this.WhenAnyValue( + x => x.SortingSelected, + y => y >= 0) + .Subscribe(c => DoSortingSelected(c)); + + this.WhenAnyValue( + x => x.AutoRefresh, + y => y == true) + .Subscribe(c => { _config.clashUIItem.proxiesAutoRefresh = AutoRefresh; }); + + Init(); } - private void DoRulemodeSelected(bool c) + private async Task Init() + { + await ProxiesReload(); + await DelayTestTask(); + } + + private async Task DoRulemodeSelected(bool c) { if (!c) { @@ -105,16 +109,16 @@ namespace ServiceLib.ViewModels { return; } - SetRuleModeCheck((ERuleMode)RuleModeSelected); + await SetRuleModeCheck((ERuleMode)RuleModeSelected); } - public void SetRuleModeCheck(ERuleMode mode) + public async Task SetRuleModeCheck(ERuleMode mode) { if (_config.clashUIItem.ruleMode == mode) { return; } - SetRuleMode(mode); + await SetRuleMode(mode); } private void DoSortingSelected(bool c) @@ -385,7 +389,7 @@ namespace ServiceLib.ViewModels { if (item == null) { - GetClashProxies(true); + await GetClashProxies(true); return; } if (Utils.IsNullOrEmpty(result)) @@ -427,7 +431,7 @@ namespace ServiceLib.ViewModels #region task - public void DelayTestTask() + public async Task DelayTestTask() { var lastTime = DateTime.Now; diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs index ef285324b4..f7fcf848b7 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs @@ -23,21 +23,7 @@ namespace ServiceLib.ViewModels public DNSSettingViewModel(Func>? updateView) { _config = AppHandler.Instance.Config; - _updateView = updateView; - - var item = AppHandler.Instance.GetDNSItem(ECoreType.Xray); - useSystemHosts = item.useSystemHosts; - domainStrategy4Freedom = item?.domainStrategy4Freedom ?? string.Empty; - domainDNSAddress = item?.domainDNSAddress ?? string.Empty; - normalDNS = item?.normalDNS ?? string.Empty; - - var item2 = AppHandler.Instance.GetDNSItem(ECoreType.sing_box); - domainStrategy4Freedom2 = item2?.domainStrategy4Freedom ?? string.Empty; - domainDNSAddress2 = item2?.domainDNSAddress ?? string.Empty; - normalDNS2 = item2?.normalDNS ?? string.Empty; - tunDNS2 = item2?.tunDNS ?? string.Empty; - SaveCmd = ReactiveCommand.CreateFromTask(async () => { await SaveSettingAsync(); @@ -53,6 +39,23 @@ namespace ServiceLib.ViewModels normalDNS2 = Utils.GetEmbedText(Global.DNSSingboxNormalFileName); tunDNS2 = Utils.GetEmbedText(Global.TunSingboxDNSFileName); }); + + Init(); + } + + private async Task Init() + { + var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); + useSystemHosts = item.useSystemHosts; + domainStrategy4Freedom = item?.domainStrategy4Freedom ?? string.Empty; + domainDNSAddress = item?.domainDNSAddress ?? string.Empty; + normalDNS = item?.normalDNS ?? string.Empty; + + var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); + domainStrategy4Freedom2 = item2?.domainStrategy4Freedom ?? string.Empty; + domainDNSAddress2 = item2?.domainDNSAddress ?? string.Empty; + normalDNS2 = item2?.normalDNS ?? string.Empty; + tunDNS2 = item2?.tunDNS ?? string.Empty; } private async Task SaveSettingAsync() @@ -91,19 +94,19 @@ namespace ServiceLib.ViewModels } } - var item = AppHandler.Instance.GetDNSItem(ECoreType.Xray); + var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); item.domainStrategy4Freedom = domainStrategy4Freedom; item.domainDNSAddress = domainDNSAddress; item.useSystemHosts = useSystemHosts; item.normalDNS = normalDNS; - ConfigHandler.SaveDNSItems(_config, item); + await ConfigHandler.SaveDNSItems(_config, item); - var item2 = AppHandler.Instance.GetDNSItem(ECoreType.sing_box); + var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); item2.domainStrategy4Freedom = domainStrategy4Freedom2; item2.domainDNSAddress = domainDNSAddress2; item2.normalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(normalDNS2)); item2.tunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(tunDNS2)); ; - ConfigHandler.SaveDNSItems(_config, item2); + await ConfigHandler.SaveDNSItems(_config, item2); NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); _updateView?.Invoke(EViewAction.CloseWindow, null); diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index 016297e6dd..4110070e11 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -70,10 +70,6 @@ namespace ServiceLib.ViewModels _config = AppHandler.Instance.Config; _updateView = updateView; - Init(); - - _config.uiItem.showInTaskbar = true; - #region WhenAnyValue && ReactiveCommand //servers @@ -203,13 +199,15 @@ namespace ServiceLib.ViewModels #endregion WhenAnyValue && ReactiveCommand - AutoHideStartup(); + Init(); } - private void Init() + private async Task Init() { - ConfigHandler.InitBuiltinRouting(_config); - ConfigHandler.InitBuiltinDNS(_config); + _config.uiItem.showInTaskbar = true; + + await ConfigHandler.InitBuiltinRouting(_config); + await ConfigHandler.InitBuiltinDNS(_config); CoreHandler.Instance.Init(_config, UpdateHandler); TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler); @@ -218,7 +216,8 @@ namespace ServiceLib.ViewModels StatisticsHandler.Instance.Init(_config, UpdateStatisticsHandler); } - Reload(); + await Reload(); + await AutoHideStartup(); } #endregion Init @@ -285,7 +284,7 @@ namespace ServiceLib.ViewModels //if (blWindowsShutDown) await SysProxyHandler.UpdateSysProxy(_config, true); - ConfigHandler.SaveConfig(_config); + await ConfigHandler.SaveConfig(_config); await ProfileExHandler.Instance.SaveTo(); await StatisticsHandler.Instance.SaveTo(); StatisticsHandler.Instance.Close(); @@ -371,7 +370,7 @@ namespace ServiceLib.ViewModels RefreshServers(); if (item.indexId == _config.indexId) { - Reload(); + await Reload(); } } } @@ -464,7 +463,7 @@ namespace ServiceLib.ViewModels if (ret == true) { Locator.Current.GetService()?.InboundDisplayStatus(); - Reload(); + await Reload(); } } @@ -473,9 +472,9 @@ namespace ServiceLib.ViewModels var ret = await _updateView?.Invoke(EViewAction.RoutingSettingWindow, null); if (ret == true) { - ConfigHandler.InitBuiltinRouting(_config); + await ConfigHandler.InitBuiltinRouting(_config); Locator.Current.GetService()?.RefreshRoutingsMenu(); - Reload(); + await Reload(); } } @@ -484,7 +483,7 @@ namespace ServiceLib.ViewModels var ret = await _updateView?.Invoke(EViewAction.DNSSettingWindow, null); if (ret == true) { - Reload(); + await Reload(); } } @@ -508,7 +507,7 @@ namespace ServiceLib.ViewModels private async Task ClearServerStatistics() { - StatisticsHandler.Instance.ClearAllServerStatistics(); + await StatisticsHandler.Instance.ClearAllServerStatistics(); RefreshServers(); } @@ -535,6 +534,7 @@ namespace ServiceLib.ViewModels await LoadCore(); Locator.Current.GetService()?.TestServerAvailability(); await SysProxyHandler.UpdateSysProxy(_config, false); + _updateView?.Invoke(EViewAction.DispatcherReload, null); } @@ -552,35 +552,29 @@ namespace ServiceLib.ViewModels private async Task LoadCore() { + //if (_config.tunModeItem.enableTun) + //{ + // Task.Delay(1000).Wait(); + // WindowsUtils.RemoveTunDevice(); + //} await Task.Run(async () => { - //if (_config.tunModeItem.enableTun) - //{ - // Task.Delay(1000).Wait(); - // WindowsUtils.RemoveTunDevice(); - //} - var node = await ConfigHandler.GetDefaultServer(_config); - CoreHandler.Instance.LoadCore(node); + await CoreHandler.Instance.LoadCore(node); }); } - public void CloseCore() + public async Task CloseCore() { - ConfigHandler.SaveConfig(_config, false); + await ConfigHandler.SaveConfig(_config, false); CoreHandler.Instance.CoreStop(); } - private void AutoHideStartup() + private async Task AutoHideStartup() { if (_config.uiItem.autoHideStartup) { - Observable.Range(1, 1) - .Delay(TimeSpan.FromSeconds(1)) - .Subscribe(async x => - { - ShowHideWindow(false); - }); + ShowHideWindow(false); } } @@ -591,12 +585,12 @@ namespace ServiceLib.ViewModels public async Task ApplyRegionalPreset(EPresetType type) { await ConfigHandler.ApplyRegionalPreset(_config, type); - ConfigHandler.InitRouting(_config); + await ConfigHandler.InitRouting(_config); Locator.Current.GetService()?.RefreshRoutingsMenu(); - ConfigHandler.SaveConfig(_config, false); + await ConfigHandler.SaveConfig(_config, false); await new UpdateService().UpdateGeoFileAll(_config, UpdateHandler); - Reload(); + await Reload(); } #endregion Presets diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs index 1c9b5ce597..5ddec596cf 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs @@ -23,9 +23,6 @@ namespace ServiceLib.ViewModels { _config = AppHandler.Instance.Config; _updateView = updateView; - - MessageBus.Current.Listen(EMsgCommand.SendMsgView.ToString()).Subscribe(async x => await AppendQueueMsg(x)); - MsgFilter = _config.msgUIItem.mainMsgFilter ?? string.Empty; AutoRefresh = _config.msgUIItem.autoRefresh ?? true; @@ -37,6 +34,13 @@ namespace ServiceLib.ViewModels x => x.AutoRefresh, y => y == true) .Subscribe(c => { _config.msgUIItem.autoRefresh = AutoRefresh; }); + + MessageBus.Current.Listen(EMsgCommand.SendMsgView.ToString()).Subscribe(OnNext); + } + + private async void OnNext(string x) + { + await AppendQueueMsg(x); } private async Task AppendQueueMsg(string msg) diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs index d00d797d0a..012caa0640 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs @@ -105,9 +105,18 @@ namespace ServiceLib.ViewModels public OptionSettingViewModel(Func>? updateView) { _config = AppHandler.Instance.Config; - _updateView = updateView; + SaveCmd = ReactiveCommand.CreateFromTask(async () => + { + await SaveSettingAsync(); + }); + + Init(); + } + + private async Task Init() + { #region Core var inbound = _config.inbound[0]; @@ -191,15 +200,10 @@ namespace ServiceLib.ViewModels #endregion Tun mode - InitCoreType(); - - SaveCmd = ReactiveCommand.CreateFromTask(async () => - { - await SaveSettingAsync(); - }); + await InitCoreType(); } - private void InitCoreType() + private async Task InitCoreType() { if (_config.coreTypeItem == null) { @@ -339,7 +343,7 @@ namespace ServiceLib.ViewModels _config.tunModeItem.enableIPv6Address = TunEnableIPv6Address; //coreType - SaveCoreType(); + await SaveCoreType(); if (await ConfigHandler.SaveConfig(_config) == 0) { @@ -359,7 +363,7 @@ namespace ServiceLib.ViewModels } } - private int SaveCoreType() + private async Task SaveCoreType() { for (int k = 1; k <= _config.coreTypeItem.Count; k++) { @@ -396,7 +400,6 @@ namespace ServiceLib.ViewModels } item.coreType = (ECoreType)Enum.Parse(typeof(ECoreType), type); } - return 0; } } } \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs index e3d7a2afb3..39ed44e7df 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs @@ -99,20 +99,6 @@ namespace ServiceLib.ViewModels _config = AppHandler.Instance.Config; _updateView = updateView; - if (_updateView != null) - { - MessageBus.Current.Listen(EMsgCommand.RefreshProfiles.ToString()) - .Subscribe(async x => await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null)); - } - - SelectedProfile = new(); - SelectedSub = new(); - SelectedMoveToGroup = new(); - SelectedServer = new(); - - RefreshSubscriptions(); - RefreshServers(); - #region WhenAnyValue && ReactiveCommand var canEditRemove = this.WhenAnyValue( @@ -122,16 +108,16 @@ namespace ServiceLib.ViewModels this.WhenAnyValue( x => x.SelectedSub, y => y != null && !y.remarks.IsNullOrEmpty() && _config.subIndexId != y.id) - .Subscribe(c => SubSelectedChangedAsync(c)); + .Subscribe(async c => await SubSelectedChangedAsync(c)); this.WhenAnyValue( x => x.SelectedMoveToGroup, y => y != null && !y.remarks.IsNullOrEmpty()) - .Subscribe(c => MoveToGroup(c)); + .Subscribe(async c => await MoveToGroup(c)); this.WhenAnyValue( x => x.SelectedServer, y => y != null && !y.Text.IsNullOrEmpty()) - .Subscribe(c => ServerSelectedChanged(c)); + .Subscribe(async c => await ServerSelectedChanged(c)); this.WhenAnyValue( x => x.ServerFilter, @@ -240,12 +226,35 @@ namespace ServiceLib.ViewModels }); #endregion WhenAnyValue && ReactiveCommand + + if (_updateView != null) + { + MessageBus.Current.Listen(EMsgCommand.RefreshProfiles.ToString()).Subscribe(OnNext); + } + + Init(); + } + + private async Task Init() + { + SelectedProfile = new(); + SelectedSub = new(); + SelectedMoveToGroup = new(); + SelectedServer = new(); + + await RefreshSubscriptions(); + RefreshServers(); } #endregion Init #region Actions + private async void OnNext(string x) + { + await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null); + } + private void Reload() { Locator.Current.GetService()?.Reload(); @@ -350,9 +359,9 @@ namespace ServiceLib.ViewModels MessageBus.Current.SendMessage("", EMsgCommand.RefreshProfiles.ToString()); } - public void RefreshServersBiz() + public async Task RefreshServersBiz() { - var lstModel = AppHandler.Instance.ProfileItemsEx(_config.subIndexId, _serverFilter); + var lstModel = await AppHandler.Instance.ProfileItemsEx(_config.subIndexId, _serverFilter); _lstProfile = JsonUtils.Deserialize>(JsonUtils.Serialize(lstModel)) ?? []; _profileItems.Clear(); @@ -371,12 +380,13 @@ namespace ServiceLib.ViewModels } } - public void RefreshSubscriptions() + public async Task RefreshSubscriptions() { _subItems.Clear(); _subItems.Add(new SubItem { remarks = ResUI.AllGroupServers }); - foreach (var item in AppHandler.Instance.SubItems().OrderBy(t => t.sort)) + + foreach (var item in await AppHandler.Instance.SubItems()) { _subItems.Add(item); } @@ -394,12 +404,12 @@ namespace ServiceLib.ViewModels #region Add Servers - private int GetProfileItems(out List lstSelecteds, bool latest) + private async Task?> GetProfileItems(bool latest) { - lstSelecteds = new List(); + var lstSelecteds = new List(); if (SelectedProfiles == null || SelectedProfiles.Count <= 0) { - return -1; + return null; } var orderProfiles = SelectedProfiles?.OrderBy(t => t.sort); @@ -407,7 +417,7 @@ namespace ServiceLib.ViewModels { foreach (var profile in orderProfiles) { - var item = AppHandler.Instance.GetProfileItem(profile.indexId); + var item = await AppHandler.Instance.GetProfileItem(profile.indexId); if (item is not null) { lstSelecteds.Add(item); @@ -419,7 +429,7 @@ namespace ServiceLib.ViewModels lstSelecteds = JsonUtils.Deserialize>(JsonUtils.Serialize(orderProfiles)); } - return 0; + return lstSelecteds; } public async Task EditServerAsync(EConfigType eConfigType) @@ -428,7 +438,7 @@ namespace ServiceLib.ViewModels { return; } - var item = AppHandler.Instance.GetProfileItem(SelectedProfile.indexId); + var item = await AppHandler.Instance.GetProfileItem(SelectedProfile.indexId); if (item is null) { NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectServer); @@ -457,7 +467,8 @@ namespace ServiceLib.ViewModels public async Task RemoveServerAsync() { - if (GetProfileItems(out List lstSelecteds, true) < 0) + var lstSelecteds = await GetProfileItems(true); + if (lstSelecteds == null) { return; } @@ -467,7 +478,7 @@ namespace ServiceLib.ViewModels } var exists = lstSelecteds.Exists(t => t.indexId == _config.indexId); - ConfigHandler.RemoveServer(_config, lstSelecteds); + await ConfigHandler.RemoveServer(_config, lstSelecteds); NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); RefreshServers(); @@ -487,7 +498,8 @@ namespace ServiceLib.ViewModels private async Task CopyServer() { - if (GetProfileItems(out List lstSelecteds, false) < 0) + var lstSelecteds = await GetProfileItems(false); + if (lstSelecteds == null) { return; } @@ -504,7 +516,7 @@ namespace ServiceLib.ViewModels { return; } - SetDefaultServer(SelectedProfile.indexId); + await SetDefaultServer(SelectedProfile.indexId); } public async Task SetDefaultServer(string indexId) @@ -517,7 +529,7 @@ namespace ServiceLib.ViewModels { return; } - var item = AppHandler.Instance.GetProfileItem(indexId); + var item = await AppHandler.Instance.GetProfileItem(indexId); if (item is null) { NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectServer); @@ -531,7 +543,7 @@ namespace ServiceLib.ViewModels } } - private void ServerSelectedChanged(bool c) + private async Task ServerSelectedChanged(bool c) { if (!c) { @@ -545,12 +557,12 @@ namespace ServiceLib.ViewModels { return; } - SetDefaultServer(SelectedServer.ID); + await SetDefaultServer(SelectedServer.ID); } public async Task ShareServerAsync() { - var item = AppHandler.Instance.GetProfileItem(SelectedProfile.indexId); + var item = await AppHandler.Instance.GetProfileItem(SelectedProfile.indexId); if (item is null) { NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectServer); @@ -567,25 +579,26 @@ namespace ServiceLib.ViewModels private async Task SetDefaultMultipleServer(ECoreType coreType) { - if (GetProfileItems(out List lstSelecteds, true) < 0) + var lstSelecteds = await GetProfileItems(true); + if (lstSelecteds == null) { return; } var ret = await ConfigHandler.AddCustomServer4Multiple(_config, lstSelecteds, coreType); - if (ret.Item1 != 0) + if (ret.Success != true) { NoticeHandler.Instance.Enqueue(ResUI.OperationFailed); return; } - if (ret.Item2 == _config.indexId) + if (ret?.Data?.ToString() == _config.indexId) { RefreshServers(); Reload(); } else { - await SetDefaultServer(ret.Item2); + await SetDefaultServer(ret?.Data?.ToString()); } } @@ -607,19 +620,20 @@ namespace ServiceLib.ViewModels } //move server - private void MoveToGroup(bool c) + private async Task MoveToGroup(bool c) { if (!c) { return; } - if (GetProfileItems(out List lstSelecteds, true) < 0) + var lstSelecteds = await GetProfileItems(true); + if (lstSelecteds == null) { return; } - ConfigHandler.MoveToGroup(_config, lstSelecteds, SelectedMoveToGroup.id); + await ConfigHandler.MoveToGroup(_config, lstSelecteds, SelectedMoveToGroup.id); NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); RefreshServers(); @@ -665,7 +679,8 @@ namespace ServiceLib.ViewModels { SelectedProfiles = _profileItems; } - if (GetProfileItems(out List lstSelecteds, false) < 0) + var lstSelecteds = await GetProfileItems(false); + if (lstSelecteds == null) { return; } @@ -681,7 +696,7 @@ namespace ServiceLib.ViewModels private async Task Export2ClientConfigAsync(bool blClipboard) { - var item = AppHandler.Instance.GetProfileItem(SelectedProfile.indexId); + var item = await AppHandler.Instance.GetProfileItem(SelectedProfile.indexId); if (item is null) { NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectServer); @@ -689,13 +704,14 @@ namespace ServiceLib.ViewModels } if (blClipboard) { - if (CoreConfigHandler.GenerateClientConfig(item, null, out string msg, out string content) != 0) + var result = await CoreConfigHandler.GenerateClientConfig(item, null); + if (result.Success != true) { - NoticeHandler.Instance.Enqueue(msg); + NoticeHandler.Instance.Enqueue(result.Msg); } else { - await _updateView?.Invoke(EViewAction.SetClipboardData, content); + await _updateView?.Invoke(EViewAction.SetClipboardData, result.Data); NoticeHandler.Instance.SendMessage(ResUI.OperationSuccess); } } @@ -705,26 +721,27 @@ namespace ServiceLib.ViewModels } } - public void Export2ClientConfigResult(string fileName, ProfileItem item) + public async Task Export2ClientConfigResult(string fileName, ProfileItem item) { if (Utils.IsNullOrEmpty(fileName)) { return; } - if (CoreConfigHandler.GenerateClientConfig(item, fileName, out string msg, out string content) != 0) + var result = await CoreConfigHandler.GenerateClientConfig(item, null); + if (result.Success != true) { - NoticeHandler.Instance.Enqueue(msg); + NoticeHandler.Instance.Enqueue(result.Msg); } else { - msg = string.Format(ResUI.SaveClientConfigurationIn, fileName); - NoticeHandler.Instance.SendMessageAndEnqueue(msg); + NoticeHandler.Instance.SendMessageAndEnqueue(string.Format(ResUI.SaveClientConfigurationIn, fileName)); } } public async Task Export2ShareUrlAsync(bool blEncode) { - if (GetProfileItems(out List lstSelecteds, true) < 0) + var lstSelecteds = await GetProfileItems(true); + if (lstSelecteds == null) { return; } @@ -767,7 +784,7 @@ namespace ServiceLib.ViewModels } else { - item = AppHandler.Instance.GetSubItem(_config.subIndexId); + item = await AppHandler.Instance.GetSubItem(_config.subIndexId); if (item is null) { return; @@ -775,8 +792,8 @@ namespace ServiceLib.ViewModels } if (await _updateView?.Invoke(EViewAction.SubEditWindow, item) == true) { - RefreshSubscriptions(); - SubSelectedChangedAsync(true); + await RefreshSubscriptions(); + await SubSelectedChangedAsync(true); } } diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs index 1a2419dfea..91fdbdc5ab 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs @@ -29,9 +29,13 @@ namespace ServiceLib.ViewModels public RoutingRuleDetailsViewModel(RulesItem rulesItem, Func>? updateView) { _config = AppHandler.Instance.Config; - _updateView = updateView; + SaveCmd = ReactiveCommand.CreateFromTask(async () => + { + await SaveRulesAsync(); + }); + if (rulesItem.id.IsNullOrEmpty()) { rulesItem.id = Utils.GetGuid(false); @@ -47,11 +51,6 @@ namespace ServiceLib.ViewModels Domain = Utils.List2String(SelectedSource.domain, true); IP = Utils.List2String(SelectedSource.ip, true); Process = Utils.List2String(SelectedSource.process, true); - - SaveCmd = ReactiveCommand.CreateFromTask(async () => - { - await SaveRulesAsync(); - }); } private async Task SaveRulesAsync() diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs index 5e22091cb6..91f90ec242 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs @@ -36,26 +36,11 @@ namespace ServiceLib.ViewModels public RoutingRuleSettingViewModel(RoutingItem routingItem, Func>? updateView) { _config = AppHandler.Instance.Config; - _updateView = updateView; - SelectedSource = new(); - - if (routingItem.id.IsNullOrEmpty()) - { - SelectedRouting = routingItem; - _rules = new(); - } - else - { - SelectedRouting = routingItem; - _rules = JsonUtils.Deserialize>(SelectedRouting.ruleSet); - } - - RefreshRulesItems(); var canEditRemove = this.WhenAnyValue( - x => x.SelectedSource, - selectedSource => selectedSource != null && !selectedSource.outboundTag.IsNullOrEmpty()); + x => x.SelectedSource, + selectedSource => selectedSource != null && !selectedSource.outboundTag.IsNullOrEmpty()); RuleAddCmd = ReactiveCommand.CreateFromTask(async () => { @@ -104,6 +89,12 @@ namespace ServiceLib.ViewModels { await SaveRoutingAsync(); }); + + SelectedSource = new(); + SelectedRouting = routingItem; + _rules = routingItem.id.IsNullOrEmpty() ? new() : JsonUtils.Deserialize>(SelectedRouting.ruleSet); + + RefreshRulesItems(); } public void RefreshRulesItems() diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs index 1bee71c823..89e223961d 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs @@ -67,27 +67,14 @@ namespace ServiceLib.ViewModels public RoutingSettingViewModel(Func>? updateView) { _config = AppHandler.Instance.Config; - _updateView = updateView; - SelectedSource = new(); - - ConfigHandler.InitBuiltinRouting(_config); - - enableRoutingAdvanced = _config.routingBasicItem.enableRoutingAdvanced; - domainStrategy = _config.routingBasicItem.domainStrategy; - domainMatcher = _config.routingBasicItem.domainMatcher; - domainStrategy4Singbox = _config.routingBasicItem.domainStrategy4Singbox; - - RefreshRoutingItems(); - - BindingLockedData(); var canEditRemove = this.WhenAnyValue( - x => x.SelectedSource, - selectedSource => selectedSource != null && !selectedSource.remarks.IsNullOrEmpty()); + x => x.SelectedSource, + selectedSource => selectedSource != null && !selectedSource.remarks.IsNullOrEmpty()); this.WhenAnyValue( - x => x.enableRoutingAdvanced) + x => x.enableRoutingAdvanced) .Subscribe(c => enableRoutingBasic = !enableRoutingAdvanced); RoutingBasicImportRulesCmd = ReactiveCommand.CreateFromTask(async () => @@ -116,13 +103,29 @@ namespace ServiceLib.ViewModels { await SaveRoutingAsync(); }); + + Init(); + } + + private async Task Init() + { + SelectedSource = new(); + + enableRoutingAdvanced = _config.routingBasicItem.enableRoutingAdvanced; + domainStrategy = _config.routingBasicItem.domainStrategy; + domainMatcher = _config.routingBasicItem.domainMatcher; + domainStrategy4Singbox = _config.routingBasicItem.domainStrategy4Singbox; + + await ConfigHandler.InitBuiltinRouting(_config); + await RefreshRoutingItems(); + await BindingLockedData(); } #region locked private async Task BindingLockedData() { - _lockedItem = ConfigHandler.GetLockedRoutingItem(_config); + _lockedItem = await ConfigHandler.GetLockedRoutingItem(_config); if (_lockedItem == null) { _lockedItem = new RoutingItem() @@ -148,7 +151,7 @@ namespace ServiceLib.ViewModels } } - private void EndBindingLockedData() + private async Task EndBindingLockedData() { if (_lockedItem != null) { @@ -163,7 +166,7 @@ namespace ServiceLib.ViewModels _lockedItem.ruleSet = JsonUtils.Serialize(_lockedRules, false); - ConfigHandler.SaveRoutingItem(_config, _lockedItem); + await ConfigHandler.SaveRoutingItem(_config, _lockedItem); } } @@ -171,11 +174,11 @@ namespace ServiceLib.ViewModels #region Refresh Save - public void RefreshRoutingItems() + public async Task RefreshRoutingItems() { _routingItems.Clear(); - var routings = AppHandler.Instance.RoutingItems(); + var routings = await AppHandler.Instance.RoutingItems(); foreach (var item in routings) { bool def = false; @@ -206,7 +209,7 @@ namespace ServiceLib.ViewModels _config.routingBasicItem.domainMatcher = domainMatcher; _config.routingBasicItem.domainStrategy4Singbox = domainStrategy4Singbox; - EndBindingLockedData(); + await EndBindingLockedData(); if (await ConfigHandler.SaveConfig(_config) == 0) { @@ -242,7 +245,7 @@ namespace ServiceLib.ViewModels } else { - item = AppHandler.Instance.GetRoutingItem(SelectedSource?.id); + item = await AppHandler.Instance.GetRoutingItem(SelectedSource?.id); if (item is null) { return; @@ -250,7 +253,7 @@ namespace ServiceLib.ViewModels } if (await _updateView?.Invoke(EViewAction.RoutingRuleSettingWindow, item) == true) { - RefreshRoutingItems(); + await RefreshRoutingItems(); IsModified = true; } } @@ -268,20 +271,20 @@ namespace ServiceLib.ViewModels } foreach (var it in SelectedSources ?? [SelectedSource]) { - var item = AppHandler.Instance.GetRoutingItem(it?.id); + var item = await AppHandler.Instance.GetRoutingItem(it?.id); if (item != null) { - ConfigHandler.RemoveRoutingItem(item); + await ConfigHandler.RemoveRoutingItem(item); } } - RefreshRoutingItems(); + await RefreshRoutingItems(); IsModified = true; } public async Task RoutingAdvancedSetDefault() { - var item = AppHandler.Instance.GetRoutingItem(SelectedSource?.id); + var item = await AppHandler.Instance.GetRoutingItem(SelectedSource?.id); if (item is null) { NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectRules); @@ -290,7 +293,7 @@ namespace ServiceLib.ViewModels if (await ConfigHandler.SetDefaultRouting(_config, item) == 0) { - RefreshRoutingItems(); + await RefreshRoutingItems(); IsModified = true; } } @@ -299,7 +302,7 @@ namespace ServiceLib.ViewModels { if (await ConfigHandler.InitRouting(_config, true) == 0) { - RefreshRoutingItems(); + await RefreshRoutingItems(); IsModified = true; } } diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs index 011e7bcfa9..80c5366e48 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs @@ -105,33 +105,12 @@ namespace ServiceLib.ViewModels { _config = AppHandler.Instance.Config; - if (updateView != null) - { - Init(updateView); - } - - SelectedRouting = new(); - SelectedServer = new(); - - if (_config.tunModeItem.enableTun && AppHandler.Instance.IsAdministrator) - { - EnableTun = true; - } - else - { - _config.tunModeItem.enableTun = EnableTun = false; - } - - RefreshRoutingsMenu(); - InboundDisplayStatus(); - ChangeSystemProxyAsync(_config.systemProxyItem.sysProxyType, true); - #region WhenAnyValue && ReactiveCommand this.WhenAnyValue( x => x.SelectedRouting, y => y != null && !y.remarks.IsNullOrEmpty()) - .Subscribe(c => RoutingSelectedChangedAsync(c)); + .Subscribe(async c => await RoutingSelectedChangedAsync(c)); this.WhenAnyValue( x => x.SelectedServer, @@ -142,12 +121,12 @@ namespace ServiceLib.ViewModels this.WhenAnyValue( x => x.SystemProxySelected, y => y >= 0) - .Subscribe(c => DoSystemProxySelected(c)); + .Subscribe(async c => await DoSystemProxySelected(c)); this.WhenAnyValue( x => x.EnableTun, y => y == true) - .Subscribe(c => DoEnableTun(c)); + .Subscribe(async c => await DoEnableTun(c)); NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () => { @@ -190,18 +169,47 @@ namespace ServiceLib.ViewModels }); #endregion WhenAnyValue && ReactiveCommand + + if (updateView != null) + { + InitUpdateView(updateView); + } + Init(); } - public void Init(Func>? updateView) + private async Task Init() + { + SelectedRouting = new(); + SelectedServer = new(); + + if (_config.tunModeItem.enableTun && AppHandler.Instance.IsAdministrator) + { + EnableTun = true; + } + else + { + _config.tunModeItem.enableTun = EnableTun = false; + } + + await RefreshRoutingsMenu(); + await InboundDisplayStatus(); + await ChangeSystemProxyAsync(_config.systemProxyItem.sysProxyType, true); + } + + public void InitUpdateView(Func>? updateView) { _updateView = updateView; if (_updateView != null) { - MessageBus.Current.Listen(EMsgCommand.RefreshProfiles.ToString()) - .Subscribe(async x => await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null)); + MessageBus.Current.Listen(EMsgCommand.RefreshProfiles.ToString()).Subscribe(OnNext); } } + private async void OnNext(string x) + { + await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null); + } + private async Task AddServerViaClipboard() { var service = Locator.Current.GetService(); @@ -222,7 +230,7 @@ namespace ServiceLib.ViewModels public async Task RefreshServersBiz() { - RefreshServersMenu(); + await RefreshServersMenu(); //display running server var running = await ConfigHandler.GetDefaultServer(_config); @@ -238,9 +246,9 @@ namespace ServiceLib.ViewModels } } - private void RefreshServersMenu() + private async Task RefreshServersMenu() { - var lstModel = AppHandler.Instance.ProfileItems(_config.subIndexId, ""); + var lstModel = await AppHandler.Instance.ProfileItems(_config.subIndexId, ""); _servers.Clear(); if (lstModel.Count > _config.guiItem.trayMenuServersLimit) @@ -309,11 +317,11 @@ namespace ServiceLib.ViewModels return; } _config.systemProxyItem.sysProxyType = type; - ChangeSystemProxyAsync(type, true); + await ChangeSystemProxyAsync(type, true); NoticeHandler.Instance.SendMessageEx($"{ResUI.TipChangeSystemProxy} - {_config.systemProxyItem.sysProxyType.ToString()}"); SystemProxySelected = (int)_config.systemProxyItem.sysProxyType; - ConfigHandler.SaveConfig(_config, false); + await ConfigHandler.SaveConfig(_config, false); } public async Task ChangeSystemProxyAsync(ESysProxyType type, bool blChange) @@ -336,7 +344,7 @@ namespace ServiceLib.ViewModels } } - public void RefreshRoutingsMenu() + public async Task RefreshRoutingsMenu() { _routingItems.Clear(); if (!_config.routingBasicItem.enableRoutingAdvanced) @@ -346,7 +354,7 @@ namespace ServiceLib.ViewModels } BlRouting = true; - var routings = AppHandler.Instance.RoutingItems(); + var routings = await AppHandler.Instance.RoutingItems(); foreach (var item in routings) { _routingItems.Add(item); @@ -369,7 +377,7 @@ namespace ServiceLib.ViewModels return; } - var item = AppHandler.Instance.GetRoutingItem(SelectedRouting?.id); + var item = await AppHandler.Instance.GetRoutingItem(SelectedRouting?.id); if (item is null) { return; @@ -387,7 +395,7 @@ namespace ServiceLib.ViewModels } } - private void DoSystemProxySelected(bool c) + private async Task DoSystemProxySelected(bool c) { if (!c) { @@ -397,10 +405,10 @@ namespace ServiceLib.ViewModels { return; } - SetListenerType((ESysProxyType)SystemProxySelected); + await SetListenerType((ESysProxyType)SystemProxySelected); } - private void DoEnableTun(bool c) + private async Task DoEnableTun(bool c) { if (_config.tunModeItem.enableTun != EnableTun) { @@ -412,7 +420,7 @@ namespace ServiceLib.ViewModels Locator.Current.GetService()?.RebootAsAdmin(); return; } - ConfigHandler.SaveConfig(_config); + await ConfigHandler.SaveConfig(_config); Locator.Current.GetService()?.Reload(); } } @@ -421,7 +429,7 @@ namespace ServiceLib.ViewModels #region UI - public void InboundDisplayStatus() + public async Task InboundDisplayStatus() { StringBuilder sb = new(); sb.Append($"[{EInboundProtocol.socks}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}]"); diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs index d58dd257b6..3f38ab9a74 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs @@ -14,27 +14,19 @@ namespace ServiceLib.ViewModels public SubEditViewModel(SubItem subItem, Func>? updateView) { _config = AppHandler.Instance.Config; - _updateView = updateView; - if (subItem.id.IsNullOrEmpty()) - { - SelectedSource = subItem; - } - else - { - SelectedSource = JsonUtils.DeepCopy(subItem); - } - SaveCmd = ReactiveCommand.CreateFromTask(async () => { await SaveSubAsync(); }); + + SelectedSource = subItem.id.IsNullOrEmpty() ? subItem : JsonUtils.DeepCopy(subItem); } private async Task SaveSubAsync() { - string remarks = SelectedSource.remarks; + var remarks = SelectedSource.remarks; if (Utils.IsNullOrEmpty(remarks)) { NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs index 5eb6d6e835..840c1c7e09 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs @@ -25,13 +25,8 @@ namespace ServiceLib.ViewModels public SubSettingViewModel(Func>? updateView) { _config = AppHandler.Instance.Config; - _updateView = updateView; - SelectedSource = new(); - - RefreshSubItems(); - var canEditRemove = this.WhenAnyValue( x => x.SelectedSource, selectedSource => selectedSource != null && !selectedSource.id.IsNullOrEmpty()); @@ -52,12 +47,21 @@ namespace ServiceLib.ViewModels { await _updateView?.Invoke(EViewAction.ShareSub, SelectedSource?.url); }, canEditRemove); + + Init(); } - public void RefreshSubItems() + private async Task Init() + { + SelectedSource = new(); + + await RefreshSubItems(); + } + + public async Task RefreshSubItems() { _subItems.Clear(); - _subItems.AddRange(AppHandler.Instance.SubItems().OrderBy(t => t.sort)); + _subItems.AddRange(await AppHandler.Instance.SubItems()); } public async Task EditSubAsync(bool blNew) @@ -69,7 +73,7 @@ namespace ServiceLib.ViewModels } else { - item = AppHandler.Instance.GetSubItem(SelectedSource?.id); + item = await AppHandler.Instance.GetSubItem(SelectedSource?.id); if (item is null) { return; @@ -77,7 +81,7 @@ namespace ServiceLib.ViewModels } if (await _updateView?.Invoke(EViewAction.SubEditWindow, item) == true) { - RefreshSubItems(); + await RefreshSubItems(); IsModified = true; } } @@ -91,9 +95,9 @@ namespace ServiceLib.ViewModels foreach (var it in SelectedSources ?? [SelectedSource]) { - ConfigHandler.DeleteSubItem(_config, it.id); + await ConfigHandler.DeleteSubItem(_config, it.id); } - RefreshSubItems(); + await RefreshSubItems(); NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); IsModified = true; } diff --git a/v2rayn/v2rayN/v2rayN.Desktop/Views/CheckUpdateView.axaml.cs b/v2rayn/v2rayN/v2rayN.Desktop/Views/CheckUpdateView.axaml.cs index a11a72fadb..6859b5776e 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/Views/CheckUpdateView.axaml.cs +++ b/v2rayn/v2rayN/v2rayN.Desktop/Views/CheckUpdateView.axaml.cs @@ -19,7 +19,6 @@ namespace v2rayN.Desktop.Views this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables); - this.OneWayBind(ViewModel, vm => vm.IsCheckUpdate, v => v.btnCheckUpdate.IsEnabled).DisposeWith(disposables); }); } diff --git a/v2rayn/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayn/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs index f4d6d8ea2d..2c07ac3c8f 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs +++ b/v2rayn/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs @@ -4,7 +4,6 @@ using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.Notifications; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Platform.Storage; using Avalonia.ReactiveUI; using Avalonia.Threading; using DialogHostAvalonia; @@ -40,7 +39,7 @@ namespace v2rayN.Desktop.Views menuCheckUpdate.Click += MenuCheckUpdate_Click; menuBackupAndRestore.Click += MenuBackupAndRestore_Click; - MessageBus.Current.Listen(EMsgCommand.SendSnackMsg.ToString()).Subscribe(x => DelegateSnackMsg(x)); + MessageBus.Current.Listen(EMsgCommand.SendSnackMsg.ToString()).Subscribe(DelegateSnackMsg); ViewModel = new MainWindowViewModel(UpdateViewHandler); Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel)); @@ -123,6 +122,7 @@ namespace v2rayN.Desktop.Views menuSettingsSetUWP.IsVisible = false; menuGlobalHotkeySetting.IsVisible = false; } + menuAddServerViaScan.IsVisible = false; switch (_config.uiItem.mainGirdOrientation) { @@ -289,7 +289,7 @@ namespace v2rayN.Desktop.Views break; case Key.S: - ScanScreenTaskAsync().ContinueWith(_ => { }); + await ScanScreenTaskAsync(); break; } } diff --git a/v2rayn/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs b/v2rayn/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs index d0dbda616f..8956397141 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs +++ b/v2rayn/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs @@ -21,7 +21,7 @@ namespace v2rayN.Desktop.Views //ViewModel = new StatusBarViewModel(UpdateViewHandler); //Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(StatusBarViewModel)); ViewModel = Locator.Current.GetService(); - ViewModel?.Init(UpdateViewHandler); + ViewModel?.InitUpdateView(UpdateViewHandler); txtRunningServerDisplay.Tapped += TxtRunningServerDisplay_Tapped; txtRunningInfoDisplay.Tapped += TxtRunningServerDisplay_Tapped; diff --git a/v2rayn/v2rayN/v2rayN/Views/CheckUpdateView.xaml.cs b/v2rayn/v2rayN/v2rayN/Views/CheckUpdateView.xaml.cs index def6e53ff8..ad676092f5 100644 --- a/v2rayn/v2rayN/v2rayN/Views/CheckUpdateView.xaml.cs +++ b/v2rayn/v2rayN/v2rayN/Views/CheckUpdateView.xaml.cs @@ -19,7 +19,6 @@ namespace v2rayN.Views this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables); - this.OneWayBind(ViewModel, vm => vm.IsCheckUpdate, v => v.btnCheckUpdate.IsEnabled).DisposeWith(disposables); }); } diff --git a/v2rayn/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayn/v2rayN/v2rayN/Views/MainWindow.xaml.cs index 5c233c7ee0..d5b61a5cfe 100644 --- a/v2rayn/v2rayN/v2rayN/Views/MainWindow.xaml.cs +++ b/v2rayn/v2rayN/v2rayN/Views/MainWindow.xaml.cs @@ -36,7 +36,7 @@ namespace v2rayN.Views menuCheckUpdate.Click += MenuCheckUpdate_Click; menuBackupAndRestore.Click += MenuBackupAndRestore_Click; - MessageBus.Current.Listen(EMsgCommand.SendSnackMsg.ToString()).Subscribe(x => DelegateSnackMsg(x)); + MessageBus.Current.Listen(EMsgCommand.SendSnackMsg.ToString()).Subscribe(DelegateSnackMsg); ViewModel = new MainWindowViewModel(UpdateViewHandler); Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel)); diff --git a/v2rayng/README.md b/v2rayng/README.md index 0299c6735e..bc76718b8c 100644 --- a/v2rayng/README.md +++ b/v2rayng/README.md @@ -3,7 +3,7 @@ A V2Ray client for Android, support [Xray core](https://github.com/XTLS/Xray-core) and [v2fly core](https://github.com/v2fly/v2ray-core) [![API](https://img.shields.io/badge/API-21%2B-yellow.svg?style=flat)](https://developer.android.com/about/versions/lollipop) -[![Kotlin Version](https://img.shields.io/badge/Kotlin-1.9.23-blue.svg)](https://kotlinlang.org) +[![Kotlin Version](https://img.shields.io/badge/Kotlin-2.0.21-blue.svg)](https://kotlinlang.org) [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayNG)](https://github.com/2dust/v2rayNG/commits/master) [![CodeFactor](https://www.codefactor.io/repository/github/2dust/v2rayng/badge)](https://www.codefactor.io/repository/github/2dust/v2rayng) [![GitHub Releases](https://img.shields.io/github/downloads/2dust/v2rayNG/latest/total?logo=github)](https://github.com/2dust/v2rayNG/releases) diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/helper/SimpleItemTouchHelperCallback.java b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/helper/SimpleItemTouchHelperCallback.java index e3686921b8..36474fb809 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/helper/SimpleItemTouchHelperCallback.java +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/helper/SimpleItemTouchHelperCallback.java @@ -16,14 +16,14 @@ package com.v2ray.ang.helper; +import android.animation.ValueAnimator; import android.graphics.Canvas; - +import android.view.animation.DecelerateInterpolator; +import androidx.annotation.NonNull; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; -import org.jetbrains.annotations.NotNull; - /** * An implementation of {@link ItemTouchHelper.Callback} that enables basic drag & drop and * swipe-to-dismiss. Drag events are automatically started by an item long-press.
@@ -36,9 +36,12 @@ import org.jetbrains.annotations.NotNull; */ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { - public static final float ALPHA_FULL = 1.0f; + private static final float ALPHA_FULL = 1.0f; + private static final float SWIPE_THRESHOLD = 0.25f; + private static final long ANIMATION_DURATION = 200; private final ItemTouchHelperAdapter mAdapter; + private ValueAnimator mReturnAnimator; public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { mAdapter = adapter; @@ -51,15 +54,14 @@ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { @Override public boolean isItemViewSwipeEnabled() { - return false; + return true; } @Override - public int getMovementFlags(RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder) { - // Set movement flags based on the layout manager + public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { if (recyclerView.getLayoutManager() instanceof GridLayoutManager) { final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; - final int swipeFlags = 0; + final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); } else { final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; @@ -69,61 +71,89 @@ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { } @Override - public boolean onMove(@NotNull RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { + public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder source, @NonNull RecyclerView.ViewHolder target) { if (source.getItemViewType() != target.getItemViewType()) { return false; } - - // Notify the adapter of the move mAdapter.onItemMove(source.getBindingAdapterPosition(), target.getBindingAdapterPosition()); return true; } @Override - public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) { - // Notify the adapter of the dismissal - mAdapter.onItemDismiss(viewHolder.getBindingAdapterPosition()); + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + // 不执行删除操作,仅返回项目到原位 + returnViewToOriginalPosition(viewHolder); } @Override - public void onChildDraw(@NotNull Canvas c, @NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder, float dX, - float dY, int actionState, boolean isCurrentlyActive) { + public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder, + float dX, float dY, int actionState, boolean isCurrentlyActive) { if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { - // Fade out the view as it is swiped out of the parent's bounds - final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth(); + float maxSwipeDistance = viewHolder.itemView.getWidth() * SWIPE_THRESHOLD; + float swipeAmount = Math.abs(dX); + float direction = Math.signum(dX); + + // 限制最大滑动距离 + float translationX = Math.min(swipeAmount, maxSwipeDistance) * direction; + float alpha = ALPHA_FULL - Math.min(swipeAmount, maxSwipeDistance) / maxSwipeDistance; + + viewHolder.itemView.setTranslationX(translationX); viewHolder.itemView.setAlpha(alpha); - viewHolder.itemView.setTranslationX(dX); + + if (swipeAmount >= maxSwipeDistance && isCurrentlyActive) { + returnViewToOriginalPosition(viewHolder); + } } else { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } } + private void returnViewToOriginalPosition(RecyclerView.ViewHolder viewHolder) { + if (mReturnAnimator != null && mReturnAnimator.isRunning()) { + mReturnAnimator.cancel(); + } + + mReturnAnimator = ValueAnimator.ofFloat(viewHolder.itemView.getTranslationX(), 0f); + mReturnAnimator.addUpdateListener(animation -> { + float value = (float) animation.getAnimatedValue(); + viewHolder.itemView.setTranslationX(value); + viewHolder.itemView.setAlpha(1f - Math.abs(value) / (viewHolder.itemView.getWidth() * SWIPE_THRESHOLD)); + }); + mReturnAnimator.setInterpolator(new DecelerateInterpolator()); + mReturnAnimator.setDuration(ANIMATION_DURATION); + mReturnAnimator.start(); + } + @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { - // We only want the active item to change if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { if (viewHolder instanceof ItemTouchHelperViewHolder) { - // Let the view holder know that this item is being moved or dragged ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder; itemViewHolder.onItemSelected(); } } - super.onSelectedChanged(viewHolder, actionState); } @Override - public void clearView(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder) { + public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); - - mAdapter.onItemMoveCompleted(); - viewHolder.itemView.setAlpha(ALPHA_FULL); - if (viewHolder instanceof ItemTouchHelperViewHolder) { - // Tell the view holder it's time to restore the idle state ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder; itemViewHolder.onItemClear(); } + mAdapter.onItemMoveCompleted(); + } + + @Override + public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) { + return 1.1f; // 设置一个大于1的值,确保不会触发默认的滑动删除操作 + } + + @Override + public float getSwipeEscapeVelocity(float defaultValue) { + return defaultValue * 10; // 增加滑动逃逸速度,使得更难触发滑动 } } diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt index 3d2096515f..62adf79f1a 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt @@ -60,8 +60,6 @@ object AppConfig { const val CACHE_KEYWORD_FILTER = "cache_keyword_filter" /** Protocol identifiers. */ - const val PROTOCOL_HTTP: String = "http://" - const val PROTOCOL_HTTPS: String = "https://" const val PROTOCOL_FREEDOM: String = "freedom" /** Broadcast actions. */ @@ -157,5 +155,21 @@ object AppConfig { /** Give a good name to this, IDK*/ const val VPN = "VPN" + // Google API rule constants + const val GOOGLEAPIS_CN_DOMAIN = "domain:googleapis.cn" + const val GOOGLEAPIS_COM_DOMAIN = "googleapis.com" + + // Android Private DNS constants + const val DNS_PUB_DOMAIN = "dns.pub" + const val DNS_ALIDNS_DOMAIN = "dns.alidns.com" + const val DNS_ONE_ONE_DOMAIN = "one.one.one.one" + const val DNS_GOOGLE_DOMAIN = "dns.google" + + val DNS_PUB_ADDRESSES = arrayListOf("1.12.12.12", "120.53.53.53") + val DNS_ALIDNS_ADDRESSES = arrayListOf("223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1") + val DNS_ONE_ONE_ADDRESSES = arrayListOf("1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001") + val DNS_GOOGLE_ADDRESSES = arrayListOf("8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844") + + } diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt index 1dca494174..fd1578e581 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt @@ -16,6 +16,6 @@ enum class EConfigType(val value: Int, val protocolScheme: String) { HTTP(10, AppConfig.HTTP); companion object { - fun fromInt(value: Int) = values().firstOrNull { it.value == value } + fun fromInt(value: Int) = entries.firstOrNull { it.value == value } } } diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/Language.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/Language.kt new file mode 100644 index 0000000000..c517bc75c0 --- /dev/null +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/Language.kt @@ -0,0 +1,18 @@ +package com.v2ray.ang.dto + +enum class Language(val code: String) { + AUTO("auto"), + ENGLISH("en"), + CHINA("zh-rCN"), + TRADITIONAL_CHINESE("zh-rTW"), + VIETNAMESE("vi"), + RUSSIAN("ru"), + PERSIAN("fa"), + BANGLA("bn"); + + companion object { + fun fromCode(code: String): Language { + return entries.find { it.code == code } ?: AUTO + } + } +} diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/RoutingType.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/RoutingType.kt new file mode 100644 index 0000000000..a98ac167c8 --- /dev/null +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/RoutingType.kt @@ -0,0 +1,20 @@ +package com.v2ray.ang.dto + +enum class RoutingType(val fileName: String) { + WHITE("custom_routing_white"), + BLACK("custom_routing_black"), + GLOBAL("custom_routing_global"), + WHITE_IRAN("custom_routing_white_iran"); + + companion object { + fun fromIndex(index: Int): RoutingType { + return when (index) { + 0 -> WHITE + 1 -> BLACK + 2 -> GLOBAL + 3 -> WHITE_IRAN + else -> WHITE + } + } + } +} diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt index 86b27da5c8..880a7b299c 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt @@ -81,10 +81,10 @@ class SubEditActivity : BaseActivity() { toast(R.string.sub_setting_remarks) return false } -// if (TextUtils.isEmpty(subItem.url)) { -// toast(R.string.sub_setting_url) -// return false -// } + if (!Utils.isValidSubUrl(subItem.url)) { + toast(R.string.toast_invalid_url) + return false + } MmkvManager.encodeSubscription(editSubId, subItem) toast(R.string.toast_success) diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt index b4e1b7c49b..ab4a4b9e00 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt @@ -219,7 +219,7 @@ object AngConfigManager { var count = 0 servers.lines() .forEach { str -> - if (str.startsWith(AppConfig.PROTOCOL_HTTP) || str.startsWith(AppConfig.PROTOCOL_HTTPS)) { + if (Utils.isValidSubUrl(str)) { count += importUrlAsSubscription(str) } } diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/JsonUtil.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/JsonUtil.kt index 0c1c950a83..b89b52ff36 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/JsonUtil.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/JsonUtil.kt @@ -23,7 +23,7 @@ object JsonUtil { val gsonPre = GsonBuilder() .setPrettyPrinting() .disableHtmlEscaping() - .registerTypeAdapter( // custom serialiser is needed here since JSON by default parse number as Double, core will fail to start + .registerTypeAdapter( // custom serializer is needed here since JSON by default parse number as Double, core will fail to start object : TypeToken() {}.type, JsonSerializer { src: Double?, _: Type?, _: JsonSerializationContext? -> JsonPrimitive( diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/SettingsManager.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/SettingsManager.kt index 0b1b4a1245..f14caa829f 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/SettingsManager.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/SettingsManager.kt @@ -6,7 +6,12 @@ import android.text.TextUtils import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.GEOIP_PRIVATE import com.v2ray.ang.AppConfig.GEOSITE_PRIVATE +import com.v2ray.ang.AppConfig.ROUTING_BLACK +import com.v2ray.ang.AppConfig.ROUTING_GLOBAL +import com.v2ray.ang.AppConfig.ROUTING_WHITE +import com.v2ray.ang.AppConfig.ROUTING_WHITE_IRAN import com.v2ray.ang.AppConfig.TAG_DIRECT +import com.v2ray.ang.dto.RoutingType import com.v2ray.ang.dto.RulesetItem import com.v2ray.ang.dto.ServerConfig import com.v2ray.ang.util.MmkvManager.decodeProfileConfig @@ -27,13 +32,7 @@ object SettingsManager { } private fun getPresetRoutingRulesets(context: Context, index: Int = 0): MutableList? { - val fileName = when (index) { - 0 -> "custom_routing_white" - 1 -> "custom_routing_black" - 2 -> "custom_routing_global" - 3 -> "custom_routing_white_iran" - else -> "custom_routing_white" - } + val fileName = RoutingType.fromIndex(index).fileName val assets = Utils.readTextFromAssets(context, fileName) if (TextUtils.isEmpty(assets)) { return null @@ -42,6 +41,7 @@ object SettingsManager { return JsonUtil.fromJson(assets, Array::class.java).toMutableList() } + fun resetRoutingRulesets(context: Context, index: Int) { val rulesetList = getPresetRoutingRulesets(context, index) ?: return resetRoutingRulesetsCommon(rulesetList) diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt index 687fac9b77..bb559aaf77 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt @@ -22,6 +22,7 @@ import com.v2ray.ang.AppConfig.ANG_PACKAGE import com.v2ray.ang.AppConfig.LOOPBACK import com.v2ray.ang.BuildConfig import com.v2ray.ang.R +import com.v2ray.ang.dto.Language import com.v2ray.ang.extension.toast import com.v2ray.ang.service.V2RayServiceManager import com.v2ray.ang.util.MmkvManager.settingsStorage @@ -405,21 +406,24 @@ object Utils { } fun getLocale(): Locale { - val lang = settingsStorage?.decodeString(AppConfig.PREF_LANGUAGE) ?: "auto" - return when (lang) { - "auto" -> getSysLocale() - "en" -> Locale.ENGLISH - "zh-rCN" -> Locale.CHINA - "zh-rTW" -> Locale.TRADITIONAL_CHINESE - "vi" -> Locale("vi") - "ru" -> Locale("ru") - "fa" -> Locale("fa") - "bn" -> Locale("bn") - else -> getSysLocale() + val langCode = settingsStorage?.decodeString(AppConfig.PREF_LANGUAGE) ?: Language.AUTO.code + val language = Language.fromCode(langCode) + + return when (language) { + Language.AUTO -> getSysLocale() + Language.ENGLISH -> Locale.ENGLISH + Language.CHINA -> Locale.CHINA + Language.TRADITIONAL_CHINESE -> Locale.TRADITIONAL_CHINESE + Language.VIETNAMESE -> Locale("vi") + Language.RUSSIAN -> Locale("ru") + Language.PERSIAN -> Locale("fa") + Language.BANGLA -> Locale("bn") } } + + private fun getSysLocale(): Locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { LocaleList.getDefault()[0] } else { @@ -465,5 +469,17 @@ object Utils { // if the program gets here, no port in the range was found throw IOException("no free port found") } + + fun isValidSubUrl(value: String?): Boolean { + try { + if (value.isNullOrEmpty()) return false + if (URLUtil.isHttpsUrl(value)) return true + if (URLUtil.isHttpUrl(value) && value.contains(LOOPBACK)) return true + } catch (e: Exception) { + e.printStackTrace() + } + return false + } + } diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt index 1e1b450492..b1265d1839 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt @@ -6,10 +6,20 @@ import android.util.Log import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.ANG_PACKAGE +import com.v2ray.ang.AppConfig.DNS_ALIDNS_ADDRESSES +import com.v2ray.ang.AppConfig.DNS_ALIDNS_DOMAIN +import com.v2ray.ang.AppConfig.DNS_GOOGLE_ADDRESSES +import com.v2ray.ang.AppConfig.DNS_GOOGLE_DOMAIN +import com.v2ray.ang.AppConfig.DNS_ONE_ONE_ADDRESSES +import com.v2ray.ang.AppConfig.DNS_ONE_ONE_DOMAIN +import com.v2ray.ang.AppConfig.DNS_PUB_ADDRESSES +import com.v2ray.ang.AppConfig.DNS_PUB_DOMAIN import com.v2ray.ang.AppConfig.GEOIP_CN import com.v2ray.ang.AppConfig.GEOSITE_CN import com.v2ray.ang.AppConfig.LOOPBACK import com.v2ray.ang.AppConfig.GEOSITE_PRIVATE +import com.v2ray.ang.AppConfig.GOOGLEAPIS_CN_DOMAIN +import com.v2ray.ang.AppConfig.GOOGLEAPIS_COM_DOMAIN import com.v2ray.ang.AppConfig.PROTOCOL_FREEDOM import com.v2ray.ang.AppConfig.TAG_BLOCKED import com.v2ray.ang.AppConfig.TAG_DIRECT @@ -71,7 +81,8 @@ object V2rayConfigUtil { return result } val v2rayConfig = JsonUtil.fromJson(assets, V2rayConfig::class.java) ?: return result - v2rayConfig.log.loglevel = settingsStorage?.decodeString(AppConfig.PREF_LOGLEVEL) ?: "warning" + v2rayConfig.log.loglevel = + settingsStorage?.decodeString(AppConfig.PREF_LOGLEVEL) ?: "warning" v2rayConfig.remarks = config.remarks inbounds(v2rayConfig) @@ -143,7 +154,11 @@ object V2rayConfigUtil { return true } - private fun outbounds(v2rayConfig: V2rayConfig, outbound: V2rayConfig.OutboundBean, isPlugin: Boolean): Pair { + private fun outbounds( + v2rayConfig: V2rayConfig, + outbound: V2rayConfig.OutboundBean, + isPlugin: Boolean + ): Pair { if (isPlugin) { val socksPort = Utils.findFreePort(listOf(100 + SettingsManager.getSocksPort(), 0)) val outboundNew = V2rayConfig.OutboundBean( @@ -190,7 +205,9 @@ object V2rayConfigUtil { private fun routing(v2rayConfig: V2rayConfig): Boolean { try { - v2rayConfig.routing.domainStrategy = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY) ?: "IPIfNonMatch" + v2rayConfig.routing.domainStrategy = + settingsStorage?.decodeString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY) + ?: "IPIfNonMatch" val rulesetItems = MmkvManager.decodeRoutingRulesets() rulesetItems?.forEach { key -> @@ -362,13 +379,14 @@ object V2rayConfigUtil { } // hardcode googleapi rule to fix play store problems - hosts["domain:googleapis.cn"] = "googleapis.com" + hosts[GOOGLEAPIS_CN_DOMAIN] = GOOGLEAPIS_COM_DOMAIN // hardcode popular Android Private DNS rule to fix localhost DNS problem - hosts["dns.pub"] = arrayListOf("1.12.12.12", "120.53.53.53") - hosts["dns.alidns.com"] = arrayListOf("223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1") - hosts["one.one.one.one"] = arrayListOf("1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001") - hosts["dns.google"] = arrayListOf("8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844") + hosts[DNS_PUB_DOMAIN] = DNS_PUB_ADDRESSES + hosts[DNS_ALIDNS_DOMAIN] = DNS_ALIDNS_ADDRESSES + hosts[DNS_ONE_ONE_DOMAIN] = DNS_ONE_ONE_ADDRESSES + hosts[DNS_GOOGLE_DOMAIN] = DNS_GOOGLE_ADDRESSES + // DNS dns对象 v2rayConfig.dns = V2rayConfig.DnsBean( @@ -532,7 +550,11 @@ object V2rayConfigUtil { return true } - private fun moreOutbounds(v2rayConfig: V2rayConfig, subscriptionId: String, isPlugin: Boolean): Pair { + private fun moreOutbounds( + v2rayConfig: V2rayConfig, + subscriptionId: String, + isPlugin: Boolean + ): Pair { val returnPair = Pair(false, "") var domainPort: String = "" diff --git a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/MainViewModel.kt b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/MainViewModel.kt index f807970e53..500762462c 100644 --- a/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/MainViewModel.kt +++ b/v2rayng/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/MainViewModel.kt @@ -43,7 +43,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { var subscriptionId: String = MmkvManager.settingsStorage.decodeString(AppConfig.CACHE_SUBSCRIPTION_ID, "").orEmpty() //var keywordFilter: String = MmkvManager.settingsStorage.decodeString(AppConfig.CACHE_KEYWORD_FILTER, "")?:"" - var keywordFilter = "" + var keywordFilter = "" val serversCache = mutableListOf() val isRunning by lazy { MutableLiveData() } val updateListAction by lazy { MutableLiveData() } @@ -153,7 +153,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } fun updateConfigViaSubAll(): Int { - if (subscriptionId.isNullOrEmpty()) { + if (subscriptionId.isEmpty()) { return AngConfigManager.updateConfigViaSubAll() } else { val subItem = MmkvManager.decodeSubscription(subscriptionId) ?: return 0 @@ -163,7 +163,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { fun exportAllServer(): Int { val serverListCopy = - if (subscriptionId.isNullOrEmpty() && keywordFilter.isNullOrEmpty()) { + if (subscriptionId.isEmpty() && keywordFilter.isNullOrEmpty()) { serverList } else { serversCache.map { it.guid }.toList() @@ -281,7 +281,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } fun removeAllServer() { - if (subscriptionId.isNullOrEmpty() && keywordFilter.isNullOrEmpty()) { + if (subscriptionId.isEmpty() && keywordFilter.isNullOrEmpty()) { MmkvManager.removeAllServer() } else { val serversCopy = serversCache.toList() @@ -292,7 +292,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } fun removeInvalidServer() { - if (subscriptionId.isNullOrEmpty() && keywordFilter.isNullOrEmpty()) { + if (subscriptionId.isEmpty() && keywordFilter.isNullOrEmpty()) { MmkvManager.removeInvalidServer("") } else { val serversCopy = serversCache.toList() @@ -394,4 +394,4 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } } } -} \ No newline at end of file +} diff --git a/v2rayng/V2rayNG/app/src/main/res/layout/activity_bypass_list.xml b/v2rayng/V2rayNG/app/src/main/res/layout/activity_bypass_list.xml index 3772369f14..ae02540773 100644 --- a/v2rayng/V2rayNG/app/src/main/res/layout/activity_bypass_list.xml +++ b/v2rayng/V2rayNG/app/src/main/res/layout/activity_bypass_list.xml @@ -33,17 +33,13 @@ android:gravity="center" android:orientation="horizontal"> - - + android:maxLines="2" + android:text="@string/title_pref_per_app_proxy" + android:textAppearance="@style/TextAppearance.AppCompat.Small" /> @@ -56,18 +52,12 @@ android:gravity="center" android:orientation="horizontal"> - - + android:text="@string/switch_bypass_apps_mode" + android:textAppearance="@style/TextAppearance.AppCompat.Small" /> diff --git a/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml index f4231d5d28..8067393535 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml @@ -300,4 +300,13 @@ লাইট ডার্ক + + চায়না হোয়াইটলিস্ট + চায়না ব্ল্যাকলিস্ট + গ্লোবাল + ইরান হোয়াইটলিস্ট + + + + \ No newline at end of file diff --git a/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml index 05a74893f4..947dcfaeaf 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml @@ -175,7 +175,7 @@ دستگاه‌های دیگر می‌توانند از طریق socks/http به پراکسی توسط نشانی آی‌پی شما متصل شوند، فقط در شبکه مورد اعتماد فعال می‌شوند تا از اتصال غیرمجاز جلوگیری کنند اتصالات از طریق LAN را مجاز کنید، مطمئن شوید که در یک شبکه قابل اعتماد هستید - موز ناامن + مجوز ناامن هنگام استفاده از TLS، به طور پیش‌فرض مجوز ناامن فعال است پورت پروکسی SOCKS5 @@ -202,10 +202,10 @@ درباره کد منبع کانال تلگرام - پشتیبانگیری از پیکربندی + پشتیبان گیری از پیکربندی محل ذخیره سازی: [%s], پس از حذف نصب برنامه یا پاک کردن فضای ذخیره سازی، نسخه پشتیبان پاک می شود بازیابی پیکربندی - اشتراکگذاری پیکربندی + اشتراک گذاری پیکربندی تبلیغات تبلیغات، برای جزئیات بیشتر کلیک کنید (کمک مالی کنید تا حذف شود) diff --git a/v2rayng/V2rayNG/app/src/main/res/values/attrs.xml b/v2rayng/V2rayNG/app/src/main/res/values/attrs.xml index 0df1370f9f..52069cfb15 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values/attrs.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values/attrs.xml @@ -1,6 +1,5 @@ - diff --git a/v2rayng/V2rayNG/build.gradle.kts b/v2rayng/V2rayNG/build.gradle.kts index 22f79b4fa3..acb2cb0e9f 100644 --- a/v2rayng/V2rayNG/build.gradle.kts +++ b/v2rayng/V2rayNG/build.gradle.kts @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "8.4.2" apply false - id("com.android.library") version "8.4.2" apply false - id("org.jetbrains.kotlin.android") version "1.9.23" apply false + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.android.kotlin) apply false } diff --git a/v2rayng/V2rayNG/gradle/libs.versions.toml b/v2rayng/V2rayNG/gradle/libs.versions.toml index 2e70ab1dad..247d5fe718 100644 --- a/v2rayng/V2rayNG/gradle/libs.versions.toml +++ b/v2rayng/V2rayNG/gradle/libs.versions.toml @@ -25,6 +25,8 @@ rxpermissions = "0.12" toastcompat = "1.1.0" viewpager2 = "1.1.0" workRuntimeKtx = "2.9.1" +androidGradlePlugin = "8.4.2" +androidKotlinPlugin = "2.0.21" [libraries] activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityKtx" } @@ -60,4 +62,7 @@ viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "viewpag work-multiprocess = { module = "androidx.work:work-multiprocess", version.ref = "workRuntimeKtx" } work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtx" } -[plugins] \ No newline at end of file +[plugins] +android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } +android-kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "androidKotlinPlugin" } diff --git a/yass/.github/workflows/releases-mingw.yml b/yass/.github/workflows/releases-mingw.yml index f916a93772..76d7d94374 100644 --- a/yass/.github/workflows/releases-mingw.yml +++ b/yass/.github/workflows/releases-mingw.yml @@ -116,7 +116,7 @@ jobs: REM start to build with workaround mkdir build-mingw cd build-mingw - cmake -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_BENCHMARKS=on -DBUILD_TESTS=on -DGUI=on -DMINGW_MSVCRT100=on -DMINGW_WORKAROUND=on .. ${{ env.CMAKE_OPTIONS }} -DCMAKE_C_COMPILER_TARGET=${{ matrix.arch }}-pc-windows-gnu -DCMAKE_CXX_COMPILER_TARGET=${{ matrix.arch }}-pc-windows-gnu -DCMAKE_ASM_COMPILER_TARGET=${{ matrix.arch }}-pc-windows-gnu -DCMAKE_SYSROOT="%CD%\..\third_party\${{ matrix.mingw_dir }}\${{ matrix.arch }}-w64-mingw32" -DUSE_TCMALLOC=on -DUSE_LIBCXX=on -DENABLE_LLD=on -DUSE_ZLIB=on -DUSE_JSONCPP=on -DUSE_CARES=on + cmake -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_BENCHMARKS=on -DBUILD_TESTS=on -DGUI=on -DMINGW_MSVCRT100=on -DMINGW_WORKAROUND=on .. ${{ env.CMAKE_OPTIONS }} -DCMAKE_C_COMPILER_TARGET=${{ matrix.arch }}-pc-windows-gnu -DCMAKE_CXX_COMPILER_TARGET=${{ matrix.arch }}-pc-windows-gnu -DCMAKE_ASM_COMPILER_TARGET=${{ matrix.arch }}-pc-windows-gnu -DCMAKE_SYSROOT="%CD%\..\third_party\${{ matrix.mingw_dir }}\${{ matrix.arch }}-w64-mingw32" -DUSE_LIBCXX=on -DENABLE_LLD=on -DUSE_ZLIB=on -DUSE_JSONCPP=on -DUSE_CARES=on ninja yass yass_benchmark yass_test - name: Populate depedencies (libgcc-i686) if: ${{ matrix.arch == 'i686' }} diff --git a/yass/CMakeLists.txt b/yass/CMakeLists.txt index a9bfbe861c..c2804fc25a 100644 --- a/yass/CMakeLists.txt +++ b/yass/CMakeLists.txt @@ -142,7 +142,7 @@ option(OFFICIAL_BUILD "Build with official build" OFF) if (OFFICIAL_BUILD) list(APPEND YASS_APP_FEATURES "official-build") - add_definitions(-DOFFICIAL_BUILD) + add_compile_definitions(-DOFFICIAL_BUILD) endif() if(MSVC) @@ -559,7 +559,7 @@ cmake_dependent_option( if (FLATPAK_BUILD) list(APPEND YASS_APP_FEATURES "flatpak-build") - add_definitions(-DFLATPAK_BUILD) + add_compile_definitions(-DFLATPAK_BUILD) endif() cmake_dependent_option( @@ -568,7 +568,7 @@ cmake_dependent_option( if (FLATHUB_BUILD) list(APPEND YASS_APP_FEATURES "flathub-build") - add_definitions(-DFLATHUB_BUILD) + add_compile_definitions(-DFLATHUB_BUILD) endif() # Dynamic users are supported from version 235 @@ -652,7 +652,33 @@ endif() if (ENABLE_ASSERTIONS) message(STATUS "Enabled Assertions") list(APPEND YASS_APP_FEATURES "assertions") - add_definitions(-DDCHECK_ALWAYS_ON=1) + add_compile_definitions(-DDCHECK_ALWAYS_ON=1) + + # MSVC doesn't like _DEBUG on release builds. See PR 4379. + if(NOT MSVC) + add_compile_definitions(_DEBUG) + endif() + # On non-Debug builds cmake automatically defines NDEBUG, so we + # explicitly undefine it: + if(NOT upper_CMAKE_BUILD_TYPE STREQUAL "DEBUG") + add_compile_options($<$,$>:-UNDEBUG>) + if (MSVC) + # Also remove /D NDEBUG to avoid MSVC warnings about conflicting defines. + foreach(flags_var_to_scrub + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_C_FLAGS_MINSIZEREL) + string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " + "${flags_var_to_scrub}" "${${flags_var_to_scrub}}") + endforeach() + endif() + endif() +else() + ## Optimization flags + add_compile_options($<$,$>:-DNDEBUG>) endif() if (ENABLE_LTO AND IS_RELEASE_BUILD) @@ -896,7 +922,7 @@ if(MSAN) add_compile_options(-fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer) add_link_options(-fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer) endif() - add_definitions(-DMEMORY_SANITIZER) + add_compile_definitions(-DMEMORY_SANITIZER) list(APPEND YASS_APP_FEATURES "msan") endif() @@ -914,9 +940,9 @@ if(ASAN) add_compile_options(-fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer) add_link_options(-fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer) endif() - add_definitions(-DADDRESS_SANITIZER) + add_compile_definitions(-DADDRESS_SANITIZER) if (NOT APPLE AND USE_LIBCXX) - add_definitions(-D_LIBCPP_INSTRUMENTED_WITH_ASAN) + add_compile_definitions(-D_LIBCPP_INSTRUMENTED_WITH_ASAN) endif() list(APPEND YASS_APP_FEATURES "asan") endif() @@ -949,7 +975,7 @@ if(TSAN) add_compile_options(-fsanitize=thread) add_link_options(-fsanitize=thread) endif() - add_definitions(-DTHREAD_SANITIZER) + add_compile_definitions(-DTHREAD_SANITIZER) list(APPEND YASS_APP_FEATURES "tsan") endif() @@ -967,7 +993,7 @@ if(UBSAN) add_compile_options(-fsanitize=undefined) add_link_options(-fsanitize=undefined) endif() - add_definitions(-DUNDEFINED_SANITIZER) + add_compile_definitions(-DUNDEFINED_SANITIZER) list(APPEND YASS_APP_FEATURES "ubsan") endif() @@ -1014,14 +1040,6 @@ if (NOT MSVC) endif() endif() - ## optimization flags - ## TODO Changed in version 3.19: Multiple configurations can be specified for cfgs - ## see https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:CONFIG - add_compile_options( - "$<$:-DNDEBUG>" - "$<$:-DNDEBUG>" - ) - ## can gc eliminate any unused functions and data items if (NOT APPLE) add_compile_options($<$:-fdata-sections>) @@ -1153,7 +1171,6 @@ else() ## Optimization flags add_compile_options($<$,$>:/Zc:inline>) - add_compile_options($<$,$>:/DNDEBUG>) ## Disable LTCG for static libraries because this setting introduces ABI incompatibility between minor compiler versions if (NOT MSVC_CRT_LINKAGE STREQUAL "static" AND NOT COMPILER_CLANG) @@ -1918,7 +1935,7 @@ endif() # ***************************************************************************************** if (USE_LIBCXX) - add_definitions(-DHAVE_LIBCXX) + add_compile_definitions(-DHAVE_LIBCXX) add_subdirectory(third_party/libc++ EXCLUDE_FROM_ALL) link_libraries(cxx ${libcxx_PUBLIC_LIBRARIES}) set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES} ${libcxx_PUBLIC_LIBRARIES}") @@ -1928,9 +1945,13 @@ if (USE_LIBCXX) list(APPEND YASS_APP_FEATURES "msvcrt100") endif() if (MINGW_WORKAROUND) + if (USE_TCMALLOC) + # see #1127 mingw emutls patch crashes in 32-bit windows + message(FATAL_ERROR "mingw emutls workaround doesn't work with tcmalloc") + endif() list(APPEND YASS_APP_FEATURES "mingw atexit workaround") endif() -elseif(NOT MSVC) +elseif(LINUX AND ENABLE_ASSERTIONS) # Enable assertions on safety checks, also in libstdc++ # # In case the C++ standard library implementation used is libstdc++, then @@ -1938,7 +1959,7 @@ elseif(NOT MSVC) # # Enable libstdc++ hardening lightweight assertions. Those have a low # performance penalty but are considered a bare minimum for security. - add_definitions(-D_GLIBCXX_ASSERTIONS=1) + add_compile_definitions(-D_GLIBCXX_ASSERTIONS=1) endif() # ***************************************************************************************** @@ -1966,7 +1987,7 @@ int main() { } " HAVE_FLOCK) if (HAVE_FLOCK) - add_definitions(-DHAVE_FLOCK) + add_compile_definitions(-DHAVE_FLOCK) endif() if (NOT WIN32 AND NOT APPLE) @@ -1978,16 +1999,16 @@ if (NOT WIN32 AND NOT APPLE) check_symbol_exists(mallinfo2 malloc.h HAVE_MALLINFO2) endif() if (HAVE_PIPE2) - add_definitions(-DHAVE_PIPE2) + add_compile_definitions(-DHAVE_PIPE2) endif() if (HAVE_DUP3) - add_definitions(-DHAVE_DUP3) + add_compile_definitions(-DHAVE_DUP3) endif() if (HAVE_MALLINFO) - add_definitions(-DHAVE_MALLINFO) + add_compile_definitions(-DHAVE_MALLINFO) endif() if (HAVE_MALLINFO2) - add_definitions(-DHAVE_MALLINFO2) + add_compile_definitions(-DHAVE_MALLINFO2) endif() if (MINGW) # see https://github.com/mingw-w64/mingw-w64/blob/master/mingw-w64-headers/crt/_mingw.h.in#L215 @@ -2366,9 +2387,9 @@ include_directories(third_party/abseil-cpp) # force win32 thread model for libc++ usage if (MINGW AND USE_LIBCXX) # force non-inline emulated-tls - add_definitions(-DABSL_CONSUME_DLL) + add_compile_definitions(-DABSL_CONSUME_DLL) # force c++11 thread model - add_definitions(-DABSL_FORCE_THREAD_IDENTITY_MODE=ABSL_THREAD_IDENTITY_MODE_USE_CPP11) + add_compile_definitions(-DABSL_FORCE_THREAD_IDENTITY_MODE=ABSL_THREAD_IDENTITY_MODE_USE_CPP11) endif() if (ABSL_BUILD_TESTING) set(ABSL_USE_EXTERNAL_GOOGLETEST "ON" CACHE BOOL "") @@ -4056,10 +4077,6 @@ add_library(yass_core STATIC src/config/config_impl_windows.hpp src/core/logging.cpp src/core/logging.hpp - src/core/check_op.cpp - src/core/check_op.hpp - src/core/check.cpp - src/core/check.hpp src/core/process_utils.hpp src/core/process_utils.cpp src/crypto/crypter_export.cpp @@ -4072,26 +4089,16 @@ add_library(yass_core STATIC src/core/safe_strerror.hpp src/core/debug.cpp src/core/debug.hpp - src/core/rand_util.cpp - src/core/rand_util.hpp src/core/scoped_clear_last_error_win.cpp - src/core/ref_counted.cpp - src/core/ref_counted.hpp - src/core/thread_collision_warner.hpp - src/core/thread_collision_warner.cpp - src/core/atomic_ref_count.hpp ) if (WIN32) - target_sources(yass_core PRIVATE src/core/rand_util_win.cpp) target_sources(yass_core PRIVATE src/core/utils_win.cpp) elseif (APPLE) target_sources(yass_core PRIVATE src/config/config_impl_apple.hpp) target_sources(yass_core PRIVATE src/config/config_impl_apple.mm) - target_sources(yass_core PRIVATE src/core/rand_util_posix.cpp) target_sources(yass_core PRIVATE src/core/utils_mac.mm) else() - target_sources(yass_core PRIVATE src/core/rand_util_posix.cpp) target_sources(yass_core PRIVATE src/core/utils_linux.cpp) target_sources(yass_core PRIVATE src/core/utils_freebsd.cpp) endif() @@ -4119,6 +4126,7 @@ if (APPLE) endif() target_include_directories(yass_core PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googleurl-override/polyfills ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googleurl-override ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googleurl/polyfills ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googleurl diff --git a/yass/src/cli/cli_connection.cpp b/yass/src/cli/cli_connection.cpp index d040d7f348..58192710a5 100644 --- a/yass/src/cli/cli_connection.cpp +++ b/yass/src/cli/cli_connection.cpp @@ -5,10 +5,10 @@ #include #include +#include #include #include "config/config.hpp" -#include "core/rand_util.hpp" #include "core/utils.hpp" #include "net/asio.hpp" #include "net/base64.hpp" @@ -2246,9 +2246,9 @@ void CliConnection::connected() { // originated from naive_proxy_delegate.go;func ServeHTTP if (padding_support_) { // Sends client-side padding header regardless of server support - std::string padding(RandInt(16, 32), '~'); + std::string padding(gurl_base::RandInt(16, 32), '~'); InitializeNonindexCodes(); - FillNonindexHeaderValue(RandUint64(), &padding[0], padding.size()); + FillNonindexHeaderValue(gurl_base::RandUint64(), &padding[0], padding.size()); headers.emplace_back("padding"s, padding); } int submit_result = adapter_->SubmitRequest(GenerateHeaders(headers), std::move(data_frame), false, nullptr); diff --git a/yass/src/cli/cli_connection.hpp b/yass/src/cli/cli_connection.hpp index ca6c81fc3e..3d326a6d0e 100644 --- a/yass/src/cli/cli_connection.hpp +++ b/yass/src/cli/cli_connection.hpp @@ -6,8 +6,6 @@ #include "cli/cli_connection_stats.hpp" #include "core/logging.hpp" -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "net/channel.hpp" #include "net/cipher.hpp" #include "net/connection.hpp" @@ -26,6 +24,8 @@ #include #include #include +#include +#include #include #ifdef HAVE_QUICHE @@ -85,7 +85,7 @@ class DataFrameSource : public http2::adapter::DataFrameSource { /// The ultimate service class to deliever the network traffic to the remote /// endpoint -class CliConnection : public RefCountedThreadSafe, +class CliConnection : public gurl_base::RefCountedThreadSafe, #ifdef HAVE_QUICHE public http2::adapter::Http2VisitorInterface, #endif // HAVE_QUICHE diff --git a/yass/src/config/config_test.cpp b/yass/src/config/config_test.cpp index e22e58d82f..27b72d13c6 100644 --- a/yass/src/config/config_test.cpp +++ b/yass/src/config/config_test.cpp @@ -6,11 +6,11 @@ #include #include +#include #include #include #include "config/config_impl.hpp" #include "core/process_utils.hpp" -#include "core/rand_util.hpp" #include "core/utils_fs.hpp" using namespace yass; @@ -25,7 +25,7 @@ ABSL_FLAG(std::string, test_string, "", "Test string value"); class ConfigTest : public ::testing::Test { public: void SetUp() override { - key_prefix_ = absl::StrCat("pid_", GetPID(), "_run_", RandUint64()); + key_prefix_ = absl::StrCat("pid_", GetPID(), "_run_", gurl_base::RandUint64()); #if !(defined(_WIN32) || defined(__APPLE__)) original_configfile_ = config::g_configfile; const char* tmpdir = getenv("TMPDIR"); diff --git a/yass/src/config/config_version.cpp b/yass/src/config/config_version.cpp index ea4822ed78..36d8f4dd3b 100644 --- a/yass/src/config/config_version.cpp +++ b/yass/src/config/config_version.cpp @@ -82,6 +82,9 @@ static void ParseConfigFileOption(int argc, const char** argv) { #endif #ifndef NDEBUG std::cout << "Debug build (NDEBUG not #defined)" << std::endl; +#endif +#ifdef DCHECK_ALWAYS_ON + std::cout << "Assertions build (DCHECK_ALWAYS_ON #defined)" << std::endl; #endif argv[pos] = ""; pos += 1; @@ -100,8 +103,11 @@ static void ParseConfigFileOption(int argc, const char** argv) { #ifdef HAVE_MIMALLOC std::cerr << "MIMALLOC: " << mi_version() << std::endl; #endif +#ifdef DCHECK_ALWAYS_ON + std::cerr << "Assertions build (DCHECK_ALWAYS_ON #defined)" << std::endl; +#endif #ifndef NDEBUG - std::cerr << "Debug build (NDEBUG not #defined)\n" << std::endl; + std::cerr << "Debug build (NDEBUG not #defined)" << std::endl; #endif } @@ -130,8 +136,11 @@ void ReadConfigFileAndArguments(int argc, const char** argv) { #ifdef HAVE_MIMALLOC LOG(WARNING) << "MIMALLOC: " << mi_version(); #endif +#ifdef DCHECK_ALWAYS_ON + LOG(WARNING) << "Assertions build (DCHECK_ALWAYS_ON #defined)"; +#endif #ifndef NDEBUG - LOG(WARNING) << "Debug build (NDEBUG not #defined)\n"; + LOG(WARNING) << "Debug build (NDEBUG not #defined)"; #endif } diff --git a/yass/src/core/debug.cpp b/yass/src/core/debug.cpp index c5e0b6b217..df4f241d4b 100644 --- a/yass/src/core/debug.cpp +++ b/yass/src/core/debug.cpp @@ -2,9 +2,9 @@ /* Copyright (c) 2022-2024 Chilledheart */ #include "core/debug.hpp" -#include "core/check_op.hpp" #include +#include #include #include #include diff --git a/yass/src/core/logging.cpp b/yass/src/core/logging.cpp index e50573b317..0de8474ce7 100644 --- a/yass/src/core/logging.cpp +++ b/yass/src/core/logging.cpp @@ -209,16 +209,6 @@ typedef FILE* FileHandle; #include #include -#if !defined(NDEBUG) || defined(_DEBUG) -#define DEFAULT_LOGBUFLEVEL -1 -#define DEFAULT_VERBOSE_LEVEL 1 -#define DEFAULT_LOGSTDERRTHRESHOLD LOGGING_WARNING -#else -#define DEFAULT_LOGBUFLEVEL 0 -#define DEFAULT_VERBOSE_LEVEL 0 -#define DEFAULT_LOGSTDERRTHRESHOLD LOGGING_ERROR -#endif - namespace { // simple init once flag std::atomic g_log_init; @@ -302,7 +292,7 @@ ABSL_FLAG(bool, // when they run a program without having to look in another file. ABSL_FLAG(int32_t, stderrthreshold, - DEFAULT_LOGSTDERRTHRESHOLD, + gurl_base::logging::LOGGING_ERROR, "log messages at or above this level are copied to stderr in " "addition to logfiles. This flag obsoletes --alsologtostderr."); ABSL_FLAG(int32_t, @@ -312,7 +302,7 @@ ABSL_FLAG(int32_t, "actually get logged anywhere"); ABSL_FLAG(int32_t, logbuflevel, - DEFAULT_LOGBUFLEVEL, + 0, "Buffer log messages logged at this level or lower" " (-1 means don't buffer; 0 means buffer INFO only;" " ...)"); @@ -355,7 +345,7 @@ ABSL_FLAG(bool, stop_logging_if_full_disk, false, "Stop attempting to log to dis ABSL_FLAG(std::string, log_backtrace_at, "", "Emit a backtrace when logging at file:linenum."); -ABSL_FLAG(int32_t, v, DEFAULT_VERBOSE_LEVEL, "verboselevel"); +ABSL_FLAG(int32_t, v, 0, "verboselevel"); ABSL_FLAG(std::string, vmodule, @@ -368,7 +358,8 @@ ABSL_FLAG(std::string, ABSL_FLAG(bool, symbolize_stacktrace, true, "Symbolize the stack trace in the tombstone"); -namespace yass { +namespace gurl_base { +namespace logging { // TODO(hamaji): consider windows #define PATH_SEPARATOR '/' @@ -2996,7 +2987,7 @@ std::string SystemErrorCodeToString(SystemErrorCode error_code) { DWORD len = FormatMessageA(flags, nullptr, error_code, 0, msgbuf, sizeof(msgbuf) / sizeof(msgbuf[0]), nullptr); if (len) { // Messages returned by system end with line breaks. - return gurl_base::CollapseWhitespaceASCII(msgbuf, true) + absl::StrFormat(" (0x%lX)", error_code); + return CollapseWhitespaceASCII(msgbuf, true) + absl::StrFormat(" (0x%lX)", error_code); } return absl::StrFormat("Error (0x%lX) while retrieving error. (0x%lX)", GetLastError(), error_code); #elif BUILDFLAG(IS_POSIX) @@ -3057,4 +3048,5 @@ void RawLog(int level, const char* message) { BreakDebuggerAsyncSafe(); } -} // namespace yass +} // namespace logging +} // namespace gurl_base diff --git a/yass/src/core/logging.hpp b/yass/src/core/logging.hpp index e489d520d5..7b7593b513 100644 --- a/yass/src/core/logging.hpp +++ b/yass/src/core/logging.hpp @@ -3,829 +3,8 @@ #ifndef H_CORE_LOGGING #define H_CORE_LOGGING -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "third_party/googleurl-override/polyfills/base/check.h" +#include "third_party/googleurl-override/polyfills/base/check_op.h" +#include "third_party/googleurl-override/polyfills/base/logging.h" -#include -#include -#include -#include -#include - -#if BUILDFLAG(IS_WIN) -#include -#endif - -// ScopedClearLastError stores and resets the value of thread local error codes -// (errno, GetLastError()), and restores them in the destructor. This is useful -// to avoid side effects on these values in instrumentation functions that -// interact with the OS. - -// Common implementation of ScopedClearLastError for all platforms. Use -// ScopedClearLastError instead. -class ScopedClearLastErrorBase { - public: - ScopedClearLastErrorBase() : last_errno_(errno) { errno = 0; } - ScopedClearLastErrorBase(const ScopedClearLastErrorBase&) = delete; - ScopedClearLastErrorBase& operator=(const ScopedClearLastErrorBase&) = delete; - ~ScopedClearLastErrorBase() { errno = last_errno_; } - - private: - const int last_errno_; -}; - -#if BUILDFLAG(IS_WIN) - -// Windows specific implementation of ScopedClearLastError. -class ScopedClearLastError : public ScopedClearLastErrorBase { - public: - ScopedClearLastError(); - ScopedClearLastError(const ScopedClearLastError&) = delete; - ScopedClearLastError& operator=(const ScopedClearLastError&) = delete; - ~ScopedClearLastError(); - - private: - const unsigned long last_system_error_; -}; - -#elif BUILDFLAG(IS_POSIX) - -using ScopedClearLastError = ScopedClearLastErrorBase; - -#endif // BUILDFLAG(IS_WIN) - -using LogSeverity = int; -constexpr LogSeverity LOGGING_VERBOSE = -1; // This is level 1 verbosity -// Note: the log severities are used to index into the array of names, -// see log_severity_names. -constexpr LogSeverity LOGGING_INFO = 0; -constexpr LogSeverity LOGGING_WARNING = 1; -constexpr LogSeverity LOGGING_ERROR = 2; -constexpr LogSeverity LOGGING_FATAL = 3; -constexpr LogSeverity LOGGING_NUM_SEVERITIES = 4; - -// LOGGING_DFATAL is LOGGING_FATAL in DCHECK-enabled builds, ERROR in normal -// mode. -#if DCHECK_IS_ON() -constexpr LogSeverity LOGGING_DFATAL = LOGGING_FATAL; -#else -constexpr LogSeverity LOGGING_DFATAL = LOGGING_ERROR; -#endif - -// This block duplicates the above entries to facilitate incremental conversion -// from LOG_FOO to LOGGING_FOO. -// TODO(thestig): Convert existing users to LOGGING_FOO and remove this block. -constexpr LogSeverity LOG_VERBOSE = LOGGING_VERBOSE; -constexpr LogSeverity LOG_INFO = LOGGING_INFO; -constexpr LogSeverity LOG_WARNING = LOGGING_WARNING; -constexpr LogSeverity LOG_ERROR = LOGGING_ERROR; -constexpr LogSeverity LOG_FATAL = LOGGING_FATAL; -constexpr LogSeverity LOG_DFATAL = LOGGING_DFATAL; - -// A few definitions of macros that don't generate much code. These are used -// by LOG() and LOG_IF, etc. Since these are used all over our code, it's -// better to have compact code for these operations. -#define COMPACT_LOGGING_EX_INFO(ClassName, ...) ::yass::ClassName(__FILE__, __LINE__, LOGGING_INFO, ##__VA_ARGS__) -#define COMPACT_LOGGING_EX_WARNING(ClassName, ...) ::yass::ClassName(__FILE__, __LINE__, LOGGING_WARNING, ##__VA_ARGS__) -#define COMPACT_LOGGING_EX_ERROR(ClassName, ...) ::yass::ClassName(__FILE__, __LINE__, LOGGING_ERROR, ##__VA_ARGS__) -#define COMPACT_LOGGING_EX_FATAL(ClassName, ...) ::yass::ClassName(__FILE__, __LINE__, LOGGING_FATAL, ##__VA_ARGS__) -#define COMPACT_LOGGING_EX_DFATAL(ClassName, ...) ::yass::ClassName(__FILE__, __LINE__, LOGGING_DFATAL, ##__VA_ARGS__) -#define COMPACT_LOGGING_EX_DCHECK(ClassName, ...) ::yass::ClassName(__FILE__, __LINE__, LOGGING_DCHECK, ##__VA_ARGS__) - -#define COMPACT_LOGGING_INFO COMPACT_LOGGING_EX_INFO(LogMessage) -#define COMPACT_LOGGING_WARNING COMPACT_LOGGING_EX_WARNING(LogMessage) -#define COMPACT_LOGGING_ERROR COMPACT_LOGGING_EX_ERROR(LogMessage) -#define COMPACT_LOGGING_FATAL COMPACT_LOGGING_EX_FATAL(LogMessage) -#define COMPACT_LOGGING_DFATAL COMPACT_LOGGING_EX_DFATAL(LogMessage) -#define COMPACT_LOGGING_DCHECK COMPACT_LOGGING_EX_DCHECK(LogMessage) - -#if BUILDFLAG(IS_WIN) -// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets -// substituted with 0, and it expands to COMPACT_LOGGING_0. To allow us -// to keep using this syntax, we define this macro to do the same thing -// as COMPACT_LOGGING_ERROR, and also define ERROR the same way that -// the Windows SDK does for consistency. -#define ERROR 0 -#define COMPACT_LOGGING_EX_0(ClassName, ...) COMPACT_LOGGING_EX_ERROR(ClassName, ##__VA_ARGS__) -#define COMPACT_LOGGING_0 COMPACT_LOGGING_ERROR -// Needed for LOG_IS_ON(ERROR). -constexpr LogSeverity LOGGING_0 = LOGGING_ERROR; -#endif - -// As special cases, we can assume that LOG_IS_ON(FATAL) always holds. Also, -// LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will -// always fire if they fail. -#define LOG_IS_ON(severity) (::yass::ShouldCreateLogMessage(LOGGING_##severity)) - -#if defined(__GNUC__) -// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site. -// (Normally) the first time every VLOG_IS_ON(n) site is hit, -// we determine what variable will dynamically control logging at this site: -// it's either FLAGS_v or an appropriate internal variable -// matching the current source file that represents results of -// parsing of --vmodule flag and/or SetVLOGLevel calls. -#define VLOG_IS_ON(verboselevel) \ - __extension__({ \ - static absl::Flag* vlocal__ = NULL; \ - int32_t verbose_level__ = (verboselevel); \ - (vlocal__ == NULL ? ::yass::InitVLOG3__(&vlocal__, &FLAGS_v, __FILE__, verbose_level__) \ - : absl::GetFlag(*vlocal__) >= verbose_level__); \ - }) -#else -// GNU extensions not available, so we do not support --vmodule. -// Dynamic value of FLAGS_v always controls the logging level. -#define VLOG_IS_ON(verboselevel) (absl::GetFlag(FLAGS_v) >= (verboselevel)) -#endif - -// Helper macro which avoids evaluating the arguments to a stream if -// the condition doesn't hold. Condition is evaluated once and only once. -#define LAZY_STREAM(stream, condition) !(condition) ? (void)0 : ::yass::LogMessageVoidify() & (stream) - -// We use the preprocessor's merging operator, "##", so that, e.g., -// LOG(INFO) becomes the token COMPACT_LOGGING_INFO. There's some funny -// subtle difference between ostream member streaming functions (e.g., -// ostream::operator<<(int) and ostream non-member streaming functions -// (e.g., ::operator<<(ostream&, string&): it turns out that it's -// impossible to stream something like a string directly to an unnamed -// ostream. We employ a neat hack by calling the stream() member -// function of LogMessage which seems to avoid the problem. -#define LOG_STREAM(severity) COMPACT_LOGGING_##severity.stream() - -#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity)) -#define LOG_IF(severity, condition) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) - -// The VLOG macros log with negative verbosities. -#define VLOG_STREAM(verbose_level) ::yass::LogMessage(__FILE__, __LINE__, -(verbose_level)).stream() - -#define VLOG(verbose_level) LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) - -#define VLOG_IF(verbose_level, condition) \ - LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level) && (condition)) - -#if BUILDFLAG(IS_WIN) -#define VPLOG_STREAM(verbose_level) \ - ::yass::Win32ErrorLogMessage(__FILE__, __LINE__, -(verbose_level), ::yass::GetLastSystemErrorCode()).stream() -#elif BUILDFLAG(IS_POSIX) -#define VPLOG_STREAM(verbose_level) \ - ::yass::ErrnoLogMessage(__FILE__, __LINE__, -(verbose_level), ::yass::GetLastSystemErrorCode()).stream() -#endif - -#define VPLOG(verbose_level) LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) - -#define VPLOG_IF(verbose_level, condition) \ - LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level) && (condition)) - -// TODO(akalin): Add more VLOG variants, e.g. VPLOG. - -#define LOG_ASSERT(condition) LOG_IF(FATAL, !(ABSL_PREDICT_TRUE(condition))) << "Assert failed: " #condition ". " - -#if BUILDFLAG(IS_WIN) -#define PLOG_STREAM(severity) \ - COMPACT_LOGGING_EX_##severity(Win32ErrorLogMessage, ::yass::GetLastSystemErrorCode()).stream() -#elif BUILDFLAG(IS_POSIX) -#define PLOG_STREAM(severity) COMPACT_LOGGING_EX_##severity(ErrnoLogMessage, ::yass::GetLastSystemErrorCode()).stream() -#endif - -#define PLOG(severity) LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity)) - -#define PLOG_IF(severity, condition) LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) - -namespace yass { -extern std::ostream* g_swallow_stream; -} // namespace yass - -// Note that g_swallow_stream is used instead of an arbitrary LOG() stream to -// avoid the creation of an object with a non-trivial destructor (LogMessage). -// On MSVC x86 (checked on 2015 Update 3), this causes a few additional -// pointless instructions to be emitted even at full optimization level, even -// though the : arm of the ternary operator is clearly never executed. Using a -// simpler object to be &'d with Voidify() avoids these extra instructions. -// Using a simpler POD object with a templated operator<< also works to avoid -// these instructions. However, this causes warnings on statically defined -// implementations of operator<<(std::ostream, ...) in some .cc files, because -// they become defined-but-unreferenced functions. A reinterpret_cast of 0 to an -// ostream* also is not suitable, because some compilers warn of undefined -// behavior. -#define EAT_STREAM_PARAMETERS true ? (void)0 : ::yass::LogMessageVoidify() & (*::yass::g_swallow_stream) - -// Definitions for DLOG et al. - -#if DCHECK_IS_ON() - -#define DLOG_IS_ON(severity) LOG_IS_ON(severity) -#define DLOG_IF(severity, condition) LOG_IF(severity, condition) -#define DLOG_ASSERT(condition) LOG_ASSERT(condition) -#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition) -#define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition) -#define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition) - -#else // !DCHECK_IS_ON() - -// If !DCHECK_IS_ON(), we want to avoid emitting any references to |condition| -// (which may reference a variable defined only if DCHECK_IS_ON()). -// Contrast this with DCHECK et al., which has different behavior. - -#define DLOG_IS_ON(severity) false -#define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS -#define DLOG_ASSERT(condition) EAT_STREAM_PARAMETERS -#define DPLOG_IF(severity, condition) EAT_STREAM_PARAMETERS -#define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS -#define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS - -#endif // DCHECK_IS_ON() - -#define DLOG(severity) LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity)) - -#define DPLOG(severity) LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity)) - -#define DVLOG(verboselevel) DVLOG_IF(verboselevel, true) - -#define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, true) - -// Definitions for DCHECK et al. - -constexpr LogSeverity LOGGING_DCHECK = LOGGING_FATAL; - -// Redefine the standard assert to use our nice log files -#undef assert -#define assert(x) DLOG_ASSERT(x) - -ABSL_DECLARE_FLAG(bool, tick_counts_in_logfile_name); -ABSL_DECLARE_FLAG(bool, logtostderr); -ABSL_DECLARE_FLAG(bool, alsologtostderr); -ABSL_DECLARE_FLAG(bool, colorlogtostderr); -#if BUILDFLAG(IS_POSIX) -ABSL_DECLARE_FLAG(bool, drop_log_memory); -#endif - -ABSL_DECLARE_FLAG(int32_t, stderrthreshold); -ABSL_DECLARE_FLAG(int32_t, minloglevel); -ABSL_DECLARE_FLAG(int32_t, logbuflevel); -ABSL_DECLARE_FLAG(int32_t, logbufsecs); - -ABSL_DECLARE_FLAG(int32_t, logfile_mode); -ABSL_DECLARE_FLAG(std::string, log_dir); -ABSL_DECLARE_FLAG(std::string, log_link); -ABSL_DECLARE_FLAG(int32_t, max_log_size); -ABSL_DECLARE_FLAG(bool, stop_logging_if_full_disk); -ABSL_DECLARE_FLAG(std::string, log_backtrace_at); - -ABSL_DECLARE_FLAG(int32_t, v); -ABSL_DECLARE_FLAG(std::string, vmodule); - -ABSL_DECLARE_FLAG(bool, log_process_id); -ABSL_DECLARE_FLAG(bool, log_thread_id); -ABSL_DECLARE_FLAG(bool, log_timestamp); -ABSL_DECLARE_FLAG(bool, log_tickcount); -ABSL_DECLARE_FLAG(std::string, log_prefix); - -namespace yass { - -// Set VLOG(_IS_ON) level for module_pattern to log_level. -// This lets us dynamically control what is normally set by the --vmodule flag. -// Returns the level that previously applied to module_pattern. -// NOTE: To change the log level for VLOG(_IS_ON) sites -// that have already executed after/during InitGoogleLogging, -// one needs to supply the exact --vmodule pattern that applied to them. -// (If no --vmodule pattern applied to them -// the value of FLAGS_v will continue to control them.) -extern int SetVLOGLevel(const char* module_pattern, int log_level); - -// Various declarations needed for VLOG_IS_ON above: ========================= - -// Helper routine which determines the logging info for a particalur VLOG site. -// site_flag is the address of the site-local pointer to the controlling -// verbosity level -// site_default is the default to use for *site_flag -// fname is the current source file name -// verbose_level is the argument to VLOG_IS_ON -// We will return the return value for VLOG_IS_ON -// and if possible set *site_flag appropriately. -extern bool InitVLOG3__(absl::Flag** site_flag, - absl::Flag* site_default, - const char* fname, - int32_t verbose_level); - -// Enable/Disable old log cleaner. -void EnableLogCleaner(int overdue_days); -void DisableLogCleaner(); -void SetApplicationFingerprint(const std::string& fingerprint); - -class LogSink; // defined below - -// If a non-NULL sink pointer is given, we push this message to that sink. -// For LOG_TO_SINK we then do normal LOG(severity) logging as well. -// This is useful for capturing messages and passing/storing them -// somewhere more specific than the global log of the process. -// Argument types: -// LogSink* sink; -// LogSeverity severity; -// The cast is to disambiguate NULL arguments. -#define LOG_TO_SINK(sink, severity) \ - LogMessage(__FILE__, __LINE__, LOGGING_##severity, static_cast(sink), true).stream() -#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \ - LogMessage(__FILE__, __LINE__, LOGGING_##severity, static_cast(sink), false).stream() - -#if defined(_SANITIZE_THREAD) -#define _IFDEF_THREAD_SANITIZER(X) X -#else -#define _IFDEF_THREAD_SANITIZER(X) -#endif - -struct CrashReason; - -// LogMessage::LogStream is a std::ostream backed by this streambuf. -// This class ignores overflow and leaves two bytes at the end of the -// buffer to allow for a '\n' and '\0'. -class LogStreamBuf : public std::streambuf { - public: - // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\0'. - LogStreamBuf(char* buf, int len) { setp(buf, buf + len - 2); } - - // This effectively ignores overflow. - int_type overflow(int_type ch) { return ch; } - - // Legacy public ostrstream method. - size_t pcount() const { return pptr() - pbase(); } - char* pbase() const { return std::streambuf::pbase(); } -}; - -// -// This class more or less represents a particular log message. You -// create an instance of LogMessage and then stream stuff to it. -// When you finish streaming to it, ~LogMessage is called and the -// full message gets streamed to the appropriate destination. -// -// You shouldn't actually use LogMessage's constructor to log things, -// though. You should use the LOG() macro (and variants thereof) -// above. -class LogMessage { - public: - enum { - // Passing kNoLogPrefix for the line number disables the - // log-message prefix. Useful for using the LogMessage - // infrastructure as a printing utility. See also the --log_prefix - // flag for controlling the log-message prefix on an - // application-wide basis. - kNoLogPrefix = -1 - }; - - // LogStream inherit from non-DLL-exported class (std::ostrstream) - // and VC++ produces a warning for this situation. - // However, MSDN says "C4275 can be ignored in Microsoft Visual C++ - // 2005 if you are deriving from a type in the Standard C++ Library" - // http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx - // Let's just ignore the warning. - class LogStream : public std::ostream { - public: - // 'this' : used in base member initializer - LogStream(char* buf, int len, uint64_t ctr) : std::ostream(NULL), streambuf_(buf, len), ctr_(ctr), self_(this) { - rdbuf(&streambuf_); - } - - uint64_t ctr() const { return ctr_; } - void set_ctr(uint64_t ctr) { ctr_ = ctr; } - LogStream* self() const { return self_; } - - // Legacy std::streambuf methods. - size_t pcount() const { return streambuf_.pcount(); } - char* pbase() const { return streambuf_.pbase(); } - char* str() const { return pbase(); } - - private: - LogStream(const LogStream&); - LogStream& operator=(const LogStream&); - LogStreamBuf streambuf_; - uint64_t ctr_; // Counter hack (for the LOG_EVERY_X() macro) - LogStream* self_; // Consistency check hack - }; - - public: - // icc 8 requires this typedef to avoid an internal compiler error. - typedef void (LogMessage::*SendMethod)(); - - LogMessage(const char* file, int line, LogSeverity severity, uint64_t ctr, SendMethod send_method); - - // Used for LOG(severity). - LogMessage(const char* file, int line, LogSeverity severity); - - // Used for CHECK(). Implied severity = LOGGING_FATAL. - LogMessage(const char* file, int line, const char* condition); - LogMessage(const LogMessage&) = delete; - LogMessage& operator=(const LogMessage&) = delete; - virtual ~LogMessage(); - - std::ostream& stream(); - - LogSeverity severity() { return severity_; } - - // Two special constructors that generate reduced amounts of code at - // LOG call sites for common cases. - - // Used for LOG(INFO): Implied are: - // severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog. - // - // Using this constructor instead of the more complex constructor above - // saves 19 bytes per call site. - LogMessage(const char* file, int line); - - // Constructor to log this message to a specified sink (if not NULL). - // Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if - // also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise. - LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink, bool also_send_to_log); - - // Constructor where we also give a vector pointer - // for storing the messages (if the pointer is not NULL). - // Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog. - LogMessage(const char* file, int line, LogSeverity severity, std::vector* outvec); - - // Constructor where we also give a string pointer for storing the - // message (if the pointer is not NULL). Implied are: ctr = 0, - // send_method = &LogMessage::WriteToStringAndLog. - LogMessage(const char* file, int line, LogSeverity severity, std::string* message); - - // Flush a buffered message to the sink set in the constructor. Always - // called by the destructor, it may also be called from elsewhere if - // needed. Only the first call is actioned; any later ones are ignored. - void Flush(); - - // An arbitrary limit on the length of a single log message. This - // is so that streaming can be done more efficiently. - static const size_t kMaxLogMessageLen; - - // Theses should not be called directly outside of logging.*, - // only passed as SendMethod arguments to other LogMessage methods: - void SendToLog(); // Actually dispatch to the logs - - // Call abort() or similar to perform LOG(FATAL) crash. - [[noreturn]] static void Fail(); - - int preserved_errno() const; - - // Must be called without the log_mutex held. (L < log_mutex) - static int64_t num_messages(int severity); - - struct LogMessageData; - - private: - // Fully internal SendMethod cases: - void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs - void SendToSink(); // Send to sink if provided, do nothing otherwise. - - // Write to string if provided and dispatch to the logs. - void WriteToStringAndLog(); - - void SaveOrSendToLog(); // Save to stringvec if provided, else to logs - - void Init(const char* file, int line, LogSeverity severity, void (LogMessage::*send_method)()); - - // Used to fill in crash information during LOG(FATAL) failures. - void RecordCrashReason(CrashReason* reason); - - // Counts of messages sent at each priority: - static int64_t num_messages_[LOGGING_NUM_SEVERITIES]; // under log_mutex - - // We keep the data in a separate struct so that each instance of - // LogMessage uses less stack space. - LogMessageData* allocated_; - LogMessageData* data_; - - friend class LogDestination; - - const LogSeverity severity_; - - // This is useful since the LogMessage class uses a lot of Win32 calls - // that will lose the value of GLE and the code that called the log function - // will have lost the thread error value when the log call returns. - ScopedClearLastError last_error_; -}; - -// This class happens to be thread-hostile because all instances share -// a single data buffer, but since it can only be created just before -// the process dies, we don't worry so much. -class LogMessageFatal : public LogMessage { - public: - LogMessageFatal(const char* file, int line); - [[noreturn]] ~LogMessageFatal(); -}; - -// A non-macro interface to the log facility; (useful -// when the logging level is not a compile-time constant). -inline void LogAtLevel(int const severity, std::string const& msg) { - LogMessage(__FILE__, __LINE__, severity).stream() << msg; -} - -// A macro alternative of LogAtLevel. New code may want to use this -// version since there are two advantages: 1. this version outputs the -// file name and the line number where this macro is put like other -// LOG macros, 2. this macro can be used as C++ stream. -#define LOG_AT_LEVEL(severity) LogMessage(__FILE__, __LINE__, severity).stream() - -// This class is used to explicitly ignore values in the conditional -// logging macros. This avoids compiler warnings like "value computed -// is not used" and "statement has no effect". -class LogMessageVoidify { - public: - LogMessageVoidify() = default; - // This has to be an operator with a precedence lower than << but - // higher than ?: - void operator&(std::ostream&) {} -}; - -#if BUILDFLAG(IS_WIN) -typedef unsigned long SystemErrorCode; -#elif BUILDFLAG(IS_POSIX) -typedef int SystemErrorCode; -#endif - -// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to -// pull in windows.h just for GetLastError() and DWORD. -SystemErrorCode GetLastSystemErrorCode(); -std::string SystemErrorCodeToString(SystemErrorCode error_code); - -#if BUILDFLAG(IS_WIN) -// Appends a formatted system message of the GetLastError() type. -class Win32ErrorLogMessage : public LogMessage { - public: - Win32ErrorLogMessage(const char* file, int line, LogSeverity severity, SystemErrorCode err); - Win32ErrorLogMessage(const Win32ErrorLogMessage&) = delete; - Win32ErrorLogMessage& operator=(const Win32ErrorLogMessage&) = delete; - // Appends the error message before destructing the encapsulated class. - ~Win32ErrorLogMessage() override; - - private: - SystemErrorCode err_; -}; -#elif BUILDFLAG(IS_POSIX) -// Appends a formatted system message of the errno type -class ErrnoLogMessage : public LogMessage { - public: - ErrnoLogMessage(const char* file, int line, LogSeverity severity, SystemErrorCode err); - ErrnoLogMessage(const ErrnoLogMessage&) = delete; - ErrnoLogMessage& operator=(const ErrnoLogMessage&) = delete; - // Appends the error message before destructing the encapsulated class. - ~ErrnoLogMessage() override; - - private: - SystemErrorCode err_; -}; -#endif - -// Flushes all log files that contains messages that are at least of -// the specified severity level. Thread-safe. -void FlushLogFiles(LogSeverity min_severity); - -// Flushes all log files that contains messages that are at least of -// the specified severity level. Thread-hostile because it ignores -// locking -- used for catastrophic failures. -void FlushLogFilesUnsafe(LogSeverity min_severity); - -// -// Set the destination to which a particular severity level of log -// messages is sent. If base_filename is "", it means "don't log this -// severity". Thread-safe. -// -void SetLogDestination(LogSeverity severity, const char* base_filename); - -// -// Set the basename of the symlink to the latest log file at a given -// severity. If symlink_basename is empty, do not make a symlink. If -// you don't call this function, the symlink basename is the -// invocation name of the program. Thread-safe. -// -void SetLogSymlink(LogSeverity severity, const char* symlink_basename); - -// -// Used to send logs to some other kind of destination -// Users should subclass LogSink and override send to do whatever they want. -// Implementations must be thread-safe because a shared instance will -// be called from whichever thread ran the LOG(XXX) line. -class LogSink { - public: - virtual ~LogSink(); - - // Sink's logging logic (message_len is such as to exclude '\n' at the end). - // This method can't use LOG() or CHECK() as logging system mutex(s) are held - // during this call. - virtual void send(LogSeverity severity, - const char* full_filename, - const char* base_filename, - int line, - const char* message, - size_t message_len, - uint64_t /*tick_counts*/) { - send(severity, full_filename, base_filename, line, message, message_len); - } - // This send() signature is obsolete. - // New implementations should define this in terms of - // the above send() method. - virtual void send(LogSeverity severity, - const char* full_filename, - const char* base_filename, - int line, - const char* message, - size_t message_len) = 0; - - // Redefine this to implement waiting for - // the sink's logging logic to complete. - // It will be called after each send() returns, - // but before that LogMessage exits or crashes. - // By default this function does nothing. - // Using this function one can implement complex logic for send() - // that itself involves logging; and do all this w/o causing deadlocks and - // inconsistent rearrangement of log messages. - // E.g. if a LogSink has thread-specific actions, the send() method - // can simply add the message to a queue and wake up another thread that - // handles real logging while itself making some LOG() calls; - // WaitTillSent() can be implemented to wait for that logic to complete. - // See our unittest for an example. - virtual void WaitTillSent(); - - // Returns the normal text output of the log message. - // Can be useful to implement send(). - static std::string ToString(LogSeverity severity, - const char* file, - int line, - const char* message, - size_t message_len, - uint64_t tick_counts); - - // Obsolete - static std::string ToString(LogSeverity severity, - const char* file, - int line, - const char* message, - size_t message_len) { - return ToString(severity, file, line, message, message_len, 0); - } -}; - -// Add or remove a LogSink as a consumer of logging data. Thread-safe. -void AddLogSink(LogSink* destination); -void RemoveLogSink(LogSink* destination); - -// -// Specify an "extension" added to the filename specified via -// SetLogDestination. This applies to all severity levels. It's -// often used to append the port we're listening on to the logfile -// name. Thread-safe. -// -void SetLogFilenameExtension(const char* filename_extension); - -// -// Make it so that all log messages of at least a particular severity -// are logged to stderr (in addition to logging to the usual log -// file(s)). Thread-safe. -// -void SetStderrLogging(LogSeverity min_severity); - -// -// Make it so that all log messages go only to stderr. Thread-safe. -// -void LogToStderr(); - -const std::vector& GetLoggingDirectories(); - -// Returns a set of existing temporary directories, which will be a -// subset of the directories returned by GetLogginDirectories(). -// Thread-safe. -void GetExistingTempDirectories(std::vector* list); - -// Print any fatal message again -- useful to call from signal handler -// so that the last thing in the output is the fatal message. -// Thread-hostile, but a race is unlikely. -void ReprintFatalMessage(); - -// Truncate a log file that may be the append-only output of multiple -// processes and hence can't simply be renamed/reopened (typically a -// stdout/stderr). If the file "path" is > "limit" bytes, copy the -// last "keep" bytes to offset 0 and truncate the rest. Since we could -// be racing with other writers, this approach has the potential to -// lose very small amounts of data. For security, only follow symlinks -// if the path is /proc/self/fd/* -void TruncateLogFile(const char* path, int64_t limit, int64_t keep); - -// Truncate stdout and stderr if they are over the value specified by -// --max_log_size; keep the final 1MB. This function has the same -// race condition as TruncateLogFile. -void TruncateStdoutStderr(); - -// --------------------------------------------------------------------- -// Implementation details that are not useful to most clients -// --------------------------------------------------------------------- - -// A Logger is the interface used by logging modules to emit entries -// to a log. A typical implementation will dump formatted data to a -// sequence of files. We also provide interfaces that will forward -// the data to another thread so that the invoker never blocks. -// Implementations should be thread-safe since the logging system -// will write to them from multiple threads. - -class Logger { - public: - virtual ~Logger(); - - // Writes "message[0,message_len-1]" corresponding to an event that - // occurred at "tick_counts". If "force_flush" is true, the log file - // is flushed immediately. - // - // The input message has already been formatted as deemed - // appropriate by the higher level logging facility. For example, - // textual log messages already contain tick_counts, and the - // file:linenumber header. - virtual void Write(bool force_flush, uint64_t tick_counts, const char* message, int message_len) = 0; - - // Flush any buffered messages - virtual void Flush() = 0; - - // Get the current LOG file size. - // The returned value is approximate since some - // logged data may not have been flushed to disk yet. - virtual uint32_t LogSize() = 0; -}; - -// Get the logger for the specified severity level. The logger -// remains the property of the logging module and should not be -// deleted by the caller. Thread-safe. -extern Logger* GetLogger(LogSeverity level); - -// Set the logger for the specified severity level. The logger -// becomes the property of the logging module and should not -// be deleted by the caller. Thread-safe. -extern void SetLogger(LogSeverity level, Logger* logger); - -// glibc has traditionally implemented two incompatible versions of -// strerror_r(). There is a poorly defined convention for picking the -// version that we want, but it is not clear whether it even works with -// all versions of glibc. -// So, instead, we provide this wrapper that automatically detects the -// version that is in use, and then implements POSIX semantics. -// N.B. In addition to what POSIX says, we also guarantee that "buf" will -// be set to an empty string, if this function failed. This means, in most -// cases, you do not need to check the error code and you can directly -// use the value of "buf". It will never have an undefined value. -// DEPRECATED: Use StrError(int) instead. -int posix_strerror_r(int err, char* buf, size_t len); - -// A thread-safe replacement for strerror(). Returns a string describing the -// given POSIX error code. -std::string StrError(int err); - -// A class for which we define operator<<, which does nothing. -class NullStream : public LogMessage::LogStream { - public: - // Initialize the LogStream so the messages can be written somewhere - // (they'll never be actually displayed). This will be needed if a - // NullStream& is implicitly converted to LogStream&, in which case - // the overloaded NullStream::operator<< will not be invoked. - NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) {} - NullStream& stream() { return *this; } - - private: - // A very short buffer for messages (which we discard anyway). This - // will be needed if NullStream& converted to LogStream& (e.g. as a - // result of a conditional expression). - char message_buffer_[2]; -}; - -// Do nothing. This operator is inline, allowing the message to be -// compiled away. The message will not be compiled away if we do -// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when -// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly -// converted to LogStream and the message will be computed and then -// quietly discarded. -template -inline NullStream& operator<<(NullStream& str, const T&) { - return str; -} - -// Similar to NullStream, but aborts the program (without stack -// trace), like LogMessageFatal. -class NullStreamFatal : public NullStream { - public: - NullStreamFatal() {} - [[noreturn]] ~NullStreamFatal() throw() { _exit(1); } -}; - -// Used by LOG_IS_ON to lazy-evaluate stream arguments. -bool ShouldCreateLogMessage(LogSeverity severity); - -// Async signal safe logging mechanism. -void RawLog(int level, const char* message); - -#define RAW_LOG(level, message) RawLog(LOGGING_##level, message) - -} // namespace yass - -#include "core/check_op.hpp" - -#endif // H_CORE_LOGGING +#endif // H_CORE_LOGGING diff --git a/yass/src/core/rand_util.cpp b/yass/src/core/rand_util.cpp deleted file mode 100644 index c9ac15a011..0000000000 --- a/yass/src/core/rand_util.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2019-2020 Chilledheart */ - -#include "core/rand_util.hpp" - -#include -#include -#include - -#include -#include - -#include "core/logging.hpp" - -uint64_t RandUint64() { - uint64_t number; - RandBytes(&number, sizeof(number)); - return number; -} - -int RandInt(int min, int max) { - DCHECK_LE(min, max); - - uint64_t range = static_cast(max) - min + 1; - // |range| is at most UINT_MAX + 1, so the result of RandGenerator(range) - // is at most UINT_MAX. Hence it's safe to cast it from uint64_t to int64_t. - int result = static_cast(min + static_cast(RandGenerator(range))); - DCHECK_GE(result, min); - DCHECK_LE(result, max); - return result; -} - -double RandDouble() { - return BitsToOpenEndedUnitInterval(RandUint64()); -} - -double BitsToOpenEndedUnitInterval(uint64_t bits) { - // We try to get maximum precision by masking out as many bits as will fit - // in the target type's mantissa, and raising it to an appropriate power to - // produce output in the range [0, 1). For IEEE 754 doubles, the mantissa - // is expected to accommodate 53 bits. - - static_assert(std::numeric_limits::radix == 2, "otherwise use scalbn"); - static const int kBits = std::numeric_limits::digits; - uint64_t random_bits = bits & ((UINT64_C(1) << kBits) - 1); - double result = ldexp(static_cast(random_bits), -1 * kBits); - DCHECK_GE(result, 0.0); - DCHECK_LT(result, 1.0); - return result; -} - -uint64_t RandGenerator(uint64_t range) { - DCHECK_GT(range, 0u); - // We must discard random results above this number, as they would - // make the random generator non-uniform (consider e.g. if - // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice - // as likely as a result of 3 or 4). - uint64_t max_acceptable_value = (std::numeric_limits::max() / range) * range - 1; - - uint64_t value; - do { - value = RandUint64(); - } while (value > max_acceptable_value); - - return value % range; -} - -std::string RandBytesAsString(size_t length) { - DCHECK_GT(length, 0u); - std::string result; - result.reserve(length + 1); - result.resize(length); - RandBytes(&result[0], length); - return result; -} diff --git a/yass/src/core/rand_util.hpp b/yass/src/core/rand_util.hpp deleted file mode 100644 index a5c33ec08b..0000000000 --- a/yass/src/core/rand_util.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2019-2020 Chilledheart */ - -#ifndef CORE_RAND_UTIL -#define CORE_RAND_UTIL - -#include -#include - -#include - -// Returns a random number in range [0, UINT64_MAX]. Thread-safe. -uint64_t RandUint64(); - -// Returns a random number between min and max (inclusive). Thread-safe. -int RandInt(int min, int max); - -// Returns a random number in range [0, range). Thread-safe. -uint64_t RandGenerator(uint64_t range); - -// Returns a random double in range [0, 1). Thread-safe. -double RandDouble(); - -// Given input |bits|, convert with maximum precision to a double in -// the range [0, 1). Thread-safe. -double BitsToOpenEndedUnitInterval(uint64_t bits); - -// Fills |output_length| bytes of |output| with random data. Thread-safe. -// -void RandBytes(void* output, size_t output_length); - -// Fills a string of length |length| with random data and returns it. -// |length| should be nonzero. Thread-safe. -// -// Note that this is a variation of |RandBytes| with a different return type. -// The returned string is likely not ASCII/UTF-8. Use with care. -// -// Although implementations are required to use a cryptographically secure -// random number source, code outside of base/ that relies on this should use -// crypto::RandBytes instead to ensure the requirement is easily discoverable. -std::string RandBytesAsString(size_t length); - -// An STL UniformRandomBitGenerator backed by RandUint64. -// TODO(tzik): Consider replacing this with a faster implementation. -class RandomBitGenerator { - public: - using result_type = uint64_t; - static constexpr result_type min() { return 0; } - static constexpr result_type max() { return UINT64_MAX; } - result_type operator()() const { return RandUint64(); } - - RandomBitGenerator() = default; - ~RandomBitGenerator() = default; -}; - -#ifndef __WIN32__ -int GetUrandomFD(); -#endif // __WIN32__ - -#endif // CORE_RAND_UTIL diff --git a/yass/src/core/rand_util_posix.cpp b/yass/src/core/rand_util_posix.cpp deleted file mode 100644 index 82c1df3a14..0000000000 --- a/yass/src/core/rand_util_posix.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ - -#include "core/rand_util.hpp" - -#ifndef _WIN32 - -#include -#include -#include -#include -#include - -#include - -#include "core/logging.hpp" - -#if defined(__linux__) || defined(__ANDROID__) -#include "linux_syscall_support.h" -#elif BUILDFLAG(IS_MAC) -// TODO(crbug.com/995996): Waiting for this header to appear in the iOS SDK. -// (See below.) -#include -#endif - -#if __APPLE__ -#include -#endif - -// Inlcude MSAN_UNPOISON fixes -#include "core/compiler_specific.hpp" - -// TODO: move to file_utils.cpp -static bool ReadFromFD(int fd, char* buffer, size_t bytes); - -bool ReadFromFD(int fd, char* buffer, size_t bytes) { - size_t total_read = 0; - while (total_read < bytes) { - ssize_t bytes_read = HANDLE_EINTR(read(fd, buffer + total_read, bytes - total_read)); - if (bytes_read <= 0) - break; - total_read += bytes_read; - } - return total_read == bytes; -} - -namespace { - -static constexpr const int kOpenFlags = O_RDONLY | O_CLOEXEC; - -// We keep the file descriptor for /dev/urandom around so we don't need to -// reopen it (which is expensive), and since we may not even be able to reopen -// it if we are later put in a sandbox. This class wraps the file descriptor so -// we can use a static-local variable to handle opening it on the first access. -class URandomFd { - public: - URandomFd() : fd_(HANDLE_EINTR(open("/dev/urandom", kOpenFlags))) { CHECK(fd_ >= 0) << "Cannot open /dev/urandom"; } - - ~URandomFd() { IGNORE_EINTR(::close(fd_)); } - - int fd() const { return fd_; } - - private: - const int fd_; -}; - -} // anonymous namespace - -// NOTE: In an ideal future, all implementations of this function will just -// wrap BoringSSL's `RAND_bytes`. TODO(crbug.com/995996): Figure out the -// build/test/performance issues with dcheng's CL -// (https://chromium-review.googlesource.com/c/chromium/src/+/1545096) and land -// it or some form of it. -void RandBytes(void* output, size_t output_length) { -// FIXME currently lss doesn't like riscv32 -#if defined(__linux__) && !defined(ARCH_CPU_RISCV32) - // We have to call `getrandom` via Linux Syscall Support, rather than through - // the libc wrapper, because we might not have an up-to-date libc (e.g. on - // some bots). - const ssize_t r = HANDLE_EINTR(sys_getrandom(output, output_length, 0)); - - // Return success only on total success. In case errno == ENOSYS (or any other - // error), we'll fall through to reading from urandom below. - if (output_length == static_cast(r)) { - MSAN_UNPOISON(output, output_length); - return; - } -#elif BUILDFLAG(IS_MAC) - // TODO(crbug.com/995996): Enable this on iOS too, when sys/random.h arrives - // in its SDK. - if (getentropy(output, output_length) == 0) { - return; - } -#endif - - // If the OS-specific mechanisms didn't work, fall through to reading from - // urandom. - // - // TODO(crbug.com/995996): When we no longer need to support old Linux - // kernels, we can get rid of this /dev/urandom branch altogether. - const int urandom_fd = GetUrandomFD(); - const bool success = ReadFromFD(urandom_fd, static_cast(output), output_length); - CHECK(success) << "urandom read failure"; -} - -int GetUrandomFD() { - static URandomFd urandom_fd; - return urandom_fd.fd(); -} - -#endif // _WIN32 diff --git a/yass/src/core/rand_util_win.cpp b/yass/src/core/rand_util_win.cpp deleted file mode 100644 index df002ee49d..0000000000 --- a/yass/src/core/rand_util_win.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ - -#include "core/rand_util.hpp" - -#ifdef _WIN32 - -#include -#include -#include -#include -#include - -#include -#include "core/logging.hpp" - -// Prototype for ProcessPrng. -// See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng -extern "C" { -BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData); -} - -namespace { - -// wine's trick -decltype(&ProcessPrng) GetProcessPrngFallback() { - HMODULE hmod = LoadLibraryW(L"advapi32"); - CHECK(hmod); - auto process_prng_fn = - reinterpret_cast(reinterpret_cast(GetProcAddress(hmod, "SystemFunction036"))); - CHECK(process_prng_fn); - return process_prng_fn; -} - -decltype(&ProcessPrng) GetProcessPrng() { - HMODULE hmod = LoadLibraryW(L"bcryptprimitives"); - if (hmod == nullptr) { - return GetProcessPrngFallback(); - } - auto process_prng_fn = - reinterpret_cast(reinterpret_cast(GetProcAddress(hmod, "ProcessPrng"))); - if (process_prng_fn == nullptr) { - // Possible on Windows 7 SP1, need fallback as well - return GetProcessPrngFallback(); - } - return process_prng_fn; -} - -} // namespace - -void RandBytes(void* output, size_t output_length) { - BYTE* output_ptr = static_cast(output); - while (output_length > 0) { - static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng(); - const ULONG output_bytes_this_pass = - static_cast(std::min(output_length, static_cast(std::numeric_limits::max()))); - const BOOL success = process_prng_fn(output_ptr, output_bytes_this_pass); - // ProcessPrng is documented to always return TRUE. - CHECK(success); - output_length -= output_bytes_this_pass; - output_ptr += output_bytes_this_pass; - } -} - -#endif // _WIN32 diff --git a/yass/src/core/scoped_clear_last_error_win.cpp b/yass/src/core/scoped_clear_last_error_win.cpp index ec14a85fc2..1ae6318374 100644 --- a/yass/src/core/scoped_clear_last_error_win.cpp +++ b/yass/src/core/scoped_clear_last_error_win.cpp @@ -6,6 +6,9 @@ #include +namespace gurl_base { +namespace logging { + ScopedClearLastError::ScopedClearLastError() : last_system_error_(GetLastError()) { SetLastError(0); } @@ -14,4 +17,7 @@ ScopedClearLastError::~ScopedClearLastError() { SetLastError(last_system_error_); } +} // namespace logging +} // namespace gurl_base + #endif // _WIN32 diff --git a/yass/src/core/scoped_policy.hpp b/yass/src/core/scoped_policy.hpp deleted file mode 100644 index 266b8c4571..0000000000 --- a/yass/src/core/scoped_policy.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ - -#ifndef CORE_SCOPED_POLICY_H -#define CORE_SCOPED_POLICY_H - -namespace scoped_policy { - -// Defines the ownership policy for a scoped object. -enum OwnershipPolicy { - // The scoped object takes ownership of an object by taking over an existing - // ownership claim. - ASSUME, - - // The scoped object will retain the object and any initial ownership is - // not changed. - RETAIN -}; - -} // namespace scoped_policy - -#endif // CORE_SCOPED_POLICY_H diff --git a/yass/src/core/template_util.hpp b/yass/src/core/template_util.hpp deleted file mode 100644 index f5757937fb..0000000000 --- a/yass/src/core/template_util.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022-2024 Chilledheart */ - -#ifndef CORE_TEMPLATE_UTIL_INTERNAL_H -#define CORE_TEMPLATE_UTIL_INTERNAL_H - -#include -#include -#include -#include -#include - -#include - -namespace internal { - -// Uses expression SFINAE to detect whether using operator<< would work. -template -struct SupportsOstreamOperator : std::false_type {}; -template -struct SupportsOstreamOperator() << std::declval()))> : std::true_type { -}; - -template -struct SupportsToString : std::false_type {}; -template -struct SupportsToString().ToString()))> : std::true_type {}; - -} // namespace internal - -#endif // CORE_TEMPLATE_UTIL_INTERNAL_H diff --git a/yass/src/core/thread_collision_warner.cpp b/yass/src/core/thread_collision_warner.cpp deleted file mode 100644 index 1f847e0d04..0000000000 --- a/yass/src/core/thread_collision_warner.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ - -#include "core/thread_collision_warner.hpp" -#include -#include -#include -#include "core/logging.hpp" - -void DCheckAsserter::warn() { - NOTREACHED() << "Thread Collision"; -} diff --git a/yass/src/core/utils_test.cpp b/yass/src/core/utils_test.cpp index 713d56c473..ff05824da2 100644 --- a/yass/src/core/utils_test.cpp +++ b/yass/src/core/utils_test.cpp @@ -5,7 +5,6 @@ #include "core/logging.hpp" #include "core/process_utils.hpp" -#include "core/rand_util.hpp" #include "core/utils.hpp" #include "core/utils_fs.hpp" @@ -14,6 +13,7 @@ #endif #include +#include #include #include @@ -110,9 +110,9 @@ TEST(UtilsTest, GetHomeDir) { TEST(UtilsTest, ReadFileAndWrite4K) { std::string buf, buf2; buf.resize(4096); - RandBytes(buf.data(), buf.size()); + gurl_base::RandBytes(buf.data(), buf.size()); int tmp_suffix; - RandBytes(&tmp_suffix, sizeof(tmp_suffix)); + gurl_base::RandBytes(&tmp_suffix, sizeof(tmp_suffix)); auto tmp_name = absl::StrFormat("read_write_file-%u-%d", GetPID(), tmp_suffix); auto tmp_dir = std::filesystem::path(::testing::TempDir()); #ifdef _WIN32 diff --git a/yass/src/crypto/aead_evp_decrypter.cpp b/yass/src/crypto/aead_evp_decrypter.cpp index a7b3e8308b..8e9c1c2f51 100644 --- a/yass/src/crypto/aead_evp_decrypter.cpp +++ b/yass/src/crypto/aead_evp_decrypter.cpp @@ -11,7 +11,7 @@ // In debug builds only, log OpenSSL error stack. Then clear OpenSSL error // stack. static void DLogOpenSslErrors() { -#ifdef NDEBUG +#if !DCHECK_IS_ON() ERR_clear_error(); #else while (uint32_t error = ERR_get_error()) { diff --git a/yass/src/crypto/aead_evp_encrypter.cpp b/yass/src/crypto/aead_evp_encrypter.cpp index 04ea5870fb..492572aede 100644 --- a/yass/src/crypto/aead_evp_encrypter.cpp +++ b/yass/src/crypto/aead_evp_encrypter.cpp @@ -11,7 +11,7 @@ // In debug builds only, log OpenSSL error stack. Then clear OpenSSL error // stack. static void DLogOpenSslErrors() { -#ifdef NDEBUG +#if !DCHECK_IS_ON() ERR_clear_error(); #else while (uint32_t error = ERR_get_error()) { diff --git a/yass/src/crypto/aead_sodium_decrypter.cpp b/yass/src/crypto/aead_sodium_decrypter.cpp index 83ff40b247..c4483360dc 100644 --- a/yass/src/crypto/aead_sodium_decrypter.cpp +++ b/yass/src/crypto/aead_sodium_decrypter.cpp @@ -11,7 +11,7 @@ // In debug builds only, log OpenSSL error stack. Then clear OpenSSL error // stack. static void DLogOpenSslErrors() { -#ifdef NDEBUG +#if !DCHECK_IS_ON() ERR_clear_error(); #else while (uint32_t error = ERR_get_error()) { diff --git a/yass/src/crypto/aead_sodium_encrypter.cpp b/yass/src/crypto/aead_sodium_encrypter.cpp index bd45ab9561..0f8fc45832 100644 --- a/yass/src/crypto/aead_sodium_encrypter.cpp +++ b/yass/src/crypto/aead_sodium_encrypter.cpp @@ -11,7 +11,7 @@ // In debug builds only, log OpenSSL error stack. Then clear OpenSSL error // stack. static void DLogOpenSslErrors() { -#ifdef NDEBUG +#if !DCHECK_IS_ON() ERR_clear_error(); #else while (uint32_t error = ERR_get_error()) { diff --git a/yass/src/net/asio_ssl.cpp b/yass/src/net/asio_ssl.cpp index 6fbc0c5bab..eef4320138 100644 --- a/yass/src/net/asio_ssl.cpp +++ b/yass/src/net/asio_ssl.cpp @@ -259,7 +259,8 @@ void print_openssl_error() { while (uint32_t error = ERR_get_error_line(&file, &line)) { char buf[120]; ERR_error_string_n(error, buf, sizeof(buf)); - ::yass::LogMessage(file, line, LOGGING_ERROR).stream() << "OpenSSL error: " << buf; + ::gurl_base::logging::LogMessage(file, line, ::gurl_base::logging::LOGGING_ERROR).stream() + << "OpenSSL error: " << buf; } } diff --git a/yass/src/net/asio_throw_exceptions.hpp b/yass/src/net/asio_throw_exceptions.hpp index 35c45b5679..248c21aaeb 100644 --- a/yass/src/net/asio_throw_exceptions.hpp +++ b/yass/src/net/asio_throw_exceptions.hpp @@ -4,8 +4,8 @@ #ifndef H_NET_ASIO_THROW_EXCEPTIONS #define H_NET_ASIO_THROW_EXCEPTIONS +#include "base/immediate_crash.h" #include "core/debug.hpp" -#include "core/immediate_crash.hpp" #include "core/logging.hpp" namespace asio { @@ -16,7 +16,7 @@ namespace detail { template void throw_exception(const Exception& e) { Alias(&e); - ImmediateCrash(); + gurl_base::ImmediateCrash(); } #endif // ASIO_NO_EXCEPTIONS diff --git a/yass/src/net/c-ares.hpp b/yass/src/net/c-ares.hpp index e2445a64c2..7e6c9657c9 100644 --- a/yass/src/net/c-ares.hpp +++ b/yass/src/net/c-ares.hpp @@ -12,8 +12,9 @@ #include #include -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" +#include +#include + #include "net/asio.hpp" namespace net { @@ -24,11 +25,11 @@ using fd_t = SOCKET; using fd_t = int; #endif -class CAresResolver : public RefCountedThreadSafe { +class CAresResolver : public gurl_base::RefCountedThreadSafe { public: CAresResolver(asio::io_context& io_context); static scoped_refptr Create(asio::io_context& io_context) { - return MakeRefCounted(io_context); + return gurl_base::MakeRefCounted(io_context); } ~CAresResolver(); @@ -52,7 +53,7 @@ class CAresResolver : public RefCountedThreadSafe { private: struct ResolverPerContext : public RefCountedThreadSafe { static scoped_refptr Create(asio::io_context& io_context, fd_t fd) { - return MakeRefCounted(io_context, fd); + return gurl_base::MakeRefCounted(io_context, fd); } ResolverPerContext(asio::io_context& io_context, fd_t fd) : socket(io_context, asio::ip::udp::v4(), fd) {} ~ResolverPerContext() { diff --git a/yass/src/net/cipher.cpp b/yass/src/net/cipher.cpp index 718cafb146..44797da60e 100644 --- a/yass/src/net/cipher.cpp +++ b/yass/src/net/cipher.cpp @@ -5,11 +5,11 @@ #include +#include #include "third_party/boringssl/src/include/openssl/base64.h" #include "third_party/boringssl/src/include/openssl/md5.h" #include "core/logging.hpp" -#include "core/rand_util.hpp" #include "crypto/decrypter.hpp" #include "crypto/encrypter.hpp" #include "net/hkdf_sha1.hpp" @@ -193,9 +193,7 @@ cipher::cipher(const std::string& key, key_len_ = !key.empty() ? cipher_impl::parse_key(key, key_, key_bitlen_ / 8) : cipher_impl::derive_key(password, key_, key_bitlen_ / 8); -#ifndef NDEBUG DumpHex("cipher: KEY", key_, key_len_); -#endif tag_len_ = impl_->GetTagSize(); } @@ -283,9 +281,7 @@ void cipher::decrypt_salt(IOBuf* chunk) { chunk->trimStart(nonce_len); chunk->retreat(nonce_len); set_key_stream(nonce, nonce_len); -#ifndef NDEBUG DumpHex("DE-NONCE", nonce, nonce_len); -#endif return; } #endif @@ -298,9 +294,7 @@ void cipher::decrypt_salt(IOBuf* chunk) { chunk->retreat(salt_len); set_key_aead(salt_, salt_len); -#ifndef NDEBUG DumpHex("DE-SALT", salt_, salt_len); -#endif } void cipher::encrypt_salt(IOBuf* chunk) { @@ -311,29 +305,25 @@ void cipher::encrypt_salt(IOBuf* chunk) { size_t nonce_len = impl_->GetIVSize(); VLOG(4) << "encrypt: nonce: " << nonce_len; uint8_t nonce[MAX_NONCE_LENGTH] = {}; - RandBytes(nonce, nonce_len); + gurl_base::RandBytes(nonce, nonce_len); chunk->reserve(nonce_len, 0); chunk->prepend(nonce_len); memcpy(chunk->mutable_data(), nonce, nonce_len); set_key_stream(nonce, nonce_len); -#ifndef NDEBUG DumpHex("EN-NONCE", nonce, nonce_len); -#endif return; } #endif size_t salt_len = key_len_; VLOG(4) << "encrypt: salt: " << salt_len; - RandBytes(salt_, key_len_); + gurl_base::RandBytes(salt_, key_len_); chunk->reserve(salt_len, 0); chunk->prepend(salt_len); memcpy(chunk->mutable_data(), salt_, salt_len); set_key_aead(salt_, salt_len); -#ifndef NDEBUG DumpHex("EN-SALT", salt_, salt_len); -#endif } int cipher::chunk_decrypt_frame(uint64_t* counter, IOBuf* plaintext, IOBuf* ciphertext) const { @@ -539,10 +529,8 @@ void cipher::set_key_stream(const uint8_t* nonce, size_t nonce_len) { LOG(WARNING) << "SetKey Failed"; } -#ifndef NDEBUG DumpHex("KEY", impl_->GetKey(), impl_->GetKeySize()); DumpHex("IV", impl_->GetIV(), impl_->GetIVSize()); -#endif } void cipher::set_key_aead(const uint8_t* salt, size_t salt_len) { @@ -565,10 +553,8 @@ void cipher::set_key_aead(const uint8_t* salt, size_t salt_len) { LOG(WARNING) << "SetNoncePrefix Failed"; } -#ifndef NDEBUG DumpHex("SKEY", impl_->GetKey(), impl_->GetKeySize()); DumpHex("NONCE_PREFIX", impl_->GetNoncePrefix(), impl_->GetNoncePrefixSize()); -#endif } } // namespace net diff --git a/yass/src/net/cipher_test.cpp b/yass/src/net/cipher_test.cpp index a17470c235..19af55f214 100644 --- a/yass/src/net/cipher_test.cpp +++ b/yass/src/net/cipher_test.cpp @@ -5,8 +5,8 @@ #include #include +#include #include -#include "core/rand_util.hpp" #include "net/cipher.hpp" #include "test_util.hpp" @@ -17,7 +17,7 @@ namespace { std::unique_ptr GenerateRandContent(int size) { auto buf = IOBuf::create(size); - RandBytes(buf->mutable_data(), std::min(256, size)); + gurl_base::RandBytes(buf->mutable_data(), std::min(256, size)); for (int i = 1; i < size / 256; ++i) { memcpy(buf->mutable_data() + 256 * i, buf->data(), 256); } diff --git a/yass/src/net/connection.hpp b/yass/src/net/connection.hpp index 5f2f8342ea..2456130193 100644 --- a/yass/src/net/connection.hpp +++ b/yass/src/net/connection.hpp @@ -352,7 +352,7 @@ class ConnectionFactory { template static scoped_refptr Create(Args&&... args) { - return MakeRefCounted(std::forward(args)...); + return gurl_base::MakeRefCounted(std::forward(args)...); } static constexpr const ConnectionFactoryType Type = ConnectionType::Type; static constexpr const std::string_view Name = ConnectionType::Name; diff --git a/yass/src/net/content_server.hpp b/yass/src/net/content_server.hpp index f1c1fe4a87..a476558afa 100644 --- a/yass/src/net/content_server.hpp +++ b/yass/src/net/content_server.hpp @@ -15,9 +15,10 @@ #include #include +#include + #include "config/config_tls.hpp" #include "core/logging.hpp" -#include "core/scoped_refptr.hpp" #include "core/utils.hpp" #include "crypto/crypter_export.hpp" #include "net/asio.hpp" diff --git a/yass/src/net/doh_request.hpp b/yass/src/net/doh_request.hpp index 0f8727769b..0b2320d551 100644 --- a/yass/src/net/doh_request.hpp +++ b/yass/src/net/doh_request.hpp @@ -5,9 +5,9 @@ #define H_NET_DOH_REQUEST_HPP #include +#include +#include -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "net/asio.hpp" #include "net/dns_message.hpp" #include "net/network.hpp" @@ -15,7 +15,7 @@ namespace net { -class DoHRequest : public RefCountedThreadSafe { +class DoHRequest : public gurl_base::RefCountedThreadSafe { public: DoHRequest(int ssl_socket_data_index, asio::io_context& io_context, @@ -36,7 +36,7 @@ class DoHRequest : public RefCountedThreadSafe { template static scoped_refptr Create(Args&&... args) { - return MakeRefCounted(std::forward(args)...); + return gurl_base::MakeRefCounted(std::forward(args)...); } ~DoHRequest(); diff --git a/yass/src/net/doh_resolver.hpp b/yass/src/net/doh_resolver.hpp index bab467dd49..afcec5ef7b 100644 --- a/yass/src/net/doh_resolver.hpp +++ b/yass/src/net/doh_resolver.hpp @@ -5,20 +5,20 @@ #define H_NET_DOH_RESOLVER_HPP #include +#include +#include #include #include -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "net/asio.hpp" #include "net/doh_request.hpp" namespace net { -class DoHResolver : public RefCountedThreadSafe { +class DoHResolver : public gurl_base::RefCountedThreadSafe { public: DoHResolver(asio::io_context& io_context); static scoped_refptr Create(asio::io_context& io_context) { - return MakeRefCounted(io_context); + return gurl_base::MakeRefCounted(io_context); } ~DoHResolver(); diff --git a/yass/src/net/dot_request.hpp b/yass/src/net/dot_request.hpp index 1b38879cdc..11e8857f6b 100644 --- a/yass/src/net/dot_request.hpp +++ b/yass/src/net/dot_request.hpp @@ -5,9 +5,9 @@ #define H_NET_DOT_REQUEST_HPP #include +#include +#include -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "net/asio.hpp" #include "net/dns_message.hpp" #include "net/network.hpp" @@ -15,7 +15,7 @@ namespace net { -class DoTRequest : public RefCountedThreadSafe { +class DoTRequest : public gurl_base::RefCountedThreadSafe { public: DoTRequest(int ssl_socket_data_index, asio::io_context& io_context, @@ -34,7 +34,7 @@ class DoTRequest : public RefCountedThreadSafe { template static scoped_refptr Create(Args&&... args) { - return MakeRefCounted(std::forward(args)...); + return gurl_base::MakeRefCounted(std::forward(args)...); } ~DoTRequest(); diff --git a/yass/src/net/dot_resolver.hpp b/yass/src/net/dot_resolver.hpp index ba7828cf58..c00e8b191b 100644 --- a/yass/src/net/dot_resolver.hpp +++ b/yass/src/net/dot_resolver.hpp @@ -5,20 +5,20 @@ #define H_NET_DOT_RESOLVER_HPP #include +#include +#include #include #include -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "net/asio.hpp" #include "net/dot_request.hpp" namespace net { -class DoTResolver : public RefCountedThreadSafe { +class DoTResolver : public gurl_base::RefCountedThreadSafe { public: DoTResolver(asio::io_context& io_context); static scoped_refptr Create(asio::io_context& io_context) { - return MakeRefCounted(io_context); + return gurl_base::MakeRefCounted(io_context); } ~DoTResolver(); diff --git a/yass/src/net/padding.cpp b/yass/src/net/padding.cpp index 98c1f98fb6..d685df6b72 100644 --- a/yass/src/net/padding.cpp +++ b/yass/src/net/padding.cpp @@ -3,7 +3,7 @@ #include "net/padding.hpp" -#include "core/rand_util.hpp" +#include /// /// input: @@ -17,7 +17,7 @@ namespace net { void AddPadding(std::shared_ptr buf) { size_t payload_size = buf->length(); DCHECK_LE(payload_size, 0xffffu); - size_t padding_size = RandInt(0, kMaxPaddingSize); + size_t padding_size = gurl_base::RandInt(0, kMaxPaddingSize); buf->reserve(kPaddingHeaderSize, padding_size); uint8_t* p = buf->mutable_buffer(); diff --git a/yass/src/net/protocol.hpp b/yass/src/net/protocol.hpp index 1ee6f0777d..3bc6ba2c04 100644 --- a/yass/src/net/protocol.hpp +++ b/yass/src/net/protocol.hpp @@ -34,7 +34,7 @@ NextProto NextProtoFromString(std::string_view proto_string); std::string_view NextProtoToString(NextProto next_proto); -#ifndef NDEBUG +#if DCHECK_IS_ON() inline void DumpHex_Impl(const char* file, int line, const char* prefix, const uint8_t* data, uint32_t length) { if (!VLOG_IS_ON(4)) { return; @@ -82,7 +82,7 @@ inline void DumpHex_Impl(const char* file, int line, const char* prefix, const u done: // ensure it is null-terminated hex_buffer[sizeof(hex_buffer) - 1] = '\0'; - ::yass::LogMessage(file, line, -4).stream() << hex_buffer; + ::gurl_base::logging::LogMessage(file, line, -4).stream() << hex_buffer; } inline void DumpHex_Impl(const char* file, int line, const char* prefix, const net::IOBuf* buf) { @@ -90,11 +90,11 @@ inline void DumpHex_Impl(const char* file, int line, const char* prefix, const n uint32_t length = buf->length(); DumpHex_Impl(file, line, prefix, data, length); } -#endif // NDEBUG +#endif // DCHECK_IS_ON() } // namespace net -#ifndef NDEBUG +#if DCHECK_IS_ON() #define DumpHex(...) ::net::DumpHex_Impl(__FILE__, __LINE__, __VA_ARGS__) #else #define DumpHex(...) diff --git a/yass/src/net/ssl_server_socket.hpp b/yass/src/net/ssl_server_socket.hpp index 5b5e99e996..0042044fc6 100644 --- a/yass/src/net/ssl_server_socket.hpp +++ b/yass/src/net/ssl_server_socket.hpp @@ -5,10 +5,10 @@ #define H_NET_SSL_SERVER_SOCKET #include +#include +#include #include "third_party/boringssl/src/include/openssl/ssl.h" -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "net/asio.hpp" #include "net/iobuf.hpp" #include "net/net_errors.hpp" @@ -22,7 +22,7 @@ namespace net { using CompletionOnceCallback = absl::AnyInvocable; using WaitCallback = absl::AnyInvocable; -class SSLServerSocket : public RefCountedThreadSafe { +class SSLServerSocket : public gurl_base::RefCountedThreadSafe { public: SSLServerSocket(asio::io_context* io_context, asio::ip::tcp::socket* socket, SSL_CTX* ssl_ctx); ~SSLServerSocket(); @@ -32,7 +32,7 @@ class SSLServerSocket : public RefCountedThreadSafe { template static scoped_refptr Create(Args&&... args) { - return MakeRefCounted(std::forward(args)...); + return gurl_base::MakeRefCounted(std::forward(args)...); } int Handshake(CompletionOnceCallback callback); diff --git a/yass/src/net/ssl_socket.hpp b/yass/src/net/ssl_socket.hpp index 9d33f16843..04c0789e26 100644 --- a/yass/src/net/ssl_socket.hpp +++ b/yass/src/net/ssl_socket.hpp @@ -5,11 +5,11 @@ #define H_NET_SSL_SOCKET #include +#include +#include #include #include "third_party/boringssl/src/include/openssl/ssl.h" -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "net/asio.hpp" #include "net/iobuf.hpp" #include "net/net_errors.hpp" @@ -48,7 +48,7 @@ enum class SSLHandshakeDetails { using CompletionOnceCallback = absl::AnyInvocable; using WaitCallback = absl::AnyInvocable; -class SSLSocket : public RefCountedThreadSafe { +class SSLSocket : public gurl_base::RefCountedThreadSafe { public: SSLSocket(int ssl_socket_data_index, asio::io_context* io_context, @@ -63,7 +63,7 @@ class SSLSocket : public RefCountedThreadSafe { template static scoped_refptr Create(Args&&... args) { - return MakeRefCounted(std::forward(args)...); + return gurl_base::MakeRefCounted(std::forward(args)...); } // StreamSocket implementation diff --git a/yass/src/net/ssl_stream.hpp b/yass/src/net/ssl_stream.hpp index 0c7577948e..3610e965ae 100644 --- a/yass/src/net/ssl_stream.hpp +++ b/yass/src/net/ssl_stream.hpp @@ -14,7 +14,7 @@ class ssl_stream : public stream { /// construct a ssl_stream object template static scoped_refptr create(Args&&... args) { - return MakeRefCounted(std::forward(args)...); + return gurl_base::MakeRefCounted(std::forward(args)...); } /// construct a ssl stream object with ss protocol diff --git a/yass/src/net/stream.hpp b/yass/src/net/stream.hpp index 4426171a8f..f52d9de546 100644 --- a/yass/src/net/stream.hpp +++ b/yass/src/net/stream.hpp @@ -11,7 +11,6 @@ #include "config/config_network.hpp" #include "config/config_ptype.hpp" #include "core/logging.hpp" -#include "core/scoped_refptr.hpp" #include "core/utils.hpp" #include "net/asio.hpp" #include "net/network.hpp" @@ -27,6 +26,7 @@ #include #include #include +#include namespace net { @@ -71,7 +71,7 @@ inline int64_t pgrsLimitWaitTime(int64_t cursize, int64_t startsize, int64_t lim } /// the class to describe the traffic between given node (endpoint) -class stream : public RefCountedThreadSafe { +class stream : public gurl_base::RefCountedThreadSafe { public: using io_handle_t = absl::AnyInvocable; using handle_t = absl::AnyInvocable; @@ -79,7 +79,7 @@ class stream : public RefCountedThreadSafe { /// construct a stream object template static scoped_refptr create(Args&&... args) { - return MakeRefCounted(std::forward(args)...); + return gurl_base::MakeRefCounted(std::forward(args)...); } /// construct a stream object with ss protocol @@ -503,13 +503,14 @@ class stream : public RefCountedThreadSafe { if (ec) { VLOG(2) << "data transfer failed with " << endpoint_ << " due to " << ec << " stats: readed " << rbytes_transferred_ << " written: " << wbytes_transferred_; -#ifndef NDEBUG +#if DCHECK_IS_ON() const char* file; int line; while (uint32_t error = ERR_get_error_line(&file, &line)) { char buf[120]; ERR_error_string_n(error, buf, sizeof(buf)); - ::yass::LogMessage(file, line, LOGGING_ERROR).stream() << "OpenSSL error: " << buf; + ::gurl_base::logging::LogMessage(file, line, ::gurl_base::logging::LOGGING_ERROR).stream() + << "OpenSSL error: " << buf; } #endif } else { diff --git a/yass/src/server/server_connection.cpp b/yass/src/server/server_connection.cpp index 789c7defd1..e53c465c80 100644 --- a/yass/src/server/server_connection.cpp +++ b/yass/src/server/server_connection.cpp @@ -5,11 +5,11 @@ #include #include +#include #include #include #include "config/config.hpp" -#include "core/rand_util.hpp" #include "core/utils.hpp" #include "net/asio.hpp" #include "net/base64.hpp" @@ -1632,8 +1632,8 @@ void ServerConnection::OnConnect() { // Send "Padding" header // originated from forwardproxy.go;func ServeHTTP if (padding_support_) { - std::string padding(RandInt(30, 64), '~'); - uint64_t bits = RandUint64(); + std::string padding(gurl_base::RandInt(30, 64), '~'); + uint64_t bits = gurl_base::RandUint64(); for (int i = 0; i < 16; ++i) { padding[i] = "!#$()+<>?@[]^`{}"[bits & 15]; bits = bits >> 4; diff --git a/yass/src/server/server_connection.hpp b/yass/src/server/server_connection.hpp index 97e5316de0..e3679cd35c 100644 --- a/yass/src/server/server_connection.hpp +++ b/yass/src/server/server_connection.hpp @@ -5,8 +5,6 @@ #define H_SS_CONNECTION #include "core/logging.hpp" -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "net/channel.hpp" #include "net/cipher.hpp" #include "net/connection.hpp" @@ -21,6 +19,8 @@ #include #include #include +#include +#include #include #ifdef HAVE_QUICHE @@ -81,7 +81,7 @@ class DataFrameSource : public http2::adapter::DataFrameSource { /// The ultimate service class to deliever the network traffic to the remote /// endpoint -class ServerConnection : public RefCountedThreadSafe, +class ServerConnection : public gurl_base::RefCountedThreadSafe, #ifdef HAVE_QUICHE public http2::adapter::Http2VisitorInterface, #endif diff --git a/yass/src/ss_benchmark.cpp b/yass/src/ss_benchmark.cpp index fe5c5067a9..a21303850d 100644 --- a/yass/src/ss_benchmark.cpp +++ b/yass/src/ss_benchmark.cpp @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include "third_party/boringssl/src/include/openssl/crypto.h" #ifdef _MSC_VER @@ -20,9 +23,6 @@ #include "cli/cli_server.hpp" #include "config/config.hpp" -#include "core/rand_util.hpp" -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "feature.h" #include "net/cipher.hpp" #include "net/iobuf.hpp" @@ -87,7 +87,7 @@ void GenerateRandContent(int size) { g_send_buffer.clear(); g_send_buffer.reserve(0, size); - RandBytes(g_send_buffer.mutable_data(), std::min(256, size)); + gurl_base::RandBytes(g_send_buffer.mutable_data(), std::min(256, size)); for (int i = 1; i < size / 256; ++i) { memcpy(g_send_buffer.mutable_data() + 256 * i, g_send_buffer.data(), 256); } @@ -96,7 +96,7 @@ void GenerateRandContent(int size) { g_recv_buffer = IOBuf::create(size); } -class ContentProviderConnection : public RefCountedThreadSafe, public Connection { +class ContentProviderConnection : public gurl_base::RefCountedThreadSafe, public Connection { public: static constexpr const ConnectionFactoryType Type = CONNECTION_FACTORY_CONTENT_PROVIDER; static constexpr const std::string_view Name = "content-provider"; @@ -663,8 +663,11 @@ int main(int argc, char** argv) { LOG(WARNING) << "Application starting: " << YASS_APP_TAG << " type: " << ProgramTypeToStr(pType); LOG(WARNING) << "Last Change: " << YASS_APP_LAST_CHANGE; LOG(WARNING) << "Features: " << YASS_APP_FEATURES; +#ifdef DCHECK_ALWAYS_ON + LOG(WARNING) << "Assertions build (DCHECK_ALWAYS_ON #defined)"; +#endif #ifndef NDEBUG - LOG(WARNING) << "Debug build (NDEBUG not #defined)\n"; + LOG(WARNING) << "Debug build (NDEBUG not #defined)"; #endif #ifdef _WIN32 diff --git a/yass/src/ss_test.cpp b/yass/src/ss_test.cpp index 1d083bf044..968ae046b3 100644 --- a/yass/src/ss_test.cpp +++ b/yass/src/ss_test.cpp @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #include "third_party/boringssl/src/include/openssl/crypto.h" #ifdef _MSC_VER @@ -29,9 +32,6 @@ ABSL_FLAG(std::string, proxy_type, "http", "proxy type, available: socks4, socks #include "cli/cli_server.hpp" #include "config/config.hpp" -#include "core/rand_util.hpp" -#include "core/ref_counted.hpp" -#include "core/scoped_refptr.hpp" #include "feature.h" #include "net/cipher.hpp" #include "net/http_parser.hpp" @@ -101,7 +101,7 @@ void GenerateRandContent(int size) { g_send_buffer.clear(); g_send_buffer.reserve(0, size); - RandBytes(g_send_buffer.mutable_data(), std::min(256, size)); + gurl_base::RandBytes(g_send_buffer.mutable_data(), std::min(256, size)); for (int i = 1; i < size / 256; ++i) { memcpy(g_send_buffer.mutable_data() + 256 * i, g_send_buffer.data(), 256); } @@ -110,7 +110,7 @@ void GenerateRandContent(int size) { g_recv_buffer = IOBuf::create(size); } -class ContentProviderConnection : public RefCountedThreadSafe, public Connection { +class ContentProviderConnection : public gurl_base::RefCountedThreadSafe, public Connection { public: static constexpr const ConnectionFactoryType Type = CONNECTION_FACTORY_CONTENT_PROVIDER; static constexpr const std::string_view Name = "content-provider"; @@ -873,8 +873,11 @@ int main(int argc, char** argv) { LOG(WARNING) << "Application starting: " << YASS_APP_TAG << " type: " << ProgramTypeToStr(pType); LOG(WARNING) << "Last Change: " << YASS_APP_LAST_CHANGE; LOG(WARNING) << "Features: " << YASS_APP_FEATURES; +#ifdef DCHECK_ALWAYS_ON + LOG(WARNING) << "Assertions build (DCHECK_ALWAYS_ON #defined)"; +#endif #ifndef NDEBUG - LOG(WARNING) << "Debug build (NDEBUG not #defined)\n"; + LOG(WARNING) << "Debug build (NDEBUG not #defined)"; #endif #ifdef _WIN32 diff --git a/yass/third_party/CMakeLists.txt b/yass/third_party/CMakeLists.txt index 115d019e6f..de28567180 100644 --- a/yass/third_party/CMakeLists.txt +++ b/yass/third_party/CMakeLists.txt @@ -101,7 +101,7 @@ add_library(url STATIC googleurl/base/functional/identity.h googleurl/base/functional/invoke.h googleurl/base/functional/not_fn.h - googleurl/base/memory/raw_ptr_exclusion.h + #googleurl/base/memory/raw_ptr_exclusion.h googleurl/base/no_destructor.h googleurl/base/numerics/checked_math.h googleurl/base/numerics/checked_math_impl.h @@ -136,7 +136,7 @@ add_library(url STATIC googleurl/base/strings/string_util.cc googleurl/base/strings/string_util_constants.cc # FIXME vs2022 doesn't even compile - # googleurl/base/strings/utf_ostream_operators.cc + googleurl/base/strings/utf_ostream_operators.cc googleurl/base/strings/utf_string_conversion_utils.cc googleurl/base/strings/utf_string_conversions.cc # icu @@ -170,6 +170,29 @@ add_library(url STATIC # googleurl/url/scheme_host_port.h # googleurl/url/origin.cc # googleurl/url/origin.h + googleurl-override/base/atomic_ref_count.h + googleurl-override/base/atomicops.h + googleurl-override/base/atomicops_internals_portable.h + googleurl-override/base/atomicops_internals_atomicword_compat.h + googleurl-override/base/macros/concat.h + googleurl-override/base/macros/if.h + googleurl-override/base/macros/remove_parens.h + googleurl-override/base/macros/uniquify.h + googleurl-override/base/memory/raw_ptr_exclusion.h + googleurl-override/base/memory/ref_counted.cc + googleurl-override/base/memory/ref_counted.h + googleurl-override/base/memory/scoped_refptr.h + googleurl-override/base/threading/platform_thread.cc + googleurl-override/base/threading/platform_thread.h + googleurl-override/base/threading/thread_collision_warner.cc + googleurl-override/base/threading/thread_collision_warner.h + googleurl-override/base/rand_util.h + googleurl-override/base/rand_util.cc + googleurl-override/polyfills/base/logging.h + googleurl-override/polyfills/base/check.h + googleurl-override/polyfills/base/check.cc + googleurl-override/polyfills/base/check_op.h + googleurl-override/polyfills/base/check_op.cc ) if (WIN32) @@ -179,9 +202,13 @@ if (WIN32) target_sources(url PRIVATE googleurl/base/strings/string_util_win.h googleurl/base/strings/string_util_win.cc) + + target_sources(url PRIVATE googleurl-override/base/rand_util_win.cc) elseif(NOT APPLE) target_sources(url PRIVATE googleurl/base/strings/sys_string_conversions_posix.cc) + target_sources(url PRIVATE + googleurl-override/base/rand_util_posix.cc) else() target_sources(url PRIVATE googleurl-override/base/apple/scoped_cftyperef.h @@ -191,6 +218,8 @@ else() googleurl-override/base/mac/scoped_ioobject.h googleurl-override/base/strings/sys_string_conversions_apple.mm ) + target_sources(url PRIVATE + googleurl-override/base/rand_util_posix.cc) # missing apple part endif() @@ -250,9 +279,10 @@ if (USE_LTO_CMAKE) endif() target_include_directories(url PUBLIC + googleurl-override/polyfills googleurl-override - googleurl googleurl/polyfills + googleurl ${CMAKE_CURRENT_SOURCE_DIR}/.. ) diff --git a/yass/src/core/atomic_ref_count.hpp b/yass/third_party/googleurl-override/base/atomic_ref_count.h similarity index 67% rename from yass/src/core/atomic_ref_count.hpp rename to yass/third_party/googleurl-override/base/atomic_ref_count.h index 3f88029a84..44e4c3cadc 100644 --- a/yass/src/core/atomic_ref_count.hpp +++ b/yass/third_party/googleurl-override/base/atomic_ref_count.h @@ -1,15 +1,26 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ +// Copyright 2011 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef CORE_ATOMIC_REF_COUNT_H_ -#define CORE_ATOMIC_REF_COUNT_H_ +// This is a low level implementation of atomic semantics for reference +// counting. Please use base/memory/ref_counted.h directly instead. + +#ifndef BASE_ATOMIC_REF_COUNT_H_ +#define BASE_ATOMIC_REF_COUNT_H_ #include +namespace gurl_base { + +namespace subtle { +class RefCountedOverflowTest; +} // namespace subtle + class AtomicRefCount { public: constexpr AtomicRefCount() : ref_count_(0) {} - explicit constexpr AtomicRefCount(int initial_value) : ref_count_(initial_value) {} + explicit constexpr AtomicRefCount(int initial_value) + : ref_count_(initial_value) {} // Increment a reference count. // Returns the previous value of the count. @@ -17,7 +28,9 @@ class AtomicRefCount { // Increment a reference count by "increment", which must exceed 0. // Returns the previous value of the count. - int Increment(int increment) { return ref_count_.fetch_add(increment, std::memory_order_relaxed); } + int Increment(int increment) { + return ref_count_.fetch_add(increment, std::memory_order_relaxed); + } // Decrement a reference count, and return whether the result is non-zero. // Insert barriers to ensure that state written before the reference count @@ -41,14 +54,22 @@ class AtomicRefCount { // Return whether the reference count is zero. With conventional object // referencing counting, the object will be destroyed, so the reference count // should never be zero. Hence this is generally used for a debug check. - bool IsZero() const { return ref_count_.load(std::memory_order_acquire) == 0; } + bool IsZero() const { + return ref_count_.load(std::memory_order_acquire) == 0; + } // Returns the current reference count (with no barriers). This is subtle, and // should be used only for debugging. - int SubtleRefCountForDebug() const { return ref_count_.load(std::memory_order_relaxed); } + int SubtleRefCountForDebug() const { + return ref_count_.load(std::memory_order_relaxed); + } private: + friend subtle::RefCountedOverflowTest; + std::atomic_int ref_count_; }; +} // namespace base + #endif // BASE_ATOMIC_REF_COUNT_H_ diff --git a/yass/third_party/googleurl-override/base/atomicops.h b/yass/third_party/googleurl-override/base/atomicops.h new file mode 100644 index 0000000000..7f462d6e2f --- /dev/null +++ b/yass/third_party/googleurl-override/base/atomicops.h @@ -0,0 +1,153 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// IMPORTANT NOTE: deprecated. Use std::atomic instead. +// +// Rationale: +// - Uniformity: most of the code uses std::atomic, and the underlying +// implementation is the same. Use the STL one. +// - Clearer code: return values from some operations (e.g. CompareAndSwap) +// differ from the equivalent ones in std::atomic, leading to confusion. +// - Richer semantics: can use actual types, rather than e.g. Atomic32 for a +// boolean flag, or AtomicWord for T*. Bitwise operations (e.g. fetch_or()) +// are only in std::atomic. +// - Harder to misuse: base::subtle::Atomic32 is just an int, making it possible +// to accidentally manipulate, not realizing that there are no atomic +// semantics attached to it. For instance, "Atomic32 a; a++;" is almost +// certainly incorrect. + +// For atomic operations on reference counts, see atomic_refcount.h. +// For atomic operations on sequence numbers, see atomic_sequence_num.h. + +// The routines exported by this module are subtle. If you use them, even if +// you get the code right, it will depend on careful reasoning about atomicity +// and memory ordering; it will be less readable, and harder to maintain. If +// you plan to use these routines, you should have a good reason, such as solid +// evidence that performance would otherwise suffer, or there being no +// alternative. You should assume only properties explicitly guaranteed by the +// specifications in this file. You are almost certainly _not_ writing code +// just for the x86; if you assume x86 semantics, x86 hardware bugs and +// implementations on other archtectures will cause your code to break. If you +// do not know what you are doing, avoid these routines, and use a Mutex. +// +// It is incorrect to make direct assignments to/from an atomic variable. +// You should use one of the Load or Store routines. The NoBarrier +// versions are provided when no barriers are needed: +// NoBarrier_Store() +// NoBarrier_Load() +// Although there are currently no compiler enforcement, you are encouraged +// to use these. +// + +#ifndef BASE_ATOMICOPS_H_ +#define BASE_ATOMICOPS_H_ + +#include + +// Small C++ header which defines implementation specific macros used to +// identify the STL implementation. +// - libc++: captures __config for _LIBCPP_VERSION +// - libstdc++: captures bits/c++config.h for __GLIBCXX__ +#include + +#include "build/build_config.h" + +namespace gurl_base { +namespace subtle { + +typedef int32_t Atomic32; +#ifdef ARCH_CPU_64_BITS +// We need to be able to go between Atomic64 and AtomicWord implicitly. This +// means Atomic64 and AtomicWord should be the same type on 64-bit. +#if defined(__ILP32__) || BUILDFLAG(IS_NACL) +// NaCl's intptr_t is not actually 64-bits on 64-bit! +// http://code.google.com/p/nativeclient/issues/detail?id=1162 +typedef int64_t Atomic64; +#else +typedef intptr_t Atomic64; +#endif +#endif + +// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or +// Atomic64 routines below, depending on your architecture. +typedef intptr_t AtomicWord; + +// Atomically execute: +// result = *ptr; +// if (*ptr == old_value) +// *ptr = new_value; +// return result; +// +// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". +// Always return the old value of "*ptr" +// +// This routine implies no memory barriers. +Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); + +// Atomically increment *ptr by "increment". Returns the new value of +// *ptr with the increment applied. This routine implies no memory barriers. +Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); + +Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment); + +// These following lower-level operations are typically useful only to people +// implementing higher-level synchronization operations like spinlocks, +// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or +// a store with appropriate memory-ordering instructions. "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. +Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); +Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); + +void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); +void Release_Store(volatile Atomic32* ptr, Atomic32 value); + +Atomic32 NoBarrier_Load(volatile const Atomic32* ptr); +Atomic32 Acquire_Load(volatile const Atomic32* ptr); + +// 64-bit atomic operations (only available on 64-bit processors). +#ifdef ARCH_CPU_64_BITS +Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); +Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); +Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); + +Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +void Release_Store(volatile Atomic64* ptr, Atomic64 value); +Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); +Atomic64 Acquire_Load(volatile const Atomic64* ptr); +#endif // ARCH_CPU_64_BITS + +} // namespace subtle +} // namespace gurl_base + +#include "base/atomicops_internals_portable.h" + +// On some platforms we need additional declarations to make +// AtomicWord compatible with our other Atomic* types. +#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_OPENBSD) +#include "base/atomicops_internals_atomicword_compat.h" +#endif + +#endif // BASE_ATOMICOPS_H_ diff --git a/yass/third_party/googleurl-override/base/atomicops_internals_atomicword_compat.h b/yass/third_party/googleurl-override/base/atomicops_internals_atomicword_compat.h new file mode 100644 index 0000000000..983fcf28ee --- /dev/null +++ b/yass/third_party/googleurl-override/base/atomicops_internals_atomicword_compat.h @@ -0,0 +1,94 @@ +// Copyright 2011 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is an internal atomic implementation, use base/atomicops.h instead. + +#ifndef BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ +#define BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ + +#include + +#include "build/build_config.h" + +// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32_t, +// which in turn means int. On some LP32 platforms, intptr_t is an int, but +// on others, it's a long. When AtomicWord and Atomic32 are based on different +// fundamental types, their pointers are incompatible. +// +// This file defines function overloads to allow both AtomicWord and Atomic32 +// data to be used with this interface. +// +// On LP64 platforms, AtomicWord and Atomic64 are both always long, +// so this problem doesn't occur. + +#if !defined(ARCH_CPU_64_BITS) + +namespace gurl_base { +namespace subtle { + +inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return NoBarrier_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return NoBarrier_AtomicExchange( + reinterpret_cast(ptr), new_value); +} + +inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return NoBarrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return Barrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return gurl_base::subtle::Acquire_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return gurl_base::subtle::Release_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { + NoBarrier_Store( + reinterpret_cast(ptr), value); +} + +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { + return gurl_base::subtle::Release_Store( + reinterpret_cast(ptr), value); +} + +inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { + return NoBarrier_Load( + reinterpret_cast(ptr)); +} + +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { + return gurl_base::subtle::Acquire_Load( + reinterpret_cast(ptr)); +} + +} // namespace subtle +} // namespace gurl_base + +#endif // !defined(ARCH_CPU_64_BITS) + +#endif // BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ diff --git a/yass/third_party/googleurl-override/base/atomicops_internals_portable.h b/yass/third_party/googleurl-override/base/atomicops_internals_portable.h new file mode 100644 index 0000000000..903e5a0740 --- /dev/null +++ b/yass/third_party/googleurl-override/base/atomicops_internals_portable.h @@ -0,0 +1,195 @@ +// Copyright 2014 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is an internal atomic implementation, use atomicops.h instead. +// +// This implementation uses C++11 atomics' member functions. The code base is +// currently written assuming atomicity revolves around accesses instead of +// C++11's memory locations. The burden is on the programmer to ensure that all +// memory locations accessed atomically are never accessed non-atomically (tsan +// should help with this). +// +// TODO(jfb) Modify the atomicops.h API and user code to declare atomic +// locations as truly atomic. See the static_assert below. +// +// Of note in this implementation: +// * All NoBarrier variants are implemented as relaxed. +// * All Barrier variants are implemented as sequentially-consistent. +// * Compare exchange's failure ordering is always the same as the success one +// (except for release, which fails as relaxed): using a weaker ordering is +// only valid under certain uses of compare exchange. +// * Atomic increment is expected to return the post-incremented value, whereas +// C11 fetch add returns the previous value. The implementation therefore +// needs to increment twice (which the compiler should be able to detect and +// optimize). + +#ifndef BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ +#define BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ + +#include + +#include "base/numerics/wrapping_math.h" +#include "build/build_config.h" + +namespace gurl_base { +namespace subtle { + +// This implementation is transitional and maintains the original API for +// atomicops.h. This requires casting memory locations to the atomic types, and +// assumes that the API and the C++11 implementation are layout-compatible, +// which isn't true for all implementations or hardware platforms. The static +// assertion should detect this issue, were it to fire then this header +// shouldn't be used. +// +// TODO(jfb) If this header manages to stay committed then the API should be +// modified, and all call sites updated. +typedef volatile std::atomic* AtomicLocation32; +static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32), + "incompatible 32-bit atomic layout"); + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_relaxed, + std::memory_order_relaxed); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return ((AtomicLocation32)ptr) + ->exchange(new_value, std::memory_order_relaxed); +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return gurl_base::WrappingAdd( + ((AtomicLocation32)ptr)->fetch_add(increment, std::memory_order_relaxed), + increment); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return gurl_base::WrappingAdd(((AtomicLocation32)ptr)->fetch_add(increment), + increment); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_acquire, + std::memory_order_acquire); + return old_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_release, + std::memory_order_relaxed); + return old_value; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + ((AtomicLocation32)ptr)->store(value, std::memory_order_release); +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + return ((AtomicLocation32)ptr)->load(std::memory_order_acquire); +} + +#if defined(ARCH_CPU_64_BITS) + +using AtomicU64 = std::make_unsigned_t; + +typedef volatile std::atomic* AtomicLocation64; +static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64), + "incompatible 64-bit atomic layout"); + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_relaxed, + std::memory_order_relaxed); + return old_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return ((AtomicLocation64)ptr) + ->exchange(new_value, std::memory_order_relaxed); +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return gurl_base::WrappingAdd( + ((AtomicLocation64)ptr)->fetch_add(increment, std::memory_order_relaxed), + increment); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return gurl_base::WrappingAdd(((AtomicLocation64)ptr)->fetch_add(increment), + increment); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_acquire, + std::memory_order_acquire); + return old_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_release, + std::memory_order_relaxed); + return old_value; +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + ((AtomicLocation64)ptr)->store(value, std::memory_order_release); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + return ((AtomicLocation64)ptr)->load(std::memory_order_acquire); +} + +#endif // defined(ARCH_CPU_64_BITS) +} // namespace subtle +} // namespace gurl_base + +#endif // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ diff --git a/yass/third_party/googleurl-override/base/dcheck_is_on.h b/yass/third_party/googleurl-override/base/dcheck_is_on.h index 21b81d83d0..23c3e5e554 100644 --- a/yass/third_party/googleurl-override/base/dcheck_is_on.h +++ b/yass/third_party/googleurl-override/base/dcheck_is_on.h @@ -13,4 +13,6 @@ #define EXPENSIVE_DCHECKS_ARE_ON() false +#define GURL_DCHECK_IS_ON() DCHECK_IS_ON() + #endif // POLYFILLS_BASE_DCHECK_IS_ON_H_ diff --git a/yass/third_party/googleurl-override/base/files/memory_mapped_file.cc b/yass/third_party/googleurl-override/base/files/memory_mapped_file.cc index fe6eb0ae2f..9d57494c57 100644 --- a/yass/third_party/googleurl-override/base/files/memory_mapped_file.cc +++ b/yass/third_party/googleurl-override/base/files/memory_mapped_file.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/files/memory_mapped_file.h" +#include "base/check_op.h" #include "base/logging.h" // #include "base/system/sys_info.h" #include "base/numerics/safe_math.h" diff --git a/yass/src/core/immediate_crash.hpp b/yass/third_party/googleurl-override/base/immediate_crash.h similarity index 94% rename from yass/src/core/immediate_crash.hpp rename to yass/third_party/googleurl-override/base/immediate_crash.h index b5693f68dd..76856bcb6a 100644 --- a/yass/src/core/immediate_crash.hpp +++ b/yass/third_party/googleurl-override/base/immediate_crash.h @@ -1,8 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022-2024 Chilledheart */ +// Copyright 2019 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef CORE_IMMEDIATE_CRASH_H -#define CORE_IMMEDIATE_CRASH_H +#ifndef BASE_IMMEDIATE_CRASH_H_ +#define BASE_IMMEDIATE_CRASH_H_ #include @@ -137,11 +138,14 @@ #define IMMEDIATE_CRASH_ALWAYS_INLINE inline #endif +namespace gurl_base { + [[noreturn]] IMMEDIATE_CRASH_ALWAYS_INLINE void ImmediateCrash() { TRAP_SEQUENCE_(); #if defined(__clang__) || defined(COMPILER_GCC) __builtin_unreachable(); #endif // defined(__clang__) || defined(COMPILER_GCC) } +} // namespace gurl_base -#endif // CORE_IMMEDIATE_CRASH_H +#endif // BASE_IMMEDIATE_CRASH_H_ diff --git a/yass/third_party/googleurl-override/base/location.cc b/yass/third_party/googleurl-override/base/location.cc index a30b251854..f3f7bc9c65 100644 --- a/yass/third_party/googleurl-override/base/location.cc +++ b/yass/third_party/googleurl-override/base/location.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/location.h" +#include "base/check.h" +#include "base/check_op.h" #include "base/logging.h" #include "base/compiler_specific.h" #include diff --git a/yass/third_party/googleurl-override/base/macros/concat.h b/yass/third_party/googleurl-override/base/macros/concat.h new file mode 100644 index 0000000000..5909d4e1af --- /dev/null +++ b/yass/third_party/googleurl-override/base/macros/concat.h @@ -0,0 +1,16 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MACROS_CONCAT_H_ +#define BASE_MACROS_CONCAT_H_ + +// A macro that expands to the concatenation of its arguments. If the arguments +// are themselves macros, they are first expanded (due to the indirection +// through a second macro). This can be used to construct tokens. +#define BASE_CONCAT(a, b) BASE_INTERNAL_CONCAT(a, b) + +// Implementation details: do not use directly. +#define BASE_INTERNAL_CONCAT(a, b) a##b + +#endif // BASE_MACROS_CONCAT_H_ diff --git a/yass/third_party/googleurl-override/base/macros/if.h b/yass/third_party/googleurl-override/base/macros/if.h new file mode 100644 index 0000000000..eca40418e4 --- /dev/null +++ b/yass/third_party/googleurl-override/base/macros/if.h @@ -0,0 +1,20 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MACROS_IF_H_ +#define BASE_MACROS_IF_H_ + +#include "base/macros/concat.h" + +// Given a `_Cond` that evaluates to exactly 0 or 1, this macro evaluates to +// either the `_Then` or `_Else` args. Unlike a real conditional expression, +// this does not support conditions other than `0` and `1`. +#define BASE_IF(_Cond, _Then, _Else) \ + BASE_CONCAT(BASE_INTERNAL_IF_, _Cond)(_Then, _Else) + +// Implementation details: do not use directly. +#define BASE_INTERNAL_IF_1(_Then, _Else) _Then +#define BASE_INTERNAL_IF_0(_Then, _Else) _Else + +#endif // BASE_MACROS_IF_H_ diff --git a/yass/third_party/googleurl-override/base/macros/remove_parens.h b/yass/third_party/googleurl-override/base/macros/remove_parens.h new file mode 100644 index 0000000000..cb36da8916 --- /dev/null +++ b/yass/third_party/googleurl-override/base/macros/remove_parens.h @@ -0,0 +1,39 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MACROS_REMOVE_PARENS_H_ +#define BASE_MACROS_REMOVE_PARENS_H_ + +#include "base/macros/if.h" + +// A macro that removes at most one outer set of parentheses from its arguments. +// If the arguments are not surrounded by parentheses, this expands to the +// arguments unchanged. For example: +// `BASE_REMOVE_PARENS()` -> `` +// `BASE_REMOVE_PARENS(foo)` -> `foo` +// `BASE_REMOVE_PARENS(foo(1))` -> `foo(1)` +// `BASE_REMOVE_PARENS((foo))` -> `foo` +// `BASE_REMOVE_PARENS((foo(1)))` -> `foo(1)` +// `BASE_REMOVE_PARENS((foo)[1])` -> `(foo)[1]` +// `BASE_REMOVE_PARENS(((foo)))` -> `(foo)` +// `BASE_REMOVE_PARENS(foo, bar, baz)` -> `foo, bar, baz` +// `BASE_REMOVE_PARENS(foo, (bar), baz)` -> `foo, (bar), baz` +#define BASE_REMOVE_PARENS(...) \ + BASE_IF(BASE_INTERNAL_IS_PARENTHESIZED(__VA_ARGS__), BASE_INTERNAL_ECHO, \ + BASE_INTERNAL_EMPTY()) \ + __VA_ARGS__ + +#define BASE_INTERNAL_IS_PARENTHESIZED(...) \ + BASE_INTERNAL_IS_EMPTY(BASE_INTERNAL_EAT __VA_ARGS__) +#define BASE_INTERNAL_IS_EMPTY(...) BASE_INTERNAL_IS_EMPTY_EXPANDED(__VA_ARGS__) +#define BASE_INTERNAL_IS_EMPTY_EXPANDED(...) \ + BASE_INTERNAL_IS_EMPTY_INNER(_, ##__VA_ARGS__) +#define BASE_INTERNAL_IS_EMPTY_INNER(...) \ + BASE_INTERNAL_IS_EMPTY_INNER_EXPANDED(__VA_ARGS__, 0, 1) +#define BASE_INTERNAL_IS_EMPTY_INNER_EXPANDED(e0, e1, is_empty, ...) is_empty +#define BASE_INTERNAL_EAT(...) +#define BASE_INTERNAL_ECHO(...) __VA_ARGS__ +#define BASE_INTERNAL_EMPTY() + +#endif // BASE_MACROS_REMOVE_PARENS_H_ diff --git a/yass/third_party/googleurl-override/base/macros/uniquify.h b/yass/third_party/googleurl-override/base/macros/uniquify.h new file mode 100644 index 0000000000..4e72364017 --- /dev/null +++ b/yass/third_party/googleurl-override/base/macros/uniquify.h @@ -0,0 +1,15 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MACROS_UNIQUIFY_H_ +#define BASE_MACROS_UNIQUIFY_H_ + +#include "base/macros/concat.h" + +// A macro to create a "unique" token name beginning with `name` by appending +// the current line number. This is generally used inside other macros that need +// to create temporaries while minimizing the likelihood of name conflicts. +#define BASE_UNIQUIFY(name) BASE_CONCAT(name, __LINE__) + +#endif // BASE_MACROS_UNIQUIFY_H_ diff --git a/yass/third_party/googleurl-override/base/memory/raw_ptr_exclusion.h b/yass/third_party/googleurl-override/base/memory/raw_ptr_exclusion.h new file mode 100644 index 0000000000..0d884bd4cc --- /dev/null +++ b/yass/third_party/googleurl-override/base/memory/raw_ptr_exclusion.h @@ -0,0 +1,14 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_RAW_PTR_EXCLUSION_H_ +#define BASE_MEMORY_RAW_PTR_EXCLUSION_H_ + +// Although `raw_ptr` is part of the standalone PA distribution, it is +// easier to use the shorter path in `//base/memory`. We retain this +// facade header for ease of typing. +// #include "base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_exclusion.h" // IWYU pragma: export +#define RAW_PTR_EXCLUSION + +#endif // BASE_MEMORY_RAW_PTR_EXCLUSION_H_ diff --git a/yass/src/core/ref_counted.cpp b/yass/third_party/googleurl-override/base/memory/ref_counted.cc similarity index 78% rename from yass/src/core/ref_counted.cpp rename to yass/third_party/googleurl-override/base/memory/ref_counted.cc index c549ac2c8b..81d5232ddd 100644 --- a/yass/src/core/ref_counted.cpp +++ b/yass/third_party/googleurl-override/base/memory/ref_counted.cc @@ -1,19 +1,20 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ +// Copyright 2011 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#include "core/ref_counted.hpp" +#include "base/memory/ref_counted.h" -#include #include #include #include -#include "core/thread_collision_warner.hpp" +#include "base/threading/thread_collision_warner.h" +namespace gurl_base { namespace { #if DCHECK_IS_ON() -std::atomic g_cross_thread_ref_count_access_allow_count(0); +std::atomic_int g_cross_thread_ref_count_access_allow_count(0); #endif } // namespace @@ -30,8 +31,8 @@ bool RefCountedThreadSafeBase::HasAtLeastOneRef() const { #if DCHECK_IS_ON() RefCountedThreadSafeBase::~RefCountedThreadSafeBase() { - DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without " - "calling Release()"; + GURL_DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without " + "calling Release()"; } #endif @@ -52,7 +53,7 @@ void RefCountedBase::AddRefImpl() const { // // Make sure the addition didn't wrap back around to 0. This form of check // works because we assert that `ref_count_` is an unsigned integer type. - CHECK(++ref_count_ != 0); + GURL_CHECK(++ref_count_ != 0); } void RefCountedBase::ReleaseImpl() const { @@ -63,11 +64,11 @@ void RefCountedBase::ReleaseImpl() const { // // Note that unlike with overflow, underflow could also happen on 32-bit // architectures. Arguably, we should do this check on32-bit machines too. - CHECK(--ref_count_ != std::numeric_limits::max()); + GURL_CHECK(--ref_count_ != std::numeric_limits::max()); } #endif -#if !defined(ARCH_CPU_X86_FAMILY) +#if !(defined(ARCH_CPU_X86_FAMILY) || defined(__ARM_FEATURE_ATOMICS)) bool RefCountedThreadSafeBase::Release() const { return ReleaseImpl(); } @@ -79,12 +80,6 @@ void RefCountedThreadSafeBase::AddRefWithCheck() const { } #endif -#if DCHECK_IS_ON() -bool RefCountedBase::CalledOnValidSequence() const { - return g_cross_thread_ref_count_access_allow_count.load() != 0; -} -#endif - } // namespace subtle #if DCHECK_IS_ON() @@ -96,3 +91,5 @@ ScopedAllowCrossThreadRefCountAccess::~ScopedAllowCrossThreadRefCountAccess() { --g_cross_thread_ref_count_access_allow_count; } #endif + +} // namespace gurl_base diff --git a/yass/src/core/ref_counted.hpp b/yass/third_party/googleurl-override/base/memory/ref_counted.h similarity index 71% rename from yass/src/core/ref_counted.hpp rename to yass/third_party/googleurl-override/base/memory/ref_counted.h index 487795cc14..d79f993ac5 100644 --- a/yass/src/core/ref_counted.hpp +++ b/yass/third_party/googleurl-override/base/memory/ref_counted.h @@ -1,25 +1,31 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef CORE_REF_COUNTED_H_ -#define CORE_REF_COUNTED_H_ +#ifndef BASE_MEMORY_REF_COUNTED_H_ +#define BASE_MEMORY_REF_COUNTED_H_ #include + +#include #include -#include "core/atomic_ref_count.hpp" -#include "core/check_op.hpp" -#include "core/scoped_refptr.hpp" -#include "core/thread_collision_warner.hpp" - -#include -#include -#include -#include +#include "base/atomic_ref_count.h" +#include "base/base_export.h" +#include "base/check.h" +#include "base/check_op.h" +#include "base/compiler_specific.h" +#include "base/dcheck_is_on.h" +#include "base/memory/scoped_refptr.h" +#include "base/template_util.h" +#include "base/threading/thread_collision_warner.h" +#include "build/build_config.h" +#include "third_party/abseil-cpp/absl/utility/utility.h" +namespace gurl_base { namespace subtle { -class RefCountedBase { +class BASE_EXPORT RefCountedBase { public: RefCountedBase(const RefCountedBase&) = delete; RefCountedBase& operator=(const RefCountedBase&) = delete; @@ -28,7 +34,8 @@ class RefCountedBase { bool HasAtLeastOneRef() const { return ref_count_ >= 1; } protected: - explicit RefCountedBase(StartRefCountFromZeroTag) {} + explicit RefCountedBase(StartRefCountFromZeroTag) { + } explicit RefCountedBase(StartRefCountFromOneTag) : ref_count_(1) { #if DCHECK_IS_ON() @@ -39,20 +46,17 @@ class RefCountedBase { ~RefCountedBase() { #if DCHECK_IS_ON() // RefCounted object deleted without calling Release() - DCHECK(in_dtor_); + GURL_DCHECK(in_dtor_); #endif } void AddRef() const { #if DCHECK_IS_ON() - DCHECK(!in_dtor_); + GURL_DCHECK(!in_dtor_); // This RefCounted object is created with non-zero reference count. // The first reference to such a object has to be made by AdoptRef or // MakeRefCounted. - DCHECK(!needs_adopt_ref_); - if (ref_count_ >= 1) { - DCHECK(CalledOnValidSequence()); - } + GURL_DCHECK(!needs_adopt_ref_); #endif AddRefImpl(); @@ -63,12 +67,9 @@ class RefCountedBase { ReleaseImpl(); #if DCHECK_IS_ON() - DCHECK(!in_dtor_); + GURL_DCHECK(!in_dtor_); if (ref_count_ == 0) in_dtor_ = true; - - if (ref_count_ >= 1) - DCHECK(CalledOnValidSequence()); #endif return ref_count_ == 0; @@ -88,22 +89,18 @@ class RefCountedBase { // reference, or if the object is accessed from multiple threads // simultaneously. bool IsOnValidSequence() const { -#if DCHECK_IS_ON() - return ref_count_ <= 1 || CalledOnValidSequence(); -#else return true; -#endif } private: template - friend scoped_refptr AdoptRef(U*); + friend scoped_refptr gurl_base::AdoptRef(U*); - FRIEND_TEST_ALL_PREFIXES(RefCountedDeathTest, TestOverflowCheck); + friend class RefCountedOverflowTest; void Adopted() const { #if DCHECK_IS_ON() - DCHECK(needs_adopt_ref_); + GURL_DCHECK(needs_adopt_ref_); needs_adopt_ref_ = false; #endif } @@ -116,12 +113,9 @@ class RefCountedBase { void ReleaseImpl() const { --ref_count_; } #endif -#if DCHECK_IS_ON() - bool CalledOnValidSequence() const; -#endif - mutable uint32_t ref_count_ = 0; - static_assert(std::is_unsigned::value, "ref_count_ must be an unsigned type."); + static_assert(std::is_unsigned_v, + "ref_count_ must be an unsigned type."); #if DCHECK_IS_ON() mutable bool needs_adopt_ref_ = false; @@ -131,7 +125,7 @@ class RefCountedBase { DFAKE_MUTEX(add_release_); }; -class RefCountedThreadSafeBase { +class BASE_EXPORT RefCountedThreadSafeBase { public: RefCountedThreadSafeBase(const RefCountedThreadSafeBase&) = delete; RefCountedThreadSafeBase& operator=(const RefCountedThreadSafeBase&) = delete; @@ -141,7 +135,8 @@ class RefCountedThreadSafeBase { protected: explicit constexpr RefCountedThreadSafeBase(StartRefCountFromZeroTag) {} - explicit constexpr RefCountedThreadSafeBase(StartRefCountFromOneTag) : ref_count_(1) { + explicit constexpr RefCountedThreadSafeBase(StartRefCountFromOneTag) + : ref_count_(1) { #if DCHECK_IS_ON() needs_adopt_ref_ = true; #endif @@ -154,9 +149,15 @@ class RefCountedThreadSafeBase { #endif // Release and AddRef are suitable for inlining on X86 because they generate -// very small code sequences. On other platforms (ARM), it causes a size -// regression and is probably not worth it. -#if defined(ARCH_CPU_X86_FAMILY) +// very small code sequences. +// +// ARM64 devices supporting ARMv8.1-A atomic instructions generate very little +// code, e.g. fetch_add() with acquire ordering is a single instruction (ldadd), +// vs LL/SC in previous ARM architectures. Inline it there as well. +// +// On other platforms (e.g. ARM), it causes a size regression and is probably +// not worth it. +#if defined(ARCH_CPU_X86_FAMILY) || defined(__ARM_FEATURE_ATOMICS) // Returns true if the object should self-delete. bool Release() const { return ReleaseImpl(); } void AddRef() const { AddRefImpl(); } @@ -170,41 +171,45 @@ class RefCountedThreadSafeBase { private: template - friend scoped_refptr AdoptRef(U*); + friend scoped_refptr gurl_base::AdoptRef(U*); + + friend class RefCountedOverflowTest; void Adopted() const { #if DCHECK_IS_ON() - DCHECK(needs_adopt_ref_); + GURL_DCHECK(needs_adopt_ref_); needs_adopt_ref_ = false; #endif } ALWAYS_INLINE void AddRefImpl() const { #if DCHECK_IS_ON() - DCHECK(!in_dtor_); + GURL_DCHECK(!in_dtor_); // This RefCounted object is created with non-zero reference count. // The first reference to such a object has to be made by AdoptRef or // MakeRefCounted. - DCHECK(!needs_adopt_ref_); + GURL_DCHECK(!needs_adopt_ref_); #endif - ref_count_.Increment(); + GURL_CHECK_NE(ref_count_.Increment(), std::numeric_limits::max()); } ALWAYS_INLINE void AddRefWithCheckImpl() const { #if DCHECK_IS_ON() - DCHECK(!in_dtor_); + GURL_DCHECK(!in_dtor_); // This RefCounted object is created with non-zero reference count. // The first reference to such a object has to be made by AdoptRef or // MakeRefCounted. - DCHECK(!needs_adopt_ref_); + GURL_DCHECK(!needs_adopt_ref_); #endif - CHECK_GT(ref_count_.Increment(), 0); + int pre_increment_count = ref_count_.Increment(); + GURL_DCHECK_GT(pre_increment_count, 0); + GURL_CHECK_NE(pre_increment_count, std::numeric_limits::max()); } ALWAYS_INLINE bool ReleaseImpl() const { #if DCHECK_IS_ON() - DCHECK(!in_dtor_); - DCHECK(!ref_count_.IsZero()); + GURL_DCHECK(!in_dtor_); + GURL_DCHECK(!ref_count_.IsZero()); #endif if (!ref_count_.Decrement()) { #if DCHECK_IS_ON() @@ -234,7 +239,7 @@ class RefCountedThreadSafeBase { // should properly std::move() the ref to avoid hitting this check). // TODO(tzik): Cleanup existing use cases and remove // ScopedAllowCrossThreadRefCountAccess. -class ScopedAllowCrossThreadRefCountAccess final { +class BASE_EXPORT ScopedAllowCrossThreadRefCountAccess final { public: #if DCHECK_IS_ON() ScopedAllowCrossThreadRefCountAccess(); @@ -250,10 +255,10 @@ class ScopedAllowCrossThreadRefCountAccess final { // knock-off of WebKit's RefCounted class. To use this, just extend your // class from it like so: // -// class MyFoo : public RefCounted { +// class MyFoo : public gurl_base::RefCounted { // ... // private: -// friend class RefCounted; +// friend class gurl_base::RefCounted; // ~MyFoo(); // }; // @@ -277,8 +282,8 @@ class ScopedAllowCrossThreadRefCountAccess final { // the ref counted class to opt-in. // // If an object has start-from-one ref count, the first scoped_refptr need to be -// created by AdoptRef() or MakeRefCounted(). We can use -// MakeRefCounted() to create create both type of ref counted object. +// created by gurl_base::AdoptRef() or gurl_base::MakeRefCounted(). We can use +// gurl_base::MakeRefCounted() to create create both type of ref counted object. // // The motivations to use start-from-one ref count are: // - Start-from-one ref count doesn't need the ref count increment for the @@ -289,30 +294,34 @@ class ScopedAllowCrossThreadRefCountAccess final { // TODO(tzik): Implement invalid acquisition detection. // - Behavior parity to Blink's WTF::RefCounted, whose count starts from one. // And start-from-one ref count is a step to merge WTF::RefCounted into -// RefCounted. +// gurl_base::RefCounted. // #define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() \ - static constexpr ::subtle::StartRefCountFromOneTag kRefCountPreference = ::subtle::kStartRefCountFromOneTag + using RefCountPreferenceTag = ::gurl_base::subtle::StartRefCountFromOneTag template class RefCounted; template struct DefaultRefCountedTraits { - static void Destruct(const T* x) { RefCounted::DeleteInternal(x); } + static void Destruct(const T* x) { + RefCounted::DeleteInternal(x); + } }; template > class RefCounted : public subtle::RefCountedBase { public: - static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference = subtle::kStartRefCountFromZeroTag; + using RefCountPreferenceTag = subtle::StartRefCountFromZeroTag; - RefCounted() : subtle::RefCountedBase(T::kRefCountPreference) {} + RefCounted() : subtle::RefCountedBase(subtle::GetRefCountPreference()) {} RefCounted(const RefCounted&) = delete; RefCounted& operator=(const RefCounted&) = delete; - void AddRef() const { subtle::RefCountedBase::AddRef(); } + void AddRef() const { + subtle::RefCountedBase::AddRef(); + } void Release() const { if (subtle::RefCountedBase::Release()) { @@ -337,47 +346,48 @@ class RefCounted : public subtle::RefCountedBase { }; // Forward declaration. -template -class RefCountedThreadSafe; +template class RefCountedThreadSafe; // Default traits for RefCountedThreadSafe. Deletes the object when its ref // count reaches 0. Overload to delete it on a different thread etc. -template +template struct DefaultRefCountedThreadSafeTraits { static void Destruct(const T* x) { // Delete through RefCountedThreadSafe to make child classes only need to be // friend with RefCountedThreadSafe instead of this struct, which is an // implementation detail. - RefCountedThreadSafe::DeleteInternal(x); + RefCountedThreadSafe::DeleteInternal(x); } }; // // A thread-safe variant of RefCounted // -// class MyFoo : public RefCountedThreadSafe { +// class MyFoo : public gurl_base::RefCountedThreadSafe { // ... // }; // // If you're using the default trait, then you should add compile time // asserts that no one else is deleting your object. i.e. // private: -// friend class RefCountedThreadSafe; +// friend class gurl_base::RefCountedThreadSafe; // ~MyFoo(); // // We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe // too. See the comment above the RefCounted definition for details. -template > +template > class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { public: - static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference = subtle::kStartRefCountFromZeroTag; + using RefCountPreferenceTag = subtle::StartRefCountFromZeroTag; - explicit RefCountedThreadSafe() : subtle::RefCountedThreadSafeBase(T::kRefCountPreference) {} + explicit RefCountedThreadSafe() + : subtle::RefCountedThreadSafeBase(subtle::GetRefCountPreference()) {} RefCountedThreadSafe(const RefCountedThreadSafe&) = delete; RefCountedThreadSafe& operator=(const RefCountedThreadSafe&) = delete; - void AddRef() const { AddRefImpl(T::kRefCountPreference); } + void AddRef() const { AddRefImpl(subtle::GetRefCountPreference()); } void Release() const { if (subtle::RefCountedThreadSafeBase::Release()) { @@ -396,28 +406,34 @@ class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { delete x; } - void AddRefImpl(subtle::StartRefCountFromZeroTag) const { subtle::RefCountedThreadSafeBase::AddRef(); } + void AddRefImpl(subtle::StartRefCountFromZeroTag) const { + subtle::RefCountedThreadSafeBase::AddRef(); + } - void AddRefImpl(subtle::StartRefCountFromOneTag) const { subtle::RefCountedThreadSafeBase::AddRefWithCheck(); } + void AddRefImpl(subtle::StartRefCountFromOneTag) const { + subtle::RefCountedThreadSafeBase::AddRefWithCheck(); + } }; // // A thread-safe wrapper for some piece of data so we can place other // things in scoped_refptrs<>. // -template -class RefCountedData : public RefCountedThreadSafe> { +template +class RefCountedData + : public gurl_base::RefCountedThreadSafe< gurl_base::RefCountedData > { public: RefCountedData() : data() {} RefCountedData(const T& in_value) : data(in_value) {} RefCountedData(T&& in_value) : data(std::move(in_value)) {} template - explicit RefCountedData(std::in_place_t, Args&&... args) : data(std::forward(args)...) {} + explicit RefCountedData(absl::in_place_t, Args&&... args) + : data(std::forward(args)...) {} T data; private: - friend class RefCountedThreadSafe>; + friend class gurl_base::RefCountedThreadSafe >; ~RefCountedData() = default; }; @@ -431,4 +447,6 @@ bool operator!=(const RefCountedData& lhs, const RefCountedData& rhs) { return !(lhs == rhs); } -#endif // CORE_REF_COUNTED_H_ +} // namespace gurl_base + +#endif // BASE_MEMORY_REF_COUNTED_H_ diff --git a/yass/src/core/scoped_refptr.hpp b/yass/third_party/googleurl-override/base/memory/scoped_refptr.h similarity index 68% rename from yass/src/core/scoped_refptr.hpp rename to yass/third_party/googleurl-override/base/memory/scoped_refptr.h index 1ce5575a32..21eefb63a6 100644 --- a/yass/src/core/scoped_refptr.hpp +++ b/yass/third_party/googleurl-override/base/memory/scoped_refptr.h @@ -1,8 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ +// Copyright 2017 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef CORE_MEMORY_SCOPED_REFPTR_H_ -#define CORE_MEMORY_SCOPED_REFPTR_H_ +#ifndef BASE_MEMORY_SCOPED_REFPTR_H_ +#define BASE_MEMORY_SCOPED_REFPTR_H_ #include @@ -10,50 +11,105 @@ #include #include -#include -#include "core/check.hpp" +#include "base/check.h" +#include "base/compiler_specific.h" +#include "base/memory/raw_ptr_exclusion.h" template class scoped_refptr; +namespace gurl_base { + template class RefCounted; template class RefCountedThreadSafe; +template +class RefCountedDeleteOnSequence; class SequencedTaskRunner; -class WrappedPromise; template scoped_refptr AdoptRef(T* t); -namespace internal { - -class BasePromise; - -} // namespace internal - namespace subtle { enum AdoptRefTag { kAdoptRefTag }; enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag }; enum StartRefCountFromOneTag { kStartRefCountFromOneTag }; +template +struct RefCountPreferenceTagTraits; + +template <> +struct RefCountPreferenceTagTraits { + static constexpr StartRefCountFromZeroTag kTag = kStartRefCountFromZeroTag; +}; + +template <> +struct RefCountPreferenceTagTraits { + static constexpr StartRefCountFromOneTag kTag = kStartRefCountFromOneTag; +}; + +template +constexpr Tag GetRefCountPreference() { + return RefCountPreferenceTagTraits::kTag; +} + +// scoped_refptr is typically used with one of several RefCounted base +// classes or with custom AddRef and Release methods. These overloads dispatch +// on which was used. + template -constexpr bool IsRefCountPreferenceOverridden(const T*, const RefCounted*) { - return !std::is_same, - std::decay_t>::value; +constexpr bool IsRefCountPreferenceOverridden(const T*, + const RefCounted*) { + return !std::is_same_v())>, + std::decay_t())>>; } template -constexpr bool IsRefCountPreferenceOverridden(const T*, const RefCountedThreadSafe*) { - return !std::is_same, - std::decay_t>::value; +constexpr bool IsRefCountPreferenceOverridden( + const T*, + const RefCountedThreadSafe*) { + return !std::is_same_v())>, + std::decay_t())>>; +} + +template +constexpr bool IsRefCountPreferenceOverridden( + const T*, + const RefCountedDeleteOnSequence*) { + return !std::is_same_v())>, + std::decay_t())>>; } constexpr bool IsRefCountPreferenceOverridden(...) { return false; } +template +constexpr void AssertRefCountBaseMatches(const T*, const RefCounted*) { + static_assert(std::is_base_of_v, + "T implements RefCounted, but U is not a base of T."); +} + +template +constexpr void AssertRefCountBaseMatches(const T*, + const RefCountedThreadSafe*) { + static_assert( + std::is_base_of_v, + "T implements RefCountedThreadSafe, but U is not a base of T."); +} + +template +constexpr void AssertRefCountBaseMatches(const T*, + const RefCountedDeleteOnSequence*) { + static_assert( + std::is_base_of_v, + "T implements RefCountedDeleteOnSequence, but U is not a base of T."); +} + +constexpr void AssertRefCountBaseMatches(...) {} + } // namespace subtle // Creates a scoped_refptr from a raw pointer without incrementing the reference @@ -61,12 +117,12 @@ constexpr bool IsRefCountPreferenceOverridden(...) { // from 1 instead of 0. template scoped_refptr AdoptRef(T* obj) { - using Tag = std::decay_t; - static_assert(std::is_same::value, + using Tag = std::decay_t())>; + static_assert(std::is_same_v, "Use AdoptRef only if the reference count starts from one."); - DCHECK(obj); - DCHECK(obj->HasOneRef()); + GURL_DCHECK(obj); + GURL_DCHECK(obj->HasOneRef()); obj->Adopted(); return scoped_refptr(obj, subtle::kAdoptRefTag); } @@ -90,7 +146,7 @@ scoped_refptr AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) { template scoped_refptr MakeRefCounted(Args&&... args) { T* obj = new T(std::forward(args)...); - return subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference); + return subtle::AdoptRefIfNeeded(obj, subtle::GetRefCountPreference()); } // Takes an instance of T, which is a ref counted type, and wraps the object @@ -100,6 +156,8 @@ scoped_refptr WrapRefCounted(T* t) { return scoped_refptr(t); } +} // namespace gurl_base + // // A smart pointer class for reference counted objects. Use this class instead // of calling AddRef and Release manually on a reference counted object to @@ -175,7 +233,7 @@ class TRIVIAL_ABI scoped_refptr { // Constructs from a raw pointer. Note that this constructor allows implicit // conversion from T* to scoped_refptr which is strongly discouraged. If // you are creating a new ref-counted object please use - // MakeRefCounted() or WrapRefCounted(). Otherwise you + // gurl_base::MakeRefCounted() or gurl_base::WrapRefCounted(). Otherwise you // should move or copy construct from an existing scoped_refptr to the // ref-counted object. scoped_refptr(T* p) : ptr_(p) { @@ -188,7 +246,8 @@ class TRIVIAL_ABI scoped_refptr { scoped_refptr(const scoped_refptr& r) : scoped_refptr(r.ptr_) {} // Copy conversion constructor. - template ::value>::type> + template >> scoped_refptr(const scoped_refptr& r) : scoped_refptr(r.ptr_) {} // Move constructor. This is required in addition to the move conversion @@ -196,13 +255,15 @@ class TRIVIAL_ABI scoped_refptr { scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) { r.ptr_ = nullptr; } // Move conversion constructor. - template ::value>::type> + template >> scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) { r.ptr_ = nullptr; } ~scoped_refptr() { - static_assert(!subtle::IsRefCountPreferenceOverridden(static_cast(nullptr), static_cast(nullptr)), + static_assert(!gurl_base::subtle::IsRefCountPreferenceOverridden( + static_cast(nullptr), static_cast(nullptr)), "It's unsafe to override the ref count preference." " Please remove REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE" " from subclasses."); @@ -213,12 +274,12 @@ class TRIVIAL_ABI scoped_refptr { T* get() const { return ptr_; } T& operator*() const { - DCHECK(ptr_); + GURL_DCHECK(ptr_); return *ptr_; } T* operator->() const { - DCHECK(ptr_); + GURL_DCHECK(ptr_); return ptr_; } @@ -263,19 +324,16 @@ class TRIVIAL_ABI scoped_refptr { } protected: - T* ptr_ = nullptr; + // This field is not a raw_ptr<> because it was filtered by the rewriter for: + // #union, #addr-of, #global-scope + RAW_PTR_EXCLUSION T* ptr_ = nullptr; private: template - friend scoped_refptr AdoptRef(U*); - friend class ::SequencedTaskRunner; + friend scoped_refptr gurl_base::AdoptRef(U*); + friend class ::gurl_base::SequencedTaskRunner; - // Friend access so these classes can use the constructor below as part of a - // binary size optimization. - friend class ::internal::BasePromise; - friend class ::WrappedPromise; - - scoped_refptr(T* p, subtle::AdoptRefTag) : ptr_(p) {} + scoped_refptr(T* p, gurl_base::subtle::AdoptRefTag) : ptr_(p) {} // Friend required for move constructors that set r.ptr_ to null. template @@ -299,12 +357,14 @@ T* scoped_refptr::release() { // static template void scoped_refptr::AddRef(T* ptr) { + gurl_base::subtle::AssertRefCountBaseMatches(ptr, ptr); ptr->AddRef(); } // static template void scoped_refptr::Release(T* ptr) { + gurl_base::subtle::AssertRefCountBaseMatches(ptr, ptr); ptr->Release(); } @@ -358,4 +418,4 @@ void swap(scoped_refptr& lhs, scoped_refptr& rhs) noexcept { lhs.swap(rhs); } -#endif // CORE_MEMORY_SCOPED_REFPTR_H_ +#endif // BASE_MEMORY_SCOPED_REFPTR_H_ diff --git a/yass/third_party/googleurl-override/base/rand_util.cc b/yass/third_party/googleurl-override/base/rand_util.cc new file mode 100644 index 0000000000..a3f08ae3de --- /dev/null +++ b/yass/third_party/googleurl-override/base/rand_util.cc @@ -0,0 +1,180 @@ +// Copyright 2011 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/rand_util.h" + +#include +#include +#include + +#include +#include + +#include "base/check_op.h" +#include "base/strings/string_util.h" + +namespace gurl_base { + +namespace { + +bool g_subsampling_enabled = true; + +} // namespace + +uint64_t RandUint64() { + uint64_t number; + RandBytes(&number, sizeof(number)); + return number; +} + +int RandInt(int min, int max) { + GURL_DCHECK_LE(min, max); + + uint64_t range = static_cast(max) - static_cast(min) + 1; + // |range| is at most UINT_MAX + 1, so the result of RandGenerator(range) + // is at most UINT_MAX. Hence it's safe to cast it from uint64_t to int64_t. + int result = + static_cast(min + static_cast(gurl_base::RandGenerator(range))); + GURL_DCHECK_GE(result, min); + GURL_DCHECK_LE(result, max); + return result; +} + +double RandDouble() { + return BitsToOpenEndedUnitInterval(gurl_base::RandUint64()); +} + +float RandFloat() { + return BitsToOpenEndedUnitIntervalF(gurl_base::RandUint64()); +} + +#if 0 +TimeDelta RandTimeDelta(TimeDelta start, TimeDelta limit) { + // We must have a finite, non-empty, non-reversed interval. + CHECK_LT(start, limit); + CHECK(!start.is_min()); + CHECK(!limit.is_max()); + + const int64_t range = (limit - start).InMicroseconds(); + // Because of the `CHECK_LT()` above, range > 0, so this cast is safe. + const uint64_t delta_us = base::RandGenerator(static_cast(range)); + // ...and because `range` fit in an `int64_t`, so will `delta_us`. + return start + Microseconds(static_cast(delta_us)); +} + +TimeDelta RandTimeDeltaUpTo(TimeDelta limit) { + return RandTimeDelta(TimeDelta(), limit); +} +#endif + +double BitsToOpenEndedUnitInterval(uint64_t bits) { + // We try to get maximum precision by masking out as many bits as will fit + // in the target type's mantissa, and raising it to an appropriate power to + // produce output in the range [0, 1). For IEEE 754 doubles, the mantissa + // is expected to accommodate 53 bits (including the implied bit). + static_assert(std::numeric_limits::radix == 2, + "otherwise use scalbn"); + constexpr int kBits = std::numeric_limits::digits; + return ldexp(bits & ((UINT64_C(1) << kBits) - 1u), -kBits); +} + +float BitsToOpenEndedUnitIntervalF(uint64_t bits) { + // We try to get maximum precision by masking out as many bits as will fit + // in the target type's mantissa, and raising it to an appropriate power to + // produce output in the range [0, 1). For IEEE 754 floats, the mantissa is + // expected to accommodate 12 bits (including the implied bit). + static_assert(std::numeric_limits::radix == 2, "otherwise use scalbn"); + constexpr int kBits = std::numeric_limits::digits; + return ldexpf(bits & ((UINT64_C(1) << kBits) - 1u), -kBits); +} + +uint64_t RandGenerator(uint64_t range) { + GURL_DCHECK_GT(range, 0u); + // We must discard random results above this number, as they would + // make the random generator non-uniform (consider e.g. if + // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice + // as likely as a result of 3 or 4). + uint64_t max_acceptable_value = + (std::numeric_limits::max() / range) * range - 1; + + uint64_t value; + do { + value = gurl_base::RandUint64(); + } while (value > max_acceptable_value); + + return value % range; +} + +std::string RandBytesAsString(size_t length) { + GURL_DCHECK_GT(length, 0u); + std::string result; + RandBytes(WriteInto(&result, length + 1), length); + return result; +} + +std::vector RandBytesAsVector(size_t length) { + std::vector result(length); + if (result.size()) { + RandBytes(result.data(), result.size()); + } + return result; +} + +InsecureRandomGenerator::InsecureRandomGenerator() { + a_ = gurl_base::RandUint64(); + b_ = gurl_base::RandUint64(); +} + +void InsecureRandomGenerator::ReseedForTesting(uint64_t seed) { + a_ = seed; + b_ = seed; +} + +uint64_t InsecureRandomGenerator::RandUint64() { + // Using XorShift128+, which is simple and widely used. See + // https://en.wikipedia.org/wiki/Xorshift#xorshift+ for details. + uint64_t t = a_; + const uint64_t s = b_; + + a_ = s; + t ^= t << 23; + t ^= t >> 17; + t ^= s ^ (s >> 26); + b_ = t; + + return t + s; +} + +uint32_t InsecureRandomGenerator::RandUint32() { + // The generator usually returns an uint64_t, truncate it. + // + // It is noted in this paper (https://arxiv.org/abs/1810.05313) that the + // lowest 32 bits fail some statistical tests from the Big Crush + // suite. Use the higher ones instead. + return this->RandUint64() >> 32; +} + +double InsecureRandomGenerator::RandDouble() { + uint64_t x = RandUint64(); + // From https://vigna.di.unimi.it/xorshift/. + // 53 bits of mantissa, hence the "hexadecimal exponent" 1p-53. + return (x >> 11) * 0x1.0p-53; +} + +MetricsSubSampler::MetricsSubSampler() = default; +bool MetricsSubSampler::ShouldSample(double probability) { + return !g_subsampling_enabled || generator_.RandDouble() < probability; +} + +MetricsSubSampler::ScopedDisableForTesting::ScopedDisableForTesting() { + GURL_DCHECK(g_subsampling_enabled); + g_subsampling_enabled = false; +} + +MetricsSubSampler::ScopedDisableForTesting::~ScopedDisableForTesting() { + GURL_DCHECK(!g_subsampling_enabled); + g_subsampling_enabled = true; +} + +} // namespace base diff --git a/yass/third_party/googleurl-override/base/rand_util.h b/yass/third_party/googleurl-override/base/rand_util.h new file mode 100644 index 0000000000..f2a1e28f0c --- /dev/null +++ b/yass/third_party/googleurl-override/base/rand_util.h @@ -0,0 +1,208 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_RAND_UTIL_H_ +#define BASE_RAND_UTIL_H_ + +#include +#include + +#include +#include +#include + +#include "base/base_export.h" +#include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" +#include "build/build_config.h" + +namespace memory_simulator { +class MemoryHolder; +} + +namespace gurl_base { + +class TimeDelta; + +namespace internal { + +#if BUILDFLAG(IS_ANDROID) +// Sets the implementation of RandBytes according to the corresponding +// base::Feature. Thread safe: allows to switch while RandBytes() is in use. +void ConfigureRandBytesFieldTrial(); +#endif + +// Returns a random double in range [0, 1). For use in allocator shim to avoid +// infinite recursion. Thread-safe. +BASE_EXPORT double RandDoubleAvoidAllocation(); + +} // namespace internal + +// Returns a random number in range [0, UINT64_MAX]. Thread-safe. +BASE_EXPORT uint64_t RandUint64(); + +// Returns a random number between min and max (inclusive). Thread-safe. +// +// TODO(crbug.com/1488681): Change from fully-closed to half-closed (i.e. +// exclude `max`) to parallel other APIs here. +BASE_EXPORT int RandInt(int min, int max); + +// Returns a random number in range [0, range). Thread-safe. +BASE_EXPORT uint64_t RandGenerator(uint64_t range); + +// Returns a random double in range [0, 1). Thread-safe. +BASE_EXPORT double RandDouble(); + +// Returns a random float in range [0, 1). Thread-safe. +BASE_EXPORT float RandFloat(); + +#if 0 +// Returns a random duration in [`start`, `limit`). Thread-safe. +// +// REQUIRES: `start` < `limit` +BASE_EXPORT TimeDelta RandTimeDelta(TimeDelta start, TimeDelta limit); + +// Returns a random duration in [`TimeDelta()`, `limit`). Thread-safe. +// +// REQUIRES: `limit.is_positive()` +BASE_EXPORT TimeDelta RandTimeDeltaUpTo(TimeDelta limit); +#endif + +// Given input |bits|, convert with maximum precision to a double in +// the range [0, 1). Thread-safe. +BASE_EXPORT double BitsToOpenEndedUnitInterval(uint64_t bits); + +// Given input `bits`, convert with maximum precision to a float in the range +// [0, 1). Thread-safe. +BASE_EXPORT float BitsToOpenEndedUnitIntervalF(uint64_t bits); + +// Fills |output_length| bytes of |output| with random data. Thread-safe. +// +// Although implementations are required to use a cryptographically secure +// random number source, code outside of base/ that relies on this should use +// crypto::RandBytes instead to ensure the requirement is easily discoverable. +BASE_EXPORT void RandBytes(void* output, size_t output_length); + +// Creates a vector of `length` bytes, fills it with random data, and returns +// it. Thread-safe. +// +// Although implementations are required to use a cryptographically secure +// random number source, code outside of base/ that relies on this should use +// crypto::RandBytes instead to ensure the requirement is easily discoverable. +BASE_EXPORT std::vector RandBytesAsVector(size_t length); + +// DEPRECATED. Prefert RandBytesAsVector() above. +// Fills a string of length |length| with random data and returns it. +// |length| should be nonzero. Thread-safe. +// +// Note that this is a variation of |RandBytes| with a different return type. +// The returned string is likely not ASCII/UTF-8. Use with care. +// +// Although implementations are required to use a cryptographically secure +// random number source, code outside of base/ that relies on this should use +// crypto::RandBytes instead to ensure the requirement is easily discoverable. +BASE_EXPORT std::string RandBytesAsString(size_t length); + +// An STL UniformRandomBitGenerator backed by RandUint64. +class RandomBitGenerator { + public: + using result_type = uint64_t; + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return UINT64_MAX; } + result_type operator()() const { return RandUint64(); } + + RandomBitGenerator() = default; + ~RandomBitGenerator() = default; +}; + +// Shuffles [first, last) randomly. Thread-safe. +template +void RandomShuffle(Itr first, Itr last) { + std::shuffle(first, last, RandomBitGenerator()); +} + +#if BUILDFLAG(IS_POSIX) +BASE_EXPORT int GetUrandomFD(); +#endif + +class MetricsSubSampler; + +// Fast, insecure pseudo-random number generator. +// +// WARNING: This is not the generator you are looking for. This has significant +// caveats: +// - It is non-cryptographic, so easy to miuse +// - It is neither fork() nor clone()-safe. +// - Synchronization is up to the client. +// +// Always prefer base::Rand*() above, unless you have a use case where its +// overhead is too high, or system calls are disallowed. +// +// Performance: As of 2021, rough overhead on Linux on a desktop machine of +// base::RandUint64() is ~800ns per call (it performs a system call). On Windows +// it is lower. On the same machine, this generator's cost is ~2ns per call, +// regardless of platform. +// +// This is different from |Rand*()| above as it is guaranteed to never make a +// system call to generate a new number, except to seed it. This should *never* +// be used for cryptographic applications, and is not thread-safe. +// +// It is seeded using base::RandUint64() in the constructor, meaning that it +// doesn't need to be seeded. It can be re-seeded though, with +// ReseedForTesting(). Its period is long enough that it should not need to be +// re-seeded during use. +// +// Uses the XorShift128+ generator under the hood. +class BASE_EXPORT InsecureRandomGenerator { + public: + // Never use outside testing, not enough entropy. + void ReseedForTesting(uint64_t seed); + + uint32_t RandUint32(); + uint64_t RandUint64(); + // In [0, 1). + double RandDouble(); + + private: + InsecureRandomGenerator(); + // State. + uint64_t a_ = 0, b_ = 0; + + // Before adding a new friend class, make sure that the overhead of + // base::Rand*() is too high, using something more representative than a + // microbenchmark. + + // Uses the generator to fill memory pages with random content to make them + // hard to compress, in a simulation tool not bundled with Chrome. CPU + // overhead must be minimized to correctly measure memory effects. + friend class memory_simulator::MemoryHolder; + // Uses the generator to sub-sample metrics. + friend class MetricsSubSampler; + + FRIEND_TEST_ALL_PREFIXES(RandUtilTest, + InsecureRandomGeneratorProducesBothValuesOfAllBits); + FRIEND_TEST_ALL_PREFIXES(RandUtilTest, InsecureRandomGeneratorChiSquared); + FRIEND_TEST_ALL_PREFIXES(RandUtilTest, InsecureRandomGeneratorRandDouble); + FRIEND_TEST_ALL_PREFIXES(RandUtilPerfTest, InsecureRandomRandUint64); +}; + +class BASE_EXPORT MetricsSubSampler { + public: + MetricsSubSampler(); + bool ShouldSample(double probability); + + // Disables subsampling in a scope. Useful for testing. + class BASE_EXPORT ScopedDisableForTesting { + public: + ScopedDisableForTesting(); + ~ScopedDisableForTesting(); + }; + + private: + InsecureRandomGenerator generator_; +}; + +} // namespace gurl_base + +#endif // BASE_RAND_UTIL_H_ diff --git a/yass/third_party/googleurl-override/base/rand_util_posix.cc b/yass/third_party/googleurl-override/base/rand_util_posix.cc new file mode 100644 index 0000000000..094566a000 --- /dev/null +++ b/yass/third_party/googleurl-override/base/rand_util_posix.cc @@ -0,0 +1,215 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/rand_util.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "base/check.h" +#include "base/compiler_specific.h" +#include "base/feature_list.h" +#include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" +#include "base/posix/eintr_wrapper.h" +#include "build/build_config.h" + +#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && !BUILDFLAG(IS_NACL) +#include "third_party/lss/linux_syscall_support.h" +#elif BUILDFLAG(IS_MAC) +// TODO(crbug.com/995996): Waiting for this header to appear in the iOS SDK. +// (See below.) +#include +#endif + +namespace gurl_base { + +namespace { + +// TODO: move to file_utils.cpp +static bool ReadFromFD(int fd, char* buffer, size_t bytes); + +bool ReadFromFD(int fd, char* buffer, size_t bytes) { + size_t total_read = 0; + while (total_read < bytes) { + ssize_t bytes_read = HANDLE_EINTR(read(fd, buffer + total_read, bytes - total_read)); + if (bytes_read <= 0) + break; + total_read += bytes_read; + } + return total_read == bytes; +} + +#if BUILDFLAG(IS_AIX) +// AIX has no 64-bit support for O_CLOEXEC. +static constexpr int kOpenFlags = O_RDONLY; +#else +static constexpr int kOpenFlags = O_RDONLY | O_CLOEXEC; +#endif + +// We keep the file descriptor for /dev/urandom around so we don't need to +// reopen it (which is expensive), and since we may not even be able to reopen +// it if we are later put in a sandbox. This class wraps the file descriptor so +// we can use a static-local variable to handle opening it on the first access. +class URandomFd { + public: + URandomFd() : fd_(HANDLE_EINTR(open("/dev/urandom", kOpenFlags))) { + GURL_CHECK(fd_ >= 0) << "Cannot open /dev/urandom"; + } + + ~URandomFd() { close(fd_); } + + int fd() const { return fd_; } + + private: + const int fd_; +}; + +#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ + BUILDFLAG(IS_ANDROID)) && \ + !BUILDFLAG(IS_NACL) +// TODO(pasko): Unify reading kernel version numbers in: +// mojo/core/channel_linux.cc +// chrome/browser/android/seccomp_support_detector.cc +void KernelVersionNumbers(int32_t* major_version, + int32_t* minor_version, + int32_t* bugfix_version) { + struct utsname info; + if (uname(&info) < 0) { + GURL_NOTREACHED(); + *major_version = 0; + *minor_version = 0; + *bugfix_version = 0; + return; + } + int num_read = sscanf(info.release, "%d.%d.%d", major_version, minor_version, + bugfix_version); + if (num_read < 1) + *major_version = 0; + if (num_read < 2) + *minor_version = 0; + if (num_read < 3) + *bugfix_version = 0; +} + +bool KernelSupportsGetRandom() { + int32_t major = 0; + int32_t minor = 0; + int32_t bugfix = 0; + KernelVersionNumbers(&major, &minor, &bugfix); + if (major > 3 || (major == 3 && minor >= 17)) + return true; + return false; +} + +bool GetRandomSyscall(void* output, size_t output_length) { + // We have to call `getrandom` via Linux Syscall Support, rather than through + // the libc wrapper, because we might not have an up-to-date libc (e.g. on + // some bots). + const ssize_t r = + HANDLE_EINTR(syscall(__NR_getrandom, output, output_length, 0)); + + // Return success only on total success. In case errno == ENOSYS (or any other + // error), we'll fall through to reading from urandom below. + if (output_length == static_cast(r)) { + MSAN_UNPOISON(output, output_length); + return true; + } + return false; +} +#endif // (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || + // BUILDFLAG(IS_ANDROID)) && !BUILDFLAG(IS_NACL) + +#if BUILDFLAG(IS_ANDROID) +std::atomic g_use_getrandom; + +// Note: the BoringSSL feature takes precedence over the getrandom() trial if +// both are enabled. +BASE_FEATURE(kUseGetrandomForRandBytes, + "UseGetrandomForRandBytes", + FEATURE_ENABLED_BY_DEFAULT); + +bool UseGetrandom() { + return g_use_getrandom.load(std::memory_order_relaxed); +} +#elif (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && !BUILDFLAG(IS_NACL) +bool UseGetrandom() { + return true; +} +#endif + +} // namespace + +namespace internal { + +#if BUILDFLAG(IS_ANDROID) +void ConfigureRandBytesFieldTrial() { + g_use_getrandom.store(FeatureList::IsEnabled(kUseGetrandomForRandBytes), + std::memory_order_relaxed); +} +#endif + +} // namespace internal + +namespace { + +void RandBytes(void* output, size_t output_length, bool avoid_allocation) { +#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ + BUILDFLAG(IS_ANDROID)) && \ + !BUILDFLAG(IS_NACL) + if (avoid_allocation || UseGetrandom()) { + // On Android it is mandatory to check that the kernel _version_ has the + // support for a syscall before calling. The same check is made on Linux and + // ChromeOS to avoid making a syscall that predictably returns ENOSYS. + static const bool kernel_has_support = KernelSupportsGetRandom(); + if (kernel_has_support && GetRandomSyscall(output, output_length)) + return; + } +#elif BUILDFLAG(IS_MAC) + // TODO(crbug.com/995996): Enable this on iOS too, when sys/random.h arrives + // in its SDK. + if (getentropy(output, output_length) == 0) { + return; + } +#endif + + // If the OS-specific mechanisms didn't work, fall through to reading from + // urandom. + // + // TODO(crbug.com/995996): When we no longer need to support old Linux + // kernels, we can get rid of this /dev/urandom branch altogether. + const int urandom_fd = GetUrandomFD(); + const bool success = + ReadFromFD(urandom_fd, static_cast(output), output_length); + GURL_CHECK(success); +} + +} // namespace + +namespace internal { + +double RandDoubleAvoidAllocation() { + uint64_t number; + RandBytes(&number, sizeof(number), /*avoid_allocation=*/true); + // This transformation is explained in rand_util.cc. + return (number >> 11) * 0x1.0p-53; +} + +} // namespace internal + +void RandBytes(void* output, size_t output_length) { + RandBytes(output, output_length, /*avoid_allocation=*/false); +} + +int GetUrandomFD() { + static NoDestructor urandom_fd; + return urandom_fd->fd(); +} + +} // namespace gurl_base diff --git a/yass/third_party/googleurl-override/base/rand_util_win.cc b/yass/third_party/googleurl-override/base/rand_util_win.cc new file mode 100644 index 0000000000..91b48df31f --- /dev/null +++ b/yass/third_party/googleurl-override/base/rand_util_win.cc @@ -0,0 +1,79 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/rand_util.h" + +#include + +#include +#include + +#include +#include +#include + +#include "base/check.h" + +// Prototype for ProcessPrng. +// See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng +extern "C" { +BOOL WINAPI ProcessPrng(PBYTE pbData, SIZE_T cbData); +} + +namespace gurl_base { + +namespace { + +decltype(&ProcessPrng) GetProcessPrngFallback() { + HMODULE hmod = LoadLibraryW(L"advapi32"); + GURL_CHECK(hmod); + auto process_prng_fn = + reinterpret_cast( + reinterpret_cast(GetProcAddress(hmod, "SystemFunction036"))); + GURL_CHECK(process_prng_fn); + return process_prng_fn; +} + +// Import bcryptprimitives!ProcessPrng rather than cryptbase!RtlGenRandom to +// avoid opening a handle to \\Device\KsecDD in the renderer. +decltype(&ProcessPrng) GetProcessPrng() { + HMODULE hmod = LoadLibraryW(L"bcryptprimitives.dll"); + if (hmod == nullptr) { + return GetProcessPrngFallback(); + } + auto process_prng_fn = + reinterpret_cast( + reinterpret_cast(GetProcAddress(hmod, "ProcessPrng"))); + if (process_prng_fn == nullptr) { + // Possible on Windows 7 SP1, need fallback as well + return GetProcessPrngFallback(); + } + return process_prng_fn; +} + +void RandBytes(void* output, size_t output_length, bool avoid_allocation) { + static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng(); + BOOL success = process_prng_fn(static_cast(output), output_length); + // ProcessPrng is documented to always return TRUE. + GURL_CHECK(success); +} + +} // namespace + +void RandBytes(void* output, size_t output_length) { + RandBytes(output, output_length, /*avoid_allocation=*/false); +} + +namespace internal { + +double RandDoubleAvoidAllocation() { + uint64_t number; + RandBytes(&number, sizeof(number), /*avoid_allocation=*/true); + // This transformation is explained in rand_util.cc. + return (number >> 11) * 0x1.0p-53; +} + +} // namespace internal + +} // namespace gurl_base diff --git a/yass/third_party/googleurl-override/base/threading/platform_thread.cc b/yass/third_party/googleurl-override/base/threading/platform_thread.cc new file mode 100644 index 0000000000..57e9aae45d --- /dev/null +++ b/yass/third_party/googleurl-override/base/threading/platform_thread.cc @@ -0,0 +1,156 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "base/threading/platform_thread.h" + +#include "base/dcheck_is_on.h" +#include "base/check.h" +#include "base/compiler_specific.h" +#include "build/build_config.h" + +#if BUILDFLAG(IS_WIN) +#include +#endif + +#if BUILDFLAG(IS_POSIX) +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#include +#include +#endif + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +namespace internal { + +void InvalidateTidCache(); + +} // namespace +#endif + +namespace { + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + +// Store the thread ids in local storage since calling the SWI can be +// expensive and PlatformThread::CurrentId is used liberally. +thread_local pid_t g_thread_id = -1; + +// A boolean value that indicates that the value stored in |g_thread_id| on the +// main thread is invalid, because it hasn't been updated since the process +// forked. +// +// This used to work by setting |g_thread_id| to -1 in a pthread_atfork handler. +// However, when a multithreaded process forks, it is only allowed to call +// async-signal-safe functions until it calls an exec() syscall. However, +// accessing TLS may allocate (see crbug.com/1275748), which is not +// async-signal-safe and therefore causes deadlocks, corruption, and crashes. +// +// It's Atomic to placate TSAN. +std::atomic g_main_thread_tid_cache_valid = false; + +// Tracks whether the current thread is the main thread, and therefore whether +// |g_main_thread_tid_cache_valid| is relevant for the current thread. This is +// also updated by PlatformThread::CurrentId(). +thread_local bool g_is_main_thread = true; + +class InitAtFork { + public: + InitAtFork() { + pthread_atfork(nullptr, nullptr, internal::InvalidateTidCache); + } +}; + +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + +} // namespace + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + +namespace internal { + +void InvalidateTidCache() { + g_main_thread_tid_cache_valid.store(false, std::memory_order_relaxed); +} + +} // namespace internal + +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + +namespace gurl_base { + +#if BUILDFLAG(IS_WIN) +// static +PlatformThreadId PlatformThread::CurrentId() { + return ::GetCurrentThreadId(); +} +#else +// static +PlatformThreadId PlatformThread::CurrentId() { + // Pthreads doesn't have the concept of a thread ID, so we have to reach down + // into the kernel. +#if BUILDFLAG(IS_APPLE) + return pthread_mach_thread_np(pthread_self()); +#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + // Workaround false-positive MSAN use-of-uninitialized-value on + // thread_local storage for loaded libraries: + // https://github.com/google/sanitizers/issues/1265 + MSAN_UNPOISON(&g_thread_id, sizeof(pid_t)); + MSAN_UNPOISON(&g_is_main_thread, sizeof(bool)); + static InitAtFork init_at_fork; + if (g_thread_id == -1 || + (g_is_main_thread && + !g_main_thread_tid_cache_valid.load(std::memory_order_relaxed))) { + // Update the cached tid. + g_thread_id = static_cast(syscall(__NR_gettid)); + // If this is the main thread, we can mark the tid_cache as valid. + // Otherwise, stop the current thread from always entering this slow path. + if (g_thread_id == getpid()) { + g_main_thread_tid_cache_valid.store(true, std::memory_order_relaxed); + } else { + g_is_main_thread = false; + } + } else { +#if DCHECK_IS_ON() + if (g_thread_id != syscall(__NR_gettid)) { + RAW_LOG( + FATAL, + "Thread id stored in TLS is different from thread id returned by " + "the system. It is likely that the process was forked without going " + "through fork()."); + } +#endif + } + return g_thread_id; +#elif BUILDFLAG(IS_ANDROID) + // Note: do not cache the return value inside a thread_local variable on + // Android (as above). The reasons are: + // - thread_local is slow on Android (goes through emutls) + // - gettid() is fast, since its return value is cached in pthread (in the + // thread control block of pthread). See gettid.c in bionic. + return gettid(); +#elif BUILDFLAG(IS_FUCHSIA) + return zx_thread_self(); +#elif BUILDFLAG(IS_SOLARIS) || BUILDFLAG(IS_QNX) + return pthread_self(); +#elif BUILDFLAG(IS_NACL) && defined(__GLIBC__) + return pthread_self(); +#elif BUILDFLAG(IS_NACL) && !defined(__GLIBC__) + // Pointers are 32-bits in NaCl. + return reinterpret_cast(pthread_self()); +#elif BUILDFLAG(IS_POSIX) && BUILDFLAG(IS_AIX) + return pthread_self(); +#elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_AIX) + return reinterpret_cast(pthread_self()); +#endif +} +#endif +} // namespace gurl_base diff --git a/yass/third_party/googleurl-override/base/threading/platform_thread.h b/yass/third_party/googleurl-override/base/threading/platform_thread.h new file mode 100644 index 0000000000..0bf4f0bc45 --- /dev/null +++ b/yass/third_party/googleurl-override/base/threading/platform_thread.h @@ -0,0 +1,49 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// WARNING: You should *NOT* be using this class directly. PlatformThread is +// the low-level platform-specific abstraction to the OS's threading interface. +// You should instead be using a message-loop driven Thread, see thread.h. + +#ifndef BASE_THREADING_PLATFORM_THREAD_H_ +#define BASE_THREADING_PLATFORM_THREAD_H_ + +#include + +#include "base/base_export.h" +#include "build/build_config.h" + +#if BUILDFLAG(IS_WIN) +#include "base/win/windows_types.h" +#elif BUILDFLAG(IS_FUCHSIA) +#include +#elif BUILDFLAG(IS_APPLE) +#include +#elif BUILDFLAG(IS_POSIX) +#include +#include +#endif + +namespace gurl_base { +// Used for logging. Always an integer value. +#if BUILDFLAG(IS_WIN) +typedef DWORD PlatformThreadId; +#elif BUILDFLAG(IS_FUCHSIA) +typedef zx_handle_t PlatformThreadId; +#elif BUILDFLAG(IS_APPLE) +typedef mach_port_t PlatformThreadId; +#elif BUILDFLAG(IS_POSIX) +typedef pid_t PlatformThreadId; +#endif +static_assert(std::is_integral_v, "Always an integer value."); + +class BASE_EXPORT PlatformThread { + public: + // Gets the current thread id, which may be useful for logging purposes. + static PlatformThreadId CurrentId(); +}; + +} // namespace gurl_base + +#endif // BASE_THREADING_PLATFORM_THREAD_H_ diff --git a/yass/third_party/googleurl-override/base/threading/thread_collision_warner.cc b/yass/third_party/googleurl-override/base/threading/thread_collision_warner.cc new file mode 100644 index 0000000000..c9ad1c17d4 --- /dev/null +++ b/yass/third_party/googleurl-override/base/threading/thread_collision_warner.cc @@ -0,0 +1,66 @@ +// Copyright 2010 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/thread_collision_warner.h" + +#include + +#include "base/notreached.h" +#include "base/threading/platform_thread.h" + +namespace gurl_base { + +void DCheckAsserter::warn() { + GURL_NOTREACHED() << "Thread Collision"; +} + +static subtle::Atomic32 CurrentThread() { + const PlatformThreadId current_thread_id = PlatformThread::CurrentId(); + // We need to get the thread id into an atomic data type. This might be a + // truncating conversion, but any loss-of-information just increases the + // chance of a fault negative, not a false positive. + const subtle::Atomic32 atomic_thread_id = + static_cast(current_thread_id); + + return atomic_thread_id; +} + +void ThreadCollisionWarner::EnterSelf() { + // If the active thread is 0 then I'll write the current thread ID + // if two or more threads arrive here only one will succeed to + // write on valid_thread_id_ the current thread ID. + subtle::Atomic32 current_thread_id = CurrentThread(); + + int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_, + 0, + current_thread_id); + if (previous_value != 0 && previous_value != current_thread_id) { + // gotcha! a thread is trying to use the same class and that is + // not current thread. + asserter_->warn(); + } + + subtle::NoBarrier_AtomicIncrement(&counter_, 1); +} + +void ThreadCollisionWarner::Enter() { + subtle::Atomic32 current_thread_id = CurrentThread(); + + if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_, + 0, + current_thread_id) != 0) { + // gotcha! another thread is trying to use the same class. + asserter_->warn(); + } + + subtle::NoBarrier_AtomicIncrement(&counter_, 1); +} + +void ThreadCollisionWarner::Leave() { + if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) { + subtle::NoBarrier_Store(&valid_thread_id_, 0); + } +} + +} // namespace base diff --git a/yass/src/core/thread_collision_warner.hpp b/yass/third_party/googleurl-override/base/threading/thread_collision_warner.h similarity index 74% rename from yass/src/core/thread_collision_warner.hpp rename to yass/third_party/googleurl-override/base/threading/thread_collision_warner.h index 6d4f295fa3..03f0d525fe 100644 --- a/yass/src/core/thread_collision_warner.hpp +++ b/yass/third_party/googleurl-override/base/threading/thread_collision_warner.h @@ -1,12 +1,15 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef CORE_THREADING_THREAD_COLLISION_WARNER_H_ -#define CORE_THREADING_THREAD_COLLISION_WARNER_H_ +#ifndef BASE_THREADING_THREAD_COLLISION_WARNER_H_ +#define BASE_THREADING_THREAD_COLLISION_WARNER_H_ -#include - -#include +#include "base/atomicops.h" +#include "base/base_export.h" +#include "base/compiler_specific.h" +#include "base/macros/uniquify.h" +#include "base/memory/raw_ptr.h" // A helper class alongside macros to be used to verify assumptions about thread // safety of a class. @@ -96,23 +99,22 @@ #if !defined(NDEBUG) -#define DFAKE_UNIQUE_VARIABLE_CONCAT(a, b) a##b -// CONCAT1 provides extra level of indirection so that __LINE__ macro expands. -#define DFAKE_UNIQUE_VARIABLE_CONCAT1(a, b) DFAKE_UNIQUE_VARIABLE_CONCAT(a, b) -#define DFAKE_UNIQUE_VARIABLE_NAME(a) DFAKE_UNIQUE_VARIABLE_CONCAT1(a, __LINE__) - // Defines a class member that acts like a mutex. It is used only as a // verification tool. -#define DFAKE_MUTEX(obj) mutable ThreadCollisionWarner obj +#define DFAKE_MUTEX(obj) \ + mutable gurl_base::ThreadCollisionWarner obj // Asserts the call is never called simultaneously in two threads. Used at // member function scope. -#define DFAKE_SCOPED_LOCK(obj) ThreadCollisionWarner::ScopedCheck DFAKE_UNIQUE_VARIABLE_NAME(s_check_)(&obj) +#define DFAKE_SCOPED_LOCK(obj) \ + gurl_base::ThreadCollisionWarner::ScopedCheck BASE_UNIQUIFY(s_check_)(&obj) // Asserts the call is never called simultaneously in two threads. Used at // member function scope. Same as DFAKE_SCOPED_LOCK but allows recursive locks. -#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \ - ThreadCollisionWarner::ScopedRecursiveCheck DFAKE_UNIQUE_VARIABLE_NAME(sr_check)(&obj) +#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \ + gurl_base::ThreadCollisionWarner::ScopedRecursiveCheck BASE_UNIQUIFY(sr_check)( \ + &obj) // Asserts the code is always executed in the same thread. -#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) ThreadCollisionWarner::Check DFAKE_UNIQUE_VARIABLE_NAME(check_)(&obj) +#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) \ + gurl_base::ThreadCollisionWarner::Check BASE_UNIQUIFY(check_)(&obj) #else @@ -123,39 +125,46 @@ #endif +namespace gurl_base { + // The class ThreadCollisionWarner uses an Asserter to notify the collision // AsserterBase is the interfaces and DCheckAsserter is the default asserter // used. During the unit tests is used another class that doesn't "DCHECK" // in case of collision (check thread_collision_warner_unittests.cc) -struct AsserterBase { +struct BASE_EXPORT AsserterBase { virtual ~AsserterBase() = default; virtual void warn() = 0; }; -struct DCheckAsserter : public AsserterBase { +struct BASE_EXPORT DCheckAsserter : public AsserterBase { ~DCheckAsserter() override = default; void warn() override; }; -class ThreadCollisionWarner { +class BASE_EXPORT ThreadCollisionWarner { public: // The parameter asserter is there only for test purpose explicit ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter()) - : valid_thread_id_(0), counter_(0), asserter_(asserter) {} + : valid_thread_id_(0), + counter_(0), + asserter_(asserter) {} ThreadCollisionWarner(const ThreadCollisionWarner&) = delete; ThreadCollisionWarner& operator=(const ThreadCollisionWarner&) = delete; - ~ThreadCollisionWarner() { delete asserter_; } + ~ThreadCollisionWarner() { delete asserter_; asserter_ = nullptr; } // This class is meant to be used through the macro // DFAKE_SCOPED_LOCK_THREAD_LOCKED // it doesn't leave the critical section, as opposed to ScopedCheck, // because the critical section being pinned is allowed to be used only // from one thread - class Check { + class BASE_EXPORT Check { public: - explicit Check(ThreadCollisionWarner* warner) : warner_(warner) { warner_->EnterSelf(); } + explicit Check(ThreadCollisionWarner* warner) + : warner_(warner) { + warner_->EnterSelf(); + } Check(const Check&) = delete; Check& operator=(const Check&) = delete; @@ -163,37 +172,47 @@ class ThreadCollisionWarner { ~Check() = default; private: - ThreadCollisionWarner* warner_; + raw_ptr warner_; }; // This class is meant to be used through the macro // DFAKE_SCOPED_LOCK - class ScopedCheck { + class BASE_EXPORT ScopedCheck { public: - explicit ScopedCheck(ThreadCollisionWarner* warner) : warner_(warner) { warner_->Enter(); } + explicit ScopedCheck(ThreadCollisionWarner* warner) + : warner_(warner) { + warner_->Enter(); + } ScopedCheck(const ScopedCheck&) = delete; ScopedCheck& operator=(const ScopedCheck&) = delete; - ~ScopedCheck() { warner_->Leave(); } + ~ScopedCheck() { + warner_->Leave(); + } private: - ThreadCollisionWarner* warner_; + raw_ptr warner_; }; // This class is meant to be used through the macro // DFAKE_SCOPED_RECURSIVE_LOCK - class ScopedRecursiveCheck { + class BASE_EXPORT ScopedRecursiveCheck { public: - explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner) : warner_(warner) { warner_->EnterSelf(); } + explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner) + : warner_(warner) { + warner_->EnterSelf(); + } ScopedRecursiveCheck(const ScopedRecursiveCheck&) = delete; ScopedRecursiveCheck& operator=(const ScopedRecursiveCheck&) = delete; - ~ScopedRecursiveCheck() { warner_->Leave(); } + ~ScopedRecursiveCheck() { + warner_->Leave(); + } private: - ThreadCollisionWarner* warner_; + raw_ptr warner_; }; private: @@ -211,15 +230,17 @@ class ThreadCollisionWarner { // This stores the thread id that is inside the critical section, if the // value is 0 then no thread is inside. - volatile std::atomic valid_thread_id_; + volatile subtle::Atomic32 valid_thread_id_; // Counter to trace how many time a critical section was "pinned" // (when allowed) in order to unpin it when counter_ reaches 0. - volatile std::atomic counter_; + volatile subtle::Atomic32 counter_; // Here only for class unit tests purpose, during the test I need to not // DCHECK but notify the collision with something else. - AsserterBase* asserter_; + raw_ptr asserter_; }; -#endif // CORE_THREADING_THREAD_COLLISION_WARNER_H_ +} // namespace gurl_base + +#endif // BASE_THREADING_THREAD_COLLISION_WARNER_H_ diff --git a/yass/src/core/check.cpp b/yass/third_party/googleurl-override/polyfills/base/check.cc similarity index 91% rename from yass/src/core/check.cpp rename to yass/third_party/googleurl-override/polyfills/base/check.cc index f432621882..17f35b4d1e 100644 --- a/yass/src/core/check.cpp +++ b/yass/third_party/googleurl-override/polyfills/base/check.cc @@ -1,17 +1,19 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022-2024 Chilledheart */ +// Copyright 2020 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#include "core/check.hpp" +#include "base/check.h" // check.h is a widely included header and its size has significant impact on // build time. Try not to raise this limit unless absolutely necessary. See // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md #pragma clang max_tokens_here 17000 -#include "core/check_op.hpp" -#include "core/logging.hpp" +#include "base/check_op.h" +#include "base/logging.h" -namespace yass { +namespace gurl_base { +namespace logging { CheckError CheckError::Check(const char* file, int line, const char* condition) { CheckError check_error(new LogMessage(file, line, LOGGING_FATAL)); @@ -94,4 +96,5 @@ void RawError(const char* message) { RawLog(LOGGING_ERROR, message); } -} // namespace yass +} // namespace logging +} // namespace gurl_base diff --git a/yass/src/core/check.hpp b/yass/third_party/googleurl-override/polyfills/base/check.h similarity index 72% rename from yass/src/core/check.hpp rename to yass/third_party/googleurl-override/polyfills/base/check.h index 2e7fe5f5be..ceaaa014be 100644 --- a/yass/src/core/check.hpp +++ b/yass/third_party/googleurl-override/polyfills/base/check.h @@ -1,18 +1,21 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ +// Copyright 2020 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef CORE_CHECK_H_ -#define CORE_CHECK_H_ +#ifndef POLYFILLS_BASE_CHECK_H_ +#define POLYFILLS_BASE_CHECK_H_ #include -// Included NOMERGE fix -#include "core/compiler_specific.hpp" -#include "core/immediate_crash.hpp" +#include "polyfills/base/base_export.h" +#include "polyfills/base/logging.h" -#include +#include "base/compiler_specific.h" +#include "base/dcheck_is_on.h" +#include "base/immediate_crash.h" -namespace yass { +namespace gurl_base { +namespace logging { // This header defines the CHECK, DCHECK, and DPCHECK macros. // @@ -52,10 +55,10 @@ class VoidifyStream { // Helper macro which avoids evaluating the arguents to a stream if the // condition is false. -#define LAZY_CHECK_STREAM(stream, condition) !(condition) ? (void)0 : ::yass::VoidifyStream() & (stream) +#define LAZY_CHECK_STREAM(stream, condition) !(condition) ? (void)0 : ::gurl_base::logging::VoidifyStream() & (stream) // Macro which uses but does not evaluate expr and any stream parameters. -#define EAT_CHECK_STREAM_PARAMS(expr) true ? (void)0 : ::yass::VoidifyStream(expr) & (*::yass::g_swallow_stream) +#define EAT_CHECK_STREAM_PARAMS(expr) true ? (void)0 : ::gurl_base::logging::VoidifyStream(expr) & (*::gurl_base::logging::g_swallow_stream) extern std::ostream* g_swallow_stream; @@ -66,10 +69,10 @@ class LogMessage; class CheckError { public: static CheckError Check(const char* file, int line, const char* condition); - static CheckError CheckOp(const char* file, int line, ::yass::CheckOpResult* result); + static CheckError CheckOp(const char* file, int line, ::gurl_base::logging::CheckOpResult* result); static CheckError DCheck(const char* file, int line, const char* condition); - static CheckError DCheckOp(const char* file, int line, ::yass::CheckOpResult* result); + static CheckError DCheckOp(const char* file, int line, ::gurl_base::logging::CheckOpResult* result); static CheckError PCheck(const char* file, int line, const char* condition); static CheckError PCheck(const char* file, int line); @@ -81,7 +84,7 @@ class CheckError { // Stream for adding optional details to the error message. std::ostream& stream(); - NOMERGE NOINLINE NOT_TAIL_CALLED ~CheckError(); + NOINLINE NOT_TAIL_CALLED ~CheckError(); CheckError(const CheckError& other) = delete; CheckError& operator=(const CheckError& other) = delete; @@ -94,26 +97,26 @@ class CheckError { LogMessage* log_message_; }; -#if defined(OFFICIAL_BUILD) && defined(NDEBUG) +#if defined(OFFICIAL_BUILD) && !DCHECK_IS_ON() // Discard log strings to reduce code bloat. // // This is not calling BreakDebugger since this is called frequently, and // calling an out-of-line function instead of a noreturn inline macro prevents // compiler optimizations. -#define CHECK(condition) UNLIKELY(!(condition)) ? ImmediateCrash() : EAT_CHECK_STREAM_PARAMS() +#define CHECK(condition) UNLIKELY(!(condition)) ? ::gurl_base::ImmediateCrash() : EAT_CHECK_STREAM_PARAMS() #define PCHECK(condition) \ - LAZY_CHECK_STREAM(::yass::CheckError::PCheck(__FILE__, __LINE__).stream(), UNLIKELY(!(condition))) + LAZY_CHECK_STREAM(::gurl_base::logging::CheckError::PCheck(__FILE__, __LINE__).stream(), UNLIKELY(!(condition))) #else #define CHECK(condition) \ - LAZY_CHECK_STREAM(::yass::CheckError::Check(__FILE__, __LINE__, #condition).stream(), \ + LAZY_CHECK_STREAM(::gurl_base::logging::CheckError::Check(__FILE__, __LINE__, #condition).stream(), \ !ANALYZER_ASSUME_TRUE(condition)) #define PCHECK(condition) \ - LAZY_CHECK_STREAM(::yass::CheckError::PCheck(__FILE__, __LINE__, #condition).stream(), \ + LAZY_CHECK_STREAM(::gurl_base::logging::CheckError::PCheck(__FILE__, __LINE__, #condition).stream(), \ !ANALYZER_ASSUME_TRUE(condition)) #endif @@ -121,11 +124,11 @@ class CheckError { #if DCHECK_IS_ON() #define DCHECK(condition) \ - LAZY_CHECK_STREAM(::yass::CheckError::DCheck(__FILE__, __LINE__, #condition).stream(), \ + LAZY_CHECK_STREAM(::gurl_base::logging::CheckError::DCheck(__FILE__, __LINE__, #condition).stream(), \ !ANALYZER_ASSUME_TRUE(condition)) #define DPCHECK(condition) \ - LAZY_CHECK_STREAM(::yass::CheckError::DPCheck(__FILE__, __LINE__, #condition).stream(), \ + LAZY_CHECK_STREAM(::gurl_base::logging::CheckError::DPCheck(__FILE__, __LINE__, #condition).stream(), \ !ANALYZER_ASSUME_TRUE(condition)) #else @@ -165,6 +168,11 @@ void RawError(const char* message); } \ EAT_CHECK_STREAM_PARAMS() -} // namespace yass +} // namespace logging +} // namespace gurl_base -#endif // CORE_CHECK_H_ +#define GURL_CHECK(val) CHECK(val) +#define GURL_DCHECK(val) DCHECK(val) +#define GURL_NOTREACHED() NOTREACHED() + +#endif /* POLYFILLS_BASE_CHECK_H_ */ diff --git a/yass/src/core/check_op.cpp b/yass/third_party/googleurl-override/polyfills/base/check_op.cc similarity index 88% rename from yass/src/core/check_op.cpp rename to yass/third_party/googleurl-override/polyfills/base/check_op.cc index ee7306cd11..584bbb810d 100644 --- a/yass/src/core/check_op.cpp +++ b/yass/third_party/googleurl-override/polyfills/base/check_op.cc @@ -1,7 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ +// Copyright 2020 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#include "core/check_op.hpp" +#include "base/check_op.h" // check_op.h is a widely included header and its size has significant impact on // build time. Try not to raise this limit unless absolutely necessary. See @@ -16,7 +17,8 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -namespace yass { +namespace gurl_base { +namespace logging { char* CheckOpValueStr(int v) { char buf[50]; @@ -96,4 +98,5 @@ CheckOpResult::CheckOpResult(const char* expr_str, char* v1_str, char* v2_str) { free(v2_str); } -} // namespace yass +} // namespace logging +} // namespace gurl_base diff --git a/yass/src/core/check_op.hpp b/yass/third_party/googleurl-override/polyfills/base/check_op.h similarity index 78% rename from yass/src/core/check_op.hpp rename to yass/third_party/googleurl-override/polyfills/base/check_op.h index 920a8ec3e0..0044d2eed3 100644 --- a/yass/src/core/check_op.hpp +++ b/yass/third_party/googleurl-override/polyfills/base/check_op.h @@ -1,17 +1,46 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Chilledheart */ +// Copyright 2020 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef CORE_CHECK_OP_H_ -#define CORE_CHECK_OP_H_ +#ifndef POLYFILLS_BASE_CHECK_OP_H_ +#define POLYFILLS_BASE_CHECK_OP_H_ #include #include #include -#include "core/check.hpp" -#include "core/template_util.hpp" +#include "polyfills/base/logging.h" +#include "base/template_util.h" -namespace yass { +#include "base/check.h" +#include "base/compiler_specific.h" + +// template_util.hpp +#include +#include +#include +#include +#include + +namespace gurl_base { + +namespace internal { + +// Uses expression SFINAE to detect whether using operator<< would work. +template +struct SupportsOstreamOperator : std::false_type {}; +template +struct SupportsOstreamOperator() << std::declval()))> : std::true_type { +}; + +template +struct SupportsToString : std::false_type {}; +template +struct SupportsToString().ToString()))> : std::true_type {}; + +} // namespace internal + +namespace logging { // This header defines the (DP)CHECK_EQ etc. macros. // @@ -139,10 +168,10 @@ class CheckOpResult { switch (0) \ case 0: \ default: \ - if (::yass::CheckOpResult true_if_passed = ::yass::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \ + if (::gurl_base::logging::CheckOpResult true_if_passed = ::gurl_base::logging::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \ ; \ else \ - ::yass::CheckError::CheckOp(__FILE__, __LINE__, &true_if_passed).stream() + ::gurl_base::logging::CheckError::CheckOp(__FILE__, __LINE__, &true_if_passed).stream() #endif @@ -184,16 +213,16 @@ DEFINE_CHECK_OP_IMPL(GT, > ) switch (0) \ case 0: \ default: \ - if (::yass::CheckOpResult true_if_passed = ::yass::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \ + if (::gurl_base::logging::CheckOpResult true_if_passed = ::gurl_base::logging::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \ ; \ else \ - ::yass::CheckError::DCheckOp(__FILE__, __LINE__, &true_if_passed).stream() + ::gurl_base::logging::CheckError::DCheckOp(__FILE__, __LINE__, &true_if_passed).stream() #else // Don't do any evaluation but still reference the same stuff as when enabled. #define DCHECK_OP(name, op, val1, val2) \ - EAT_CHECK_STREAM_PARAMS((::yass::CheckOpValueStr(val1), ::yass::CheckOpValueStr(val2), (val1)op(val2))) + EAT_CHECK_STREAM_PARAMS((::gurl_base::logging::CheckOpValueStr(val1), ::gurl_base::logging::CheckOpValueStr(val2), (val1)op(val2))) #endif @@ -206,6 +235,20 @@ DEFINE_CHECK_OP_IMPL(GT, > ) #define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2) // clang-format on -} // namespace yass +} // namespace logging +} // namespace gurl_base -#endif // CORE_CHECK_OP_H_ +#define GURL_CHECK_GE(val1, val2) CHECK_GE(val1, val2) +#define GURL_CHECK_GT(val1, val2) CHECK_GT(val1, val2) +#define GURL_CHECK_LE(val1, val2) CHECK_LE(val1, val2) +#define GURL_CHECK_LT(val1, val2) CHECK_LT(val1, val2) +#define GURL_CHECK_NE(val1, val2) CHECK_NE(val1, val2) +#define GURL_CHECK_EQ(val1, val2) CHECK_EQ(val1, val2) +#define GURL_DCHECK_EQ(val1, val2) DCHECK_EQ(val1, val2) +#define GURL_DCHECK_GE(val1, val2) DCHECK_GE(val1, val2) +#define GURL_DCHECK_GT(val1, val2) DCHECK_GT(val1, val2) +#define GURL_DCHECK_LE(val1, val2) DCHECK_LE(val1, val2) +#define GURL_DCHECK_LT(val1, val2) DCHECK_LT(val1, val2) +#define GURL_DCHECK_NE(val1, val2) DCHECK_NE(val1, val2) + +#endif // BASE_CHECK_OP_H_ diff --git a/yass/third_party/googleurl-override/polyfills/base/logging.h b/yass/third_party/googleurl-override/polyfills/base/logging.h new file mode 100644 index 0000000000..7f40b5bc95 --- /dev/null +++ b/yass/third_party/googleurl-override/polyfills/base/logging.h @@ -0,0 +1,845 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef POLYFILLS_BASE_LOGGING_H_ +#define POLYFILLS_BASE_LOGGING_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "base/compiler_specific.h" +#include "base/dcheck_is_on.h" +#include "build/build_config.h" +#include "base/strings/utf_ostream_operators.h" + +#if BUILDFLAG(IS_WIN) +#include +#endif + +namespace gurl_base { +namespace logging { + +// ScopedClearLastError stores and resets the value of thread local error codes +// (errno, GetLastError()), and restores them in the destructor. This is useful +// to avoid side effects on these values in instrumentation functions that +// interact with the OS. + +// Common implementation of ScopedClearLastError for all platforms. Use +// ScopedClearLastError instead. +class ScopedClearLastErrorBase { + public: + ScopedClearLastErrorBase() : last_errno_(errno) { errno = 0; } + ScopedClearLastErrorBase(const ScopedClearLastErrorBase&) = delete; + ScopedClearLastErrorBase& operator=(const ScopedClearLastErrorBase&) = delete; + ~ScopedClearLastErrorBase() { errno = last_errno_; } + + private: + const int last_errno_; +}; + +#if BUILDFLAG(IS_WIN) + +// Windows specific implementation of ScopedClearLastError. +class ScopedClearLastError : public ScopedClearLastErrorBase { + public: + ScopedClearLastError(); + ScopedClearLastError(const ScopedClearLastError&) = delete; + ScopedClearLastError& operator=(const ScopedClearLastError&) = delete; + ~ScopedClearLastError(); + + private: + const unsigned long last_system_error_; +}; + +#elif BUILDFLAG(IS_POSIX) + +using ScopedClearLastError = ScopedClearLastErrorBase; + +#endif // BUILDFLAG(IS_WIN) + +using LogSeverity = int; +constexpr LogSeverity LOGGING_VERBOSE = -1; // This is level 1 verbosity +// Note: the log severities are used to index into the array of names, +// see log_severity_names. +constexpr LogSeverity LOGGING_INFO = 0; +constexpr LogSeverity LOGGING_WARNING = 1; +constexpr LogSeverity LOGGING_ERROR = 2; +constexpr LogSeverity LOGGING_FATAL = 3; +constexpr LogSeverity LOGGING_NUM_SEVERITIES = 4; + +// LOGGING_DFATAL is LOGGING_FATAL in DCHECK-enabled builds, ERROR in normal +// mode. +#if DCHECK_IS_ON() +constexpr LogSeverity LOGGING_DFATAL = LOGGING_FATAL; +#else +constexpr LogSeverity LOGGING_DFATAL = LOGGING_ERROR; +#endif + +// This block duplicates the above entries to facilitate incremental conversion +// from LOG_FOO to LOGGING_FOO. +// TODO(thestig): Convert existing users to LOGGING_FOO and remove this block. +constexpr LogSeverity LOG_VERBOSE = LOGGING_VERBOSE; +constexpr LogSeverity LOG_INFO = LOGGING_INFO; +constexpr LogSeverity LOG_WARNING = LOGGING_WARNING; +constexpr LogSeverity LOG_ERROR = LOGGING_ERROR; +constexpr LogSeverity LOG_FATAL = LOGGING_FATAL; +constexpr LogSeverity LOG_DFATAL = LOGGING_DFATAL; + +// A few definitions of macros that don't generate much code. These are used +// by LOG() and LOG_IF, etc. Since these are used all over our code, it's +// better to have compact code for these operations. +#define COMPACT_LOGGING_EX_INFO(ClassName, ...) ::gurl_base::logging::ClassName(__FILE__, __LINE__, ::gurl_base::logging::LOGGING_INFO, ##__VA_ARGS__) +#define COMPACT_LOGGING_EX_WARNING(ClassName, ...) ::gurl_base::logging::ClassName(__FILE__, __LINE__, ::gurl_base::logging::LOGGING_WARNING, ##__VA_ARGS__) +#define COMPACT_LOGGING_EX_ERROR(ClassName, ...) ::gurl_base::logging::ClassName(__FILE__, __LINE__, ::gurl_base::logging::LOGGING_ERROR, ##__VA_ARGS__) +#define COMPACT_LOGGING_EX_FATAL(ClassName, ...) ::gurl_base::logging::ClassName(__FILE__, __LINE__, ::gurl_base::logging::LOGGING_FATAL, ##__VA_ARGS__) +#define COMPACT_LOGGING_EX_DFATAL(ClassName, ...) ::gurl_base::logging::ClassName(__FILE__, __LINE__, ::gurl_base::logging::LOGGING_DFATAL, ##__VA_ARGS__) +#define COMPACT_LOGGING_EX_DCHECK(ClassName, ...) ::gurl_base::logging::ClassName(__FILE__, __LINE__, ::gurl_base::logging::LOGGING_DCHECK, ##__VA_ARGS__) + +#define COMPACT_LOGGING_INFO COMPACT_LOGGING_EX_INFO(LogMessage) +#define COMPACT_LOGGING_WARNING COMPACT_LOGGING_EX_WARNING(LogMessage) +#define COMPACT_LOGGING_ERROR COMPACT_LOGGING_EX_ERROR(LogMessage) +#define COMPACT_LOGGING_FATAL COMPACT_LOGGING_EX_FATAL(LogMessage) +#define COMPACT_LOGGING_DFATAL COMPACT_LOGGING_EX_DFATAL(LogMessage) +#define COMPACT_LOGGING_DCHECK COMPACT_LOGGING_EX_DCHECK(LogMessage) + +#if BUILDFLAG(IS_WIN) +// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets +// substituted with 0, and it expands to COMPACT_LOGGING_0. To allow us +// to keep using this syntax, we define this macro to do the same thing +// as COMPACT_LOGGING_ERROR, and also define ERROR the same way that +// the Windows SDK does for consistency. +#define ERROR 0 +#define COMPACT_LOGGING_EX_0(ClassName, ...) COMPACT_LOGGING_EX_ERROR(ClassName, ##__VA_ARGS__) +#define COMPACT_LOGGING_0 COMPACT_LOGGING_ERROR +// Needed for LOG_IS_ON(ERROR). +constexpr LogSeverity LOGGING_0 = LOGGING_ERROR; +#endif + +// As special cases, we can assume that LOG_IS_ON(FATAL) always holds. Also, +// LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will +// always fire if they fail. +#define LOG_IS_ON(severity) (::gurl_base::logging::ShouldCreateLogMessage(::gurl_base::logging::LOGGING_##severity)) + +#if defined(__GNUC__) +// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site. +// (Normally) the first time every VLOG_IS_ON(n) site is hit, +// we determine what variable will dynamically control logging at this site: +// it's either FLAGS_v or an appropriate internal variable +// matching the current source file that represents results of +// parsing of --vmodule flag and/or SetVLOGLevel calls. +#define VLOG_IS_ON(verboselevel) \ + __extension__({ \ + static absl::Flag* vlocal__ = NULL; \ + int32_t verbose_level__ = (verboselevel); \ + (vlocal__ == NULL ? ::gurl_base::logging::InitVLOG3__(&vlocal__, &FLAGS_v, __FILE__, verbose_level__) \ + : absl::GetFlag(*vlocal__) >= verbose_level__); \ + }) +#else +// GNU extensions not available, so we do not support --vmodule. +// Dynamic value of FLAGS_v always controls the logging level. +#define VLOG_IS_ON(verboselevel) (absl::GetFlag(FLAGS_v) >= (verboselevel)) +#endif + +// Helper macro which avoids evaluating the arguments to a stream if +// the condition doesn't hold. Condition is evaluated once and only once. +#define LAZY_STREAM(stream, condition) !(condition) ? (void)0 : ::gurl_base::logging::LogMessageVoidify() & (stream) + +// We use the preprocessor's merging operator, "##", so that, e.g., +// LOG(INFO) becomes the token COMPACT_LOGGING_INFO. There's some funny +// subtle difference between ostream member streaming functions (e.g., +// ostream::operator<<(int) and ostream non-member streaming functions +// (e.g., ::operator<<(ostream&, string&): it turns out that it's +// impossible to stream something like a string directly to an unnamed +// ostream. We employ a neat hack by calling the stream() member +// function of LogMessage which seems to avoid the problem. +#define LOG_STREAM(severity) COMPACT_LOGGING_##severity.stream() + +#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity)) +#define LOG_IF(severity, condition) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) + +// The VLOG macros log with negative verbosities. +#define VLOG_STREAM(verbose_level) ::gurl_base::logging::LogMessage(__FILE__, __LINE__, -(verbose_level)).stream() + +#define VLOG(verbose_level) LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) + +#define VLOG_IF(verbose_level, condition) \ + LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level) && (condition)) + +#if BUILDFLAG(IS_WIN) +#define VPLOG_STREAM(verbose_level) \ + ::gurl_base::logging::Win32ErrorLogMessage(__FILE__, __LINE__, -(verbose_level), ::gurl_base::logging::GetLastSystemErrorCode()).stream() +#elif BUILDFLAG(IS_POSIX) +#define VPLOG_STREAM(verbose_level) \ + ::gurl_base::logging::ErrnoLogMessage(__FILE__, __LINE__, -(verbose_level), ::gurl_base::logging::GetLastSystemErrorCode()).stream() +#endif + +#define VPLOG(verbose_level) LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) + +#define VPLOG_IF(verbose_level, condition) \ + LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level) && (condition)) + +// TODO(akalin): Add more VLOG variants, e.g. VPLOG. + +#define LOG_ASSERT(condition) LOG_IF(FATAL, !(ABSL_PREDICT_TRUE(condition))) << "Assert failed: " #condition ". " + +#if BUILDFLAG(IS_WIN) +#define PLOG_STREAM(severity) \ + COMPACT_LOGGING_EX_##severity(Win32ErrorLogMessage, ::gurl_base::logging::GetLastSystemErrorCode()).stream() +#elif BUILDFLAG(IS_POSIX) +#define PLOG_STREAM(severity) COMPACT_LOGGING_EX_##severity(ErrnoLogMessage, ::gurl_base::logging::GetLastSystemErrorCode()).stream() +#endif + +#define PLOG(severity) LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity)) + +#define PLOG_IF(severity, condition) LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) + +namespace gurl_base { +namespace logging { +extern std::ostream* g_swallow_stream; +} // namespace logging +} // namespace gurl_base + +// Note that g_swallow_stream is used instead of an arbitrary LOG() stream to +// avoid the creation of an object with a non-trivial destructor (LogMessage). +// On MSVC x86 (checked on 2015 Update 3), this causes a few additional +// pointless instructions to be emitted even at full optimization level, even +// though the : arm of the ternary operator is clearly never executed. Using a +// simpler object to be &'d with Voidify() avoids these extra instructions. +// Using a simpler POD object with a templated operator<< also works to avoid +// these instructions. However, this causes warnings on statically defined +// implementations of operator<<(std::ostream, ...) in some .cc files, because +// they become defined-but-unreferenced functions. A reinterpret_cast of 0 to an +// ostream* also is not suitable, because some compilers warn of undefined +// behavior. +#define EAT_STREAM_PARAMETERS true ? (void)0 : ::gurl_base::logging::LogMessageVoidify() & (*::gurl_base::logging::g_swallow_stream) + +// Definitions for DLOG et al. + +#if DCHECK_IS_ON() + +#define DLOG_IS_ON(severity) LOG_IS_ON(severity) +#define DLOG_IF(severity, condition) LOG_IF(severity, condition) +#define DLOG_ASSERT(condition) LOG_ASSERT(condition) +#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition) +#define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition) +#define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition) + +#else // !DCHECK_IS_ON() + +// If !DCHECK_IS_ON(), we want to avoid emitting any references to |condition| +// (which may reference a variable defined only if DCHECK_IS_ON()). +// Contrast this with DCHECK et al., which has different behavior. + +#define DLOG_IS_ON(severity) false +#define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS +#define DLOG_ASSERT(condition) EAT_STREAM_PARAMETERS +#define DPLOG_IF(severity, condition) EAT_STREAM_PARAMETERS +#define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS +#define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS + +#endif // DCHECK_IS_ON() + +#define DLOG(severity) LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity)) + +#define DPLOG(severity) LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity)) + +#define DVLOG(verboselevel) DVLOG_IF(verboselevel, true) + +#define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, true) + +// Definitions for DCHECK et al. + +constexpr LogSeverity LOGGING_DCHECK = LOGGING_FATAL; + +// Redefine the standard assert to use our nice log files +#undef assert +#define assert(x) DLOG_ASSERT(x) + +} // namespace logging +} // namespace gurl_base + +ABSL_DECLARE_FLAG(bool, tick_counts_in_logfile_name); +ABSL_DECLARE_FLAG(bool, logtostderr); +ABSL_DECLARE_FLAG(bool, alsologtostderr); +ABSL_DECLARE_FLAG(bool, colorlogtostderr); +#if BUILDFLAG(IS_POSIX) +ABSL_DECLARE_FLAG(bool, drop_log_memory); +#endif + +ABSL_DECLARE_FLAG(int32_t, stderrthreshold); +ABSL_DECLARE_FLAG(int32_t, minloglevel); +ABSL_DECLARE_FLAG(int32_t, logbuflevel); +ABSL_DECLARE_FLAG(int32_t, logbufsecs); + +ABSL_DECLARE_FLAG(int32_t, logfile_mode); +ABSL_DECLARE_FLAG(std::string, log_dir); +ABSL_DECLARE_FLAG(std::string, log_link); +ABSL_DECLARE_FLAG(int32_t, max_log_size); +ABSL_DECLARE_FLAG(bool, stop_logging_if_full_disk); +ABSL_DECLARE_FLAG(std::string, log_backtrace_at); + +ABSL_DECLARE_FLAG(int32_t, v); +ABSL_DECLARE_FLAG(std::string, vmodule); + +ABSL_DECLARE_FLAG(bool, log_process_id); +ABSL_DECLARE_FLAG(bool, log_thread_id); +ABSL_DECLARE_FLAG(bool, log_timestamp); +ABSL_DECLARE_FLAG(bool, log_tickcount); +ABSL_DECLARE_FLAG(std::string, log_prefix); + +namespace gurl_base { +namespace logging { + +// Set VLOG(_IS_ON) level for module_pattern to log_level. +// This lets us dynamically control what is normally set by the --vmodule flag. +// Returns the level that previously applied to module_pattern. +// NOTE: To change the log level for VLOG(_IS_ON) sites +// that have already executed after/during InitGoogleLogging, +// one needs to supply the exact --vmodule pattern that applied to them. +// (If no --vmodule pattern applied to them +// the value of FLAGS_v will continue to control them.) +extern int SetVLOGLevel(const char* module_pattern, int log_level); + +// Various declarations needed for VLOG_IS_ON above: ========================= + +// Helper routine which determines the logging info for a particalur VLOG site. +// site_flag is the address of the site-local pointer to the controlling +// verbosity level +// site_default is the default to use for *site_flag +// fname is the current source file name +// verbose_level is the argument to VLOG_IS_ON +// We will return the return value for VLOG_IS_ON +// and if possible set *site_flag appropriately. +extern bool InitVLOG3__(absl::Flag** site_flag, + absl::Flag* site_default, + const char* fname, + int32_t verbose_level); + +// Enable/Disable old log cleaner. +void EnableLogCleaner(int overdue_days); +void DisableLogCleaner(); +void SetApplicationFingerprint(const std::string& fingerprint); + +class LogSink; // defined below + +// If a non-NULL sink pointer is given, we push this message to that sink. +// For LOG_TO_SINK we then do normal LOG(severity) logging as well. +// This is useful for capturing messages and passing/storing them +// somewhere more specific than the global log of the process. +// Argument types: +// LogSink* sink; +// LogSeverity severity; +// The cast is to disambiguate NULL arguments. +#define LOG_TO_SINK(sink, severity) \ + LogMessage(__FILE__, __LINE__, LOGGING_##severity, static_cast(sink), true).stream() +#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \ + LogMessage(__FILE__, __LINE__, LOGGING_##severity, static_cast(sink), false).stream() + +#if defined(_SANITIZE_THREAD) +#define _IFDEF_THREAD_SANITIZER(X) X +#else +#define _IFDEF_THREAD_SANITIZER(X) +#endif + +struct CrashReason; + +// LogMessage::LogStream is a std::ostream backed by this streambuf. +// This class ignores overflow and leaves two bytes at the end of the +// buffer to allow for a '\n' and '\0'. +class LogStreamBuf : public std::streambuf { + public: + // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\0'. + LogStreamBuf(char* buf, int len) { setp(buf, buf + len - 2); } + + // This effectively ignores overflow. + int_type overflow(int_type ch) { return ch; } + + // Legacy public ostrstream method. + size_t pcount() const { return pptr() - pbase(); } + char* pbase() const { return std::streambuf::pbase(); } +}; + +// +// This class more or less represents a particular log message. You +// create an instance of LogMessage and then stream stuff to it. +// When you finish streaming to it, ~LogMessage is called and the +// full message gets streamed to the appropriate destination. +// +// You shouldn't actually use LogMessage's constructor to log things, +// though. You should use the LOG() macro (and variants thereof) +// above. +class LogMessage { + public: + enum { + // Passing kNoLogPrefix for the line number disables the + // log-message prefix. Useful for using the LogMessage + // infrastructure as a printing utility. See also the --log_prefix + // flag for controlling the log-message prefix on an + // application-wide basis. + kNoLogPrefix = -1 + }; + + // LogStream inherit from non-DLL-exported class (std::ostrstream) + // and VC++ produces a warning for this situation. + // However, MSDN says "C4275 can be ignored in Microsoft Visual C++ + // 2005 if you are deriving from a type in the Standard C++ Library" + // http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx + // Let's just ignore the warning. + class LogStream : public std::ostream { + public: + // 'this' : used in base member initializer + LogStream(char* buf, int len, uint64_t ctr) : std::ostream(NULL), streambuf_(buf, len), ctr_(ctr), self_(this) { + rdbuf(&streambuf_); + } + + uint64_t ctr() const { return ctr_; } + void set_ctr(uint64_t ctr) { ctr_ = ctr; } + LogStream* self() const { return self_; } + + // Legacy std::streambuf methods. + size_t pcount() const { return streambuf_.pcount(); } + char* pbase() const { return streambuf_.pbase(); } + char* str() const { return pbase(); } + + private: + LogStream(const LogStream&); + LogStream& operator=(const LogStream&); + LogStreamBuf streambuf_; + uint64_t ctr_; // Counter hack (for the LOG_EVERY_X() macro) + LogStream* self_; // Consistency check hack + }; + + public: + // icc 8 requires this typedef to avoid an internal compiler error. + typedef void (LogMessage::*SendMethod)(); + + LogMessage(const char* file, int line, LogSeverity severity, uint64_t ctr, SendMethod send_method); + + // Used for LOG(severity). + LogMessage(const char* file, int line, LogSeverity severity); + + // Used for CHECK(). Implied severity = LOGGING_FATAL. + LogMessage(const char* file, int line, const char* condition); + LogMessage(const LogMessage&) = delete; + LogMessage& operator=(const LogMessage&) = delete; + virtual ~LogMessage(); + + std::ostream& stream(); + + LogSeverity severity() { return severity_; } + + // Two special constructors that generate reduced amounts of code at + // LOG call sites for common cases. + + // Used for LOG(INFO): Implied are: + // severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog. + // + // Using this constructor instead of the more complex constructor above + // saves 19 bytes per call site. + LogMessage(const char* file, int line); + + // Constructor to log this message to a specified sink (if not NULL). + // Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if + // also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise. + LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink, bool also_send_to_log); + + // Constructor where we also give a vector pointer + // for storing the messages (if the pointer is not NULL). + // Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog. + LogMessage(const char* file, int line, LogSeverity severity, std::vector* outvec); + + // Constructor where we also give a string pointer for storing the + // message (if the pointer is not NULL). Implied are: ctr = 0, + // send_method = &LogMessage::WriteToStringAndLog. + LogMessage(const char* file, int line, LogSeverity severity, std::string* message); + + // Flush a buffered message to the sink set in the constructor. Always + // called by the destructor, it may also be called from elsewhere if + // needed. Only the first call is actioned; any later ones are ignored. + void Flush(); + + // An arbitrary limit on the length of a single log message. This + // is so that streaming can be done more efficiently. + static const size_t kMaxLogMessageLen; + + // Theses should not be called directly outside of logging.*, + // only passed as SendMethod arguments to other LogMessage methods: + void SendToLog(); // Actually dispatch to the logs + + // Call abort() or similar to perform LOG(FATAL) crash. + [[noreturn]] static void Fail(); + + int preserved_errno() const; + + // Must be called without the log_mutex held. (L < log_mutex) + static int64_t num_messages(int severity); + + struct LogMessageData; + + private: + // Fully internal SendMethod cases: + void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs + void SendToSink(); // Send to sink if provided, do nothing otherwise. + + // Write to string if provided and dispatch to the logs. + void WriteToStringAndLog(); + + void SaveOrSendToLog(); // Save to stringvec if provided, else to logs + + void Init(const char* file, int line, LogSeverity severity, void (LogMessage::*send_method)()); + + // Used to fill in crash information during LOG(FATAL) failures. + void RecordCrashReason(CrashReason* reason); + + // Counts of messages sent at each priority: + static int64_t num_messages_[LOGGING_NUM_SEVERITIES]; // under log_mutex + + // We keep the data in a separate struct so that each instance of + // LogMessage uses less stack space. + LogMessageData* allocated_; + LogMessageData* data_; + + friend class LogDestination; + + const LogSeverity severity_; + + // This is useful since the LogMessage class uses a lot of Win32 calls + // that will lose the value of GLE and the code that called the log function + // will have lost the thread error value when the log call returns. + ScopedClearLastError last_error_; +}; + +// This class happens to be thread-hostile because all instances share +// a single data buffer, but since it can only be created just before +// the process dies, we don't worry so much. +class LogMessageFatal : public LogMessage { + public: + LogMessageFatal(const char* file, int line); + [[noreturn]] ~LogMessageFatal(); +}; + +// A non-macro interface to the log facility; (useful +// when the logging level is not a compile-time constant). +inline void LogAtLevel(int const severity, std::string const& msg) { + LogMessage(__FILE__, __LINE__, severity).stream() << msg; +} + +// A macro alternative of LogAtLevel. New code may want to use this +// version since there are two advantages: 1. this version outputs the +// file name and the line number where this macro is put like other +// LOG macros, 2. this macro can be used as C++ stream. +#define LOG_AT_LEVEL(severity) LogMessage(__FILE__, __LINE__, severity).stream() + +// This class is used to explicitly ignore values in the conditional +// logging macros. This avoids compiler warnings like "value computed +// is not used" and "statement has no effect". +class LogMessageVoidify { + public: + LogMessageVoidify() = default; + // This has to be an operator with a precedence lower than << but + // higher than ?: + void operator&(std::ostream&) {} +}; + +#if BUILDFLAG(IS_WIN) +typedef unsigned long SystemErrorCode; +#elif BUILDFLAG(IS_POSIX) +typedef int SystemErrorCode; +#endif + +// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to +// pull in windows.h just for GetLastError() and DWORD. +SystemErrorCode GetLastSystemErrorCode(); +std::string SystemErrorCodeToString(SystemErrorCode error_code); + +#if BUILDFLAG(IS_WIN) +// Appends a formatted system message of the GetLastError() type. +class Win32ErrorLogMessage : public LogMessage { + public: + Win32ErrorLogMessage(const char* file, int line, LogSeverity severity, SystemErrorCode err); + Win32ErrorLogMessage(const Win32ErrorLogMessage&) = delete; + Win32ErrorLogMessage& operator=(const Win32ErrorLogMessage&) = delete; + // Appends the error message before destructing the encapsulated class. + ~Win32ErrorLogMessage() override; + + private: + SystemErrorCode err_; +}; +#elif BUILDFLAG(IS_POSIX) +// Appends a formatted system message of the errno type +class ErrnoLogMessage : public LogMessage { + public: + ErrnoLogMessage(const char* file, int line, LogSeverity severity, SystemErrorCode err); + ErrnoLogMessage(const ErrnoLogMessage&) = delete; + ErrnoLogMessage& operator=(const ErrnoLogMessage&) = delete; + // Appends the error message before destructing the encapsulated class. + ~ErrnoLogMessage() override; + + private: + SystemErrorCode err_; +}; +#endif + +// Flushes all log files that contains messages that are at least of +// the specified severity level. Thread-safe. +void FlushLogFiles(LogSeverity min_severity); + +// Flushes all log files that contains messages that are at least of +// the specified severity level. Thread-hostile because it ignores +// locking -- used for catastrophic failures. +void FlushLogFilesUnsafe(LogSeverity min_severity); + +// +// Set the destination to which a particular severity level of log +// messages is sent. If base_filename is "", it means "don't log this +// severity". Thread-safe. +// +void SetLogDestination(LogSeverity severity, const char* base_filename); + +// +// Set the basename of the symlink to the latest log file at a given +// severity. If symlink_basename is empty, do not make a symlink. If +// you don't call this function, the symlink basename is the +// invocation name of the program. Thread-safe. +// +void SetLogSymlink(LogSeverity severity, const char* symlink_basename); + +// +// Used to send logs to some other kind of destination +// Users should subclass LogSink and override send to do whatever they want. +// Implementations must be thread-safe because a shared instance will +// be called from whichever thread ran the LOG(XXX) line. +class LogSink { + public: + virtual ~LogSink(); + + // Sink's logging logic (message_len is such as to exclude '\n' at the end). + // This method can't use LOG() or CHECK() as logging system mutex(s) are held + // during this call. + virtual void send(LogSeverity severity, + const char* full_filename, + const char* base_filename, + int line, + const char* message, + size_t message_len, + uint64_t /*tick_counts*/) { + send(severity, full_filename, base_filename, line, message, message_len); + } + // This send() signature is obsolete. + // New implementations should define this in terms of + // the above send() method. + virtual void send(LogSeverity severity, + const char* full_filename, + const char* base_filename, + int line, + const char* message, + size_t message_len) = 0; + + // Redefine this to implement waiting for + // the sink's logging logic to complete. + // It will be called after each send() returns, + // but before that LogMessage exits or crashes. + // By default this function does nothing. + // Using this function one can implement complex logic for send() + // that itself involves logging; and do all this w/o causing deadlocks and + // inconsistent rearrangement of log messages. + // E.g. if a LogSink has thread-specific actions, the send() method + // can simply add the message to a queue and wake up another thread that + // handles real logging while itself making some LOG() calls; + // WaitTillSent() can be implemented to wait for that logic to complete. + // See our unittest for an example. + virtual void WaitTillSent(); + + // Returns the normal text output of the log message. + // Can be useful to implement send(). + static std::string ToString(LogSeverity severity, + const char* file, + int line, + const char* message, + size_t message_len, + uint64_t tick_counts); + + // Obsolete + static std::string ToString(LogSeverity severity, + const char* file, + int line, + const char* message, + size_t message_len) { + return ToString(severity, file, line, message, message_len, 0); + } +}; + +// Add or remove a LogSink as a consumer of logging data. Thread-safe. +void AddLogSink(LogSink* destination); +void RemoveLogSink(LogSink* destination); + +// +// Specify an "extension" added to the filename specified via +// SetLogDestination. This applies to all severity levels. It's +// often used to append the port we're listening on to the logfile +// name. Thread-safe. +// +void SetLogFilenameExtension(const char* filename_extension); + +// +// Make it so that all log messages of at least a particular severity +// are logged to stderr (in addition to logging to the usual log +// file(s)). Thread-safe. +// +void SetStderrLogging(LogSeverity min_severity); + +// +// Make it so that all log messages go only to stderr. Thread-safe. +// +void LogToStderr(); + +const std::vector& GetLoggingDirectories(); + +// Returns a set of existing temporary directories, which will be a +// subset of the directories returned by GetLogginDirectories(). +// Thread-safe. +void GetExistingTempDirectories(std::vector* list); + +// Print any fatal message again -- useful to call from signal handler +// so that the last thing in the output is the fatal message. +// Thread-hostile, but a race is unlikely. +void ReprintFatalMessage(); + +// Truncate a log file that may be the append-only output of multiple +// processes and hence can't simply be renamed/reopened (typically a +// stdout/stderr). If the file "path" is > "limit" bytes, copy the +// last "keep" bytes to offset 0 and truncate the rest. Since we could +// be racing with other writers, this approach has the potential to +// lose very small amounts of data. For security, only follow symlinks +// if the path is /proc/self/fd/* +void TruncateLogFile(const char* path, int64_t limit, int64_t keep); + +// Truncate stdout and stderr if they are over the value specified by +// --max_log_size; keep the final 1MB. This function has the same +// race condition as TruncateLogFile. +void TruncateStdoutStderr(); + +// --------------------------------------------------------------------- +// Implementation details that are not useful to most clients +// --------------------------------------------------------------------- + +// A Logger is the interface used by logging modules to emit entries +// to a log. A typical implementation will dump formatted data to a +// sequence of files. We also provide interfaces that will forward +// the data to another thread so that the invoker never blocks. +// Implementations should be thread-safe since the logging system +// will write to them from multiple threads. + +class Logger { + public: + virtual ~Logger(); + + // Writes "message[0,message_len-1]" corresponding to an event that + // occurred at "tick_counts". If "force_flush" is true, the log file + // is flushed immediately. + // + // The input message has already been formatted as deemed + // appropriate by the higher level logging facility. For example, + // textual log messages already contain tick_counts, and the + // file:linenumber header. + virtual void Write(bool force_flush, uint64_t tick_counts, const char* message, int message_len) = 0; + + // Flush any buffered messages + virtual void Flush() = 0; + + // Get the current LOG file size. + // The returned value is approximate since some + // logged data may not have been flushed to disk yet. + virtual uint32_t LogSize() = 0; +}; + +// Get the logger for the specified severity level. The logger +// remains the property of the logging module and should not be +// deleted by the caller. Thread-safe. +extern Logger* GetLogger(LogSeverity level); + +// Set the logger for the specified severity level. The logger +// becomes the property of the logging module and should not +// be deleted by the caller. Thread-safe. +extern void SetLogger(LogSeverity level, Logger* logger); + +// glibc has traditionally implemented two incompatible versions of +// strerror_r(). There is a poorly defined convention for picking the +// version that we want, but it is not clear whether it even works with +// all versions of glibc. +// So, instead, we provide this wrapper that automatically detects the +// version that is in use, and then implements POSIX semantics. +// N.B. In addition to what POSIX says, we also guarantee that "buf" will +// be set to an empty string, if this function failed. This means, in most +// cases, you do not need to check the error code and you can directly +// use the value of "buf". It will never have an undefined value. +// DEPRECATED: Use StrError(int) instead. +int posix_strerror_r(int err, char* buf, size_t len); + +// A thread-safe replacement for strerror(). Returns a string describing the +// given POSIX error code. +std::string StrError(int err); + +// A class for which we define operator<<, which does nothing. +class NullStream : public LogMessage::LogStream { + public: + // Initialize the LogStream so the messages can be written somewhere + // (they'll never be actually displayed). This will be needed if a + // NullStream& is implicitly converted to LogStream&, in which case + // the overloaded NullStream::operator<< will not be invoked. + NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) {} + NullStream& stream() { return *this; } + + private: + // A very short buffer for messages (which we discard anyway). This + // will be needed if NullStream& converted to LogStream& (e.g. as a + // result of a conditional expression). + char message_buffer_[2]; +}; + +// Do nothing. This operator is inline, allowing the message to be +// compiled away. The message will not be compiled away if we do +// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when +// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly +// converted to LogStream and the message will be computed and then +// quietly discarded. +template +inline NullStream& operator<<(NullStream& str, const T&) { + return str; +} + +// Similar to NullStream, but aborts the program (without stack +// trace), like LogMessageFatal. +class NullStreamFatal : public NullStream { + public: + NullStreamFatal() {} + [[noreturn]] ~NullStreamFatal() throw() { _exit(1); } +}; + +// Used by LOG_IS_ON to lazy-evaluate stream arguments. +bool ShouldCreateLogMessage(LogSeverity severity); + +// Async signal safe logging mechanism. +void RawLog(int level, const char* message); + +#define RAW_LOG(level, message) ::gurl_base::logging::RawLog(::gurl_base::logging::LOGGING_##level, message) + +} // namespace log +} // namespace gurl_base + +#define GURL_DLOG(s) DLOG(s) +#define GURL_LOG(s) LOG(s) + +#endif /* POLYFILLS_BASE_LOGGING_H_ */ diff --git a/yass/third_party/googleurl-override/polyfills/base/notreached.h b/yass/third_party/googleurl-override/polyfills/base/notreached.h new file mode 100644 index 0000000000..5b16119a59 --- /dev/null +++ b/yass/third_party/googleurl-override/polyfills/base/notreached.h @@ -0,0 +1,11 @@ +// Copyright (c) 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef POLYFILLS_BASE_NOTREACHED_H_ +#define POLYFILLS_BASE_NOTREACHED_H_ + +#include "polyfills/base/check.h" +#include "polyfills/base/logging.h" + +#endif /* POLYFILLS_BASE_NOTREACHED_H_ */ diff --git a/yass/third_party/libc++/CMakeLists.txt b/yass/third_party/libc++/CMakeLists.txt index 1447970675..59f4578952 100644 --- a/yass/third_party/libc++/CMakeLists.txt +++ b/yass/third_party/libc++/CMakeLists.txt @@ -85,10 +85,14 @@ if (${CMAKE_BUILD_TYPE} MATCHES Debug) set(libcxx_PUBLIC_DEFINITIONS ${libcxx_PUBLIC_DEFINITIONS} "_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG") -else() +elseif(ENABLE_ASSERTIONS) set(libcxx_PUBLIC_DEFINITIONS ${libcxx_PUBLIC_DEFINITIONS} "_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE") +else() + set(libcxx_PUBLIC_DEFINITIONS + ${libcxx_PUBLIC_DEFINITIONS} + "_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE") endif() set(libcxx_PUBLIC_DEFINITIONS diff --git a/yass/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h b/yass/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h index 298b6039b7..deb713c7f2 100644 --- a/yass/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h +++ b/yass/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h @@ -7,9 +7,9 @@ #include -#include "core/check_op.hpp" -#include "core/compiler_specific.hpp" -#include "core/logging.hpp" +#include "third_party/googleurl-override/polyfills/base/check_op.h" +#include "third_party/googleurl/base/compiler_specific.h" +#include "third_party/googleurl-override/polyfills/base/logging.h" #define QUICHE_LOG_IMPL(severity) QUICHE_YASS_LOG_##severity #define QUICHE_VLOG_IMPL(verbose_level) VLOG(verbose_level) diff --git a/yt-dlp/yt_dlp/extractor/_extractors.py b/yt-dlp/yt_dlp/extractor/_extractors.py index 4b1f4c316d..8d59360949 100644 --- a/yt-dlp/yt_dlp/extractor/_extractors.py +++ b/yt-dlp/yt_dlp/extractor/_extractors.py @@ -363,7 +363,10 @@ from .ccc import ( ) from .ccma import CCMAIE from .cctv import CCTVIE -from .cda import CDAIE +from .cda import ( + CDAIE, + CDAFolderIE, +) from .cellebrite import CellebriteIE from .ceskatelevize import CeskaTelevizeIE from .cgtn import CGTNIE diff --git a/yt-dlp/yt_dlp/extractor/cda.py b/yt-dlp/yt_dlp/extractor/cda.py index 62ee8b17f1..b2738e492f 100644 --- a/yt-dlp/yt_dlp/extractor/cda.py +++ b/yt-dlp/yt_dlp/extractor/cda.py @@ -12,6 +12,7 @@ from .common import InfoExtractor from ..compat import compat_ord from ..utils import ( ExtractorError, + OnDemandPagedList, float_or_none, int_or_none, merge_dicts, @@ -351,3 +352,50 @@ class CDAIE(InfoExtractor): extract_format(webpage, resolution) return merge_dicts(info_dict, info) + + +class CDAFolderIE(InfoExtractor): + _MAX_PAGE_SIZE = 36 + _VALID_URL = r'https?://(?:www\.)?cda\.pl/(?P\w+)/folder/(?P\d+)' + _TESTS = [ + { + 'url': 'https://www.cda.pl/domino264/folder/31188385', + 'info_dict': { + 'id': '31188385', + 'title': 'SERIA DRUGA', + }, + 'playlist_mincount': 13, + }, + { + 'url': 'https://www.cda.pl/smiechawaTV/folder/2664592/vfilm', + 'info_dict': { + 'id': '2664592', + 'title': 'VideoDowcipy - wszystkie odcinki', + }, + 'playlist_mincount': 71, + }, + { + 'url': 'https://www.cda.pl/DeliciousBeauty/folder/19129979/vfilm', + 'info_dict': { + 'id': '19129979', + 'title': 'TESTY KOSMETYKÓW', + }, + 'playlist_mincount': 139, + }] + + def _real_extract(self, url): + folder_id, channel = self._match_valid_url(url).group('id', 'channel') + + webpage = self._download_webpage(url, folder_id) + + def extract_page_entries(page): + webpage = self._download_webpage( + f'https://www.cda.pl/{channel}/folder/{folder_id}/vfilm/{page + 1}', folder_id, + f'Downloading page {page + 1}', expected_status=404) + items = re.findall(r']+href="/video/([0-9a-z]+)"', webpage) + for video_id in items: + yield self.url_result(f'https://www.cda.pl/video/{video_id}', CDAIE, video_id) + + return self.playlist_result( + OnDemandPagedList(extract_page_entries, self._MAX_PAGE_SIZE), + folder_id, self._og_search_title(webpage)) diff --git a/yt-dlp/yt_dlp/extractor/imgur.py b/yt-dlp/yt_dlp/extractor/imgur.py index f0c3419d49..e2644e6a40 100644 --- a/yt-dlp/yt_dlp/extractor/imgur.py +++ b/yt-dlp/yt_dlp/extractor/imgur.py @@ -37,7 +37,7 @@ class ImgurBaseIE(InfoExtractor): class ImgurIE(ImgurBaseIE): - _VALID_URL = r'https?://(?:i\.)?imgur\.com/(?!(?:a|gallery|t|topic|r)/)(?P[a-zA-Z0-9]+)' + _VALID_URL = r'https?://(?:i\.)?imgur\.com/(?!(?:a|gallery|t|topic|r)/)(?:[^/?#]+-)?(?P[a-zA-Z0-9]+)' _TESTS = [{ 'url': 'https://imgur.com/A61SaA1', @@ -54,6 +54,22 @@ class ImgurIE(ImgurBaseIE): 'like_count': int, 'thumbnail': 'https://i.imgur.com/A61SaA1h.jpg', }, + }, { + # Test with URL slug + 'url': 'https://imgur.com/mrw-gifv-is-up-running-without-any-bugs-A61SaA1', + 'info_dict': { + 'id': 'A61SaA1', + 'ext': 'mp4', + 'title': 'MRW gifv is up and running without any bugs', + 'timestamp': 1416446068, + 'upload_date': '20141120', + 'dislike_count': int, + 'comment_count': int, + 'release_timestamp': 1416446068, + 'release_date': '20141120', + 'like_count': int, + 'thumbnail': 'https://i.imgur.com/A61SaA1h.jpg', + }, }, { 'url': 'https://i.imgur.com/A61SaA1.gifv', 'only_matching': True, @@ -92,6 +108,7 @@ class ImgurIE(ImgurBaseIE): 'comment_count': int, 'release_timestamp': 1710491255, 'release_date': '20240315', + 'thumbnail': 'https://i.imgur.com/zV03bd5h.jpg', }, }] @@ -208,7 +225,10 @@ class ImgurIE(ImgurBaseIE): }), get_all=False), 'id': video_id, 'formats': formats, - 'thumbnail': url_or_none(search('thumbnailUrl')), + 'thumbnails': [{ + 'url': thumbnail_url, + 'http_headers': {'Accept': '*/*'}, + }] if (thumbnail_url := search(['thumbnailUrl', 'twitter:image', 'og:image'])) else None, 'http_headers': {'Accept': '*/*'}, } @@ -252,17 +272,9 @@ class ImgurGalleryBaseIE(ImgurBaseIE): class ImgurGalleryIE(ImgurGalleryBaseIE): IE_NAME = 'imgur:gallery' - _VALID_URL = r'https?://(?:i\.)?imgur\.com/(?:gallery|(?:t(?:opic)?|r)/[^/?#]+)/(?P[a-zA-Z0-9]+)' + _VALID_URL = r'https?://(?:i\.)?imgur\.com/(?:gallery|(?:t(?:opic)?|r)/[^/?#]+)/(?:[^/?#]+-)?(?P[a-zA-Z0-9]+)' _TESTS = [{ - 'url': 'http://imgur.com/gallery/Q95ko', - 'info_dict': { - 'id': 'Q95ko', - 'title': 'Adding faces make every GIF better', - }, - 'playlist_count': 25, - 'skip': 'Zoinks! You\'ve taken a wrong turn.', - }, { # TODO: static images - replace with animated/video gallery 'url': 'http://imgur.com/topic/Aww/ll5Vk', 'only_matching': True, @@ -280,7 +292,27 @@ class ImgurGalleryIE(ImgurGalleryBaseIE): 'release_timestamp': 1358554297, 'thumbnail': 'https://i.imgur.com/YcAQlkxh.jpg', 'release_date': '20130119', - 'uploader_url': 'https://i.imgur.com/u3R4I2S_d.png?maxwidth=290&fidelity=grand', + 'uploader_url': 'https://i.imgur.com/N5Flb2v_d.png?maxwidth=290&fidelity=grand', + 'comment_count': int, + 'dislike_count': int, + 'like_count': int, + }, + }, { + # Test with slug + 'url': 'https://imgur.com/gallery/classic-steve-carell-gif-cracks-me-up-everytime-repost-downvotes-YcAQlkx', + 'add_ies': ['Imgur'], + 'info_dict': { + 'id': 'YcAQlkx', + 'ext': 'mp4', + 'title': 'Classic Steve Carell gif...cracks me up everytime....damn the repost downvotes....', + 'timestamp': 1358554297, + 'upload_date': '20130119', + 'uploader_id': '1648642', + 'uploader': 'wittyusernamehere', + 'release_timestamp': 1358554297, + 'release_date': '20130119', + 'thumbnail': 'https://i.imgur.com/YcAQlkxh.jpg', + 'uploader_url': 'https://i.imgur.com/N5Flb2v_d.png?maxwidth=290&fidelity=grand', 'comment_count': int, 'dislike_count': int, 'like_count': int, @@ -317,6 +349,13 @@ class ImgurGalleryIE(ImgurGalleryBaseIE): 'title': 'Penguins !', }, 'playlist_count': 3, + }, { + 'url': 'https://imgur.com/t/unmuted/penguins-penguins-6lAn9VQ', + 'info_dict': { + 'id': '6lAn9VQ', + 'title': 'Penguins !', + }, + 'playlist_count': 3, }, { 'url': 'https://imgur.com/t/unmuted/kx2uD3C', 'add_ies': ['Imgur'], @@ -357,7 +396,7 @@ class ImgurGalleryIE(ImgurGalleryBaseIE): class ImgurAlbumIE(ImgurGalleryBaseIE): IE_NAME = 'imgur:album' - _VALID_URL = r'https?://(?:i\.)?imgur\.com/a/(?P[a-zA-Z0-9]+)' + _VALID_URL = r'https?://(?:i\.)?imgur\.com/a/(?:[^/?#]+-)?(?P[a-zA-Z0-9]+)' _GALLERY = False _TESTS = [{ # TODO: only static images - replace with animated/video gallery @@ -372,6 +411,14 @@ class ImgurAlbumIE(ImgurGalleryBaseIE): 'title': 'enen-no-shouboutai', }, 'playlist_count': 2, + }, { + # Test with URL slug + 'url': 'https://imgur.com/a/enen-no-shouboutai-iX265HX', + 'info_dict': { + 'id': 'iX265HX', + 'title': 'enen-no-shouboutai', + }, + 'playlist_count': 2, }, { 'url': 'https://imgur.com/a/8pih2Ed', 'info_dict': {