Update On Sat Dec 14 19:33:51 CET 2024

This commit is contained in:
github-action[bot]
2024-12-14 19:33:52 +01:00
parent 87a1582e9f
commit 17f5b1587a
134 changed files with 4030 additions and 1670 deletions
+1
View File
@@ -851,3 +851,4 @@ Update On Sat Dec 7 19:36:20 CET 2024
Update On Thu Dec 12 11:40:54 CET 2024
Update On Thu Dec 12 19:38:19 CET 2024
Update On Fri Dec 13 19:36:09 CET 2024
Update On Sat Dec 14 19:33:42 CET 2024
+1
View File
@@ -85,6 +85,7 @@ public static partial class Parser
paramBuilder.Append($"&cid={cid}&ep_id={epId}&platform=android&prefer_code_type={code}&qn={qn}");
if (isBiliPlus) paramBuilder.Append($"&ts={GetTimeStamp(true)}");
paramBuilder.Append("&s_locale=zh_SG");
string param = paramBuilder.ToString();
api += (isBiliPlus ? $"{param}&sign={GetSign(param, true)}" : param);
+4 -2
View File
@@ -34,14 +34,16 @@ public static class HTTPUtil
public static string UserAgent { get; set; } = GetRandomUserAgent();
public static async Task<string> GetWebSourceAsync(string url)
public static async Task<string> GetWebSourceAsync(string url, string? userAgent = null)
{
using var webRequest = new HttpRequestMessage(HttpMethod.Get, url);
webRequest.Headers.TryAddWithoutValidation("User-Agent", UserAgent);
webRequest.Headers.TryAddWithoutValidation("User-Agent", userAgent ?? UserAgent);
webRequest.Headers.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
webRequest.Headers.TryAddWithoutValidation("Cookie", (url.Contains("/ep") || url.Contains("/ss")) ? Config.COOKIE + ";CURRENT_FNVAL=4048;" : Config.COOKIE);
if (url.Contains("api.bilibili.com"))
webRequest.Headers.TryAddWithoutValidation("Referer", "https://www.bilibili.com/");
if (url.Contains("api.bilibili.tv"))
webRequest.Headers.TryAddWithoutValidation("sec-ch-ua", "\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"");
webRequest.Headers.CacheControl = CacheControlHeaderValue.Parse("no-cache");
webRequest.Headers.Connection.Clear();
+1 -1
View File
@@ -189,7 +189,7 @@ static partial class BBDownMuxer
if (episodeId != "") argsBuilder.Append($"-metadata album=\"{title}\" ");
if (pubTime != 0) argsBuilder.Append($"-metadata creation_time=\"{(DateTimeOffset.FromUnixTimeSeconds(pubTime).ToString("yyyy-MM-ddTHH:mm:ss.ffffffZ"))}\" ");
}
argsBuilder.Append("-c copy ");
argsBuilder.Append("-c:v copy -c:a copy ");
if (audioOnly && audioPath == "") argsBuilder.Append("-vn ");
if (subs != null) argsBuilder.Append("-c:s mov_text ");
// fix macOS hev1, see https://discussions.apple.com/thread/253081863?sortBy=rank
+3 -3
View File
@@ -582,13 +582,13 @@ static partial class BBDownUtil
private static partial Regex EpRegex();
[GeneratedRegex("/ss(\\d+)")]
private static partial Regex SsRegex();
[GeneratedRegex("space\\.bilibili\\.com/(\\d+)")]
[GeneratedRegex(@"space\.bilibili\.com/(\d+)")]
private static partial Regex UidRegex();
[GeneratedRegex("global\\.bilibili\\.com/play/\\d+/(\\d+)")]
[GeneratedRegex(@"\.bilibili\.tv\/\w+\/play\/\d+\/(\d+)")]
private static partial Regex GlobalEpRegex();
[GeneratedRegex("bangumi/media/(md\\d+)")]
private static partial Regex BangumiMdRegex();
[GeneratedRegex("window.__INITIAL_STATE__=([\\s\\S].*?);\\(function\\(\\)")]
[GeneratedRegex(@"window.__INITIAL_STATE__=([\s\S].*?);\(function\(\)")]
private static partial Regex StateRegex();
[GeneratedRegex("md(\\d+)")]
private static partial Regex MdRegex();
+4 -6
View File
@@ -227,16 +227,14 @@ partial class Program
public static async Task<(string fetchedAid, VInfo vInfo, string apiType)> GetVideoInfoAsync(MyOption myOption, string aidOri, string input)
{
Log("检测账号登录...");
// 加载认证信息
LoadCredentials(myOption);
// 检测是否登录了账号
bool is_login = await CheckLogin(Config.COOKIE);
if (!myOption.UseIntlApi && !myOption.UseTvApi && Config.AREA == "")
if (myOption is { UseIntlApi: false, UseTvApi: false } && Config.AREA == "")
{
if (!is_login)
Log("检测账号登录...");
if (!await CheckLogin(Config.COOKIE))
{
LogWarn("你尚未登录B站账号, 解析可能受到限制");
}
@@ -288,7 +286,7 @@ partial class Program
Log("发布时间: " + FormatTimeStamp(pubTime, "yyyy-MM-dd HH:mm:ss zzz"));
}
var bvid = vInfo.PagesInfo.FirstOrDefault()?.bvid;
if (!string.IsNullOrEmpty(bvid))
if (!string.IsNullOrEmpty(bvid) && !myOption.UseIntlApi)
{
Log($"视频URL: https://www.bilibili.com/video/{bvid}/");
}
+16 -16
View File
@@ -12,9 +12,9 @@ require (
github.com/go-chi/render v1.0.3
github.com/gobwas/ws v1.4.0
github.com/gofrs/uuid/v5 v5.3.0
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475
github.com/klauspost/compress v1.17.9
github.com/klauspost/cpuid/v2 v2.2.8
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef
github.com/klauspost/compress v1.17.9 // lastest version compatible with golang1.20
github.com/klauspost/cpuid/v2 v2.2.9
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
github.com/mdlayher/netlink v1.7.2
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab
@@ -35,28 +35,28 @@ require (
github.com/miekg/dns v1.1.62
github.com/mroth/weightedrand/v2 v2.1.0
github.com/openacid/low v0.1.21
github.com/oschwald/maxminddb-golang v1.12.0
github.com/oschwald/maxminddb-golang v1.12.0 // lastest version compatible with golang1.20
github.com/puzpuzpuz/xsync/v3 v3.4.0
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.1
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6
github.com/sagernet/sing-shadowtls v0.1.4
github.com/sagernet/sing-mux v0.2.1
github.com/sagernet/sing-shadowtls v0.1.5
github.com/samber/lo v1.47.0
github.com/shirou/gopsutil/v3 v3.24.5
github.com/shirou/gopsutil/v4 v4.24.11
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/stretchr/testify v1.10.0
github.com/vmihailenco/msgpack/v5 v5.4.1
github.com/wk8/go-ordered-map/v2 v2.1.8
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7
go.uber.org/automaxprocs v1.6.0
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.29.0
golang.org/x/crypto v0.31.0
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // lastest version compatible with golang1.20
golang.org/x/net v0.31.0
golang.org/x/sys v0.27.0
google.golang.org/protobuf v1.34.2
golang.org/x/net v0.32.0
golang.org/x/sys v0.28.0
google.golang.org/protobuf v1.34.2 // lastest version compatible with golang1.20
gopkg.in/yaml.v3 v3.0.1
lukechampine.com/blake3 v1.3.0
)
@@ -69,6 +69,7 @@ require (
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/ebitengine/purego v0.8.1 // indirect
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
@@ -82,7 +83,7 @@ require (
github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // 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/kr/text v0.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
@@ -98,7 +99,6 @@ require (
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
@@ -111,8 +111,8 @@ require (
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
go.uber.org/mock v0.4.0 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.24.0 // indirect
)
+27 -28
View File
@@ -27,6 +27,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/enfein/mieru/v3 v3.8.4 h1:PmBQykuEcl8yKcQ647pg8Qbjl433CRYgUbW6VLBgGn4=
github.com/enfein/mieru/v3 v3.8.4/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8=
@@ -70,19 +72,19 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 h1:hxST5pwMBEOWmxpkX20w9oZG+hXdhKmAIPQ3NGGAxas=
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef h1:NzQKDfd5ZOPnuZYf9MnRee8x2qecsVqzsnaLjEZiBko=
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
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/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
@@ -168,19 +170,16 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
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/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 h1:5bCAkvDDzSMITiHFjolBwpdqYsvycdTu71FsMEFXQ14=
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
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-mux v0.2.1 h1:N/3MHymfnFZRd29tE3TaXwPUVVgKvxhtOkiCMLp9HVo=
github.com/sagernet/sing-mux v0.2.1/go.mod h1:dm3BWL6NvES9pbib7llpylrq7Gq+LjlzG+0RacdxcyE=
github.com/sagernet/sing-shadowtls v0.1.5 h1:uXxmq/HXh8DIiBGLzpMjCbWnzIAFs+lIxiTOjdgG5qo=
github.com/sagernet/sing-shadowtls v0.1.5/go.mod h1:tvrDPTGLrSM46Wnf7mSr+L8NHvgvF8M4YnJF790rZX4=
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/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shirou/gopsutil/v4 v4.24.11 h1:WaU9xqGFKvFfsUv94SXcUPD7rCkU0vr/asVdQOBZNj8=
github.com/shirou/gopsutil/v4 v4.24.11/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b h1:rXHg9GrUEtWZhEkrykicdND3VPjlVbYiLdX9J7gimS8=
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b/go.mod h1:X7qrxNQViEaAN9LNZOPl9PfvQtp3V3c7LTo0dvGi0fM=
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c h1:DjKMC30y6yjG3IxDaeAj3PCoRr+IsO+bzyT+Se2m2Hk=
@@ -199,8 +198,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
@@ -232,8 +232,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
@@ -242,11 +242,11 @@ 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.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -258,17 +258,16 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
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-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"github.com/metacubex/mihomo/common/atomic"
"github.com/puzpuzpuz/xsync/v3"
"github.com/shirou/gopsutil/v3/process"
"github.com/shirou/gopsutil/v4/process"
)
var DefaultManager *Manager
+310 -271
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -11,7 +11,7 @@ authors = ["zzzgydi", "keiko233"]
[workspace.dependencies]
thiserror = "2"
tracing = "0.1"
boa_engine = { version = "0.19.1" }
boa_engine = { version = "0.20" }
[profile.release]
panic = "unwind"
+2 -2
View File
@@ -9,8 +9,8 @@ authors.workspace = true
[dependencies]
rustc-hash = { version = "2", features = ["std"] }
boa_engine.workspace = true
boa_gc = { version = "0.19.1" }
boa_parser = { version = "0.19.1" }
boa_gc = { version = "0.20" }
boa_parser = { version = "0.20" }
isahc = "1.7"
futures-util = "0.3"
smol = "2"
@@ -19,7 +19,7 @@ path = "./src/small.rs"
eframe = "0.29.1"
egui_extras = { version = "*", features = ["all_loaders"] }
parking_lot = "0.12"
image = { version = "0.25", features = ["jpeg", "png"] }
image = { version = "0.25.5", features = ["jpeg", "png"] }
humansize = "2.1.3"
# for svg currentColor replacement
resvg = "0.44.0" # for svg rendering
+2 -2
View File
@@ -117,7 +117,7 @@ single-instance = "0.3.3"
which = "7"
dirs = "5.0.1"
open = "5.0.1"
sysinfo = "0.32"
sysinfo = "0.33"
num_cpus = "1"
tempfile = "3.9.0"
fs_extra = "1.3.0"
@@ -143,7 +143,7 @@ tracing-appender = { version = "0.2", features = ["parking_lot"] }
test-log = { version = "0.2.16", features = ["trace"] }
# Image & Graphics
image = "0.25.0"
image = "0.25.5"
fast_image_resize = "5"
display-info = "0.5.0" # should be removed after upgrading to tauri v2
File diff suppressed because one or more lines are too long
@@ -140,7 +140,7 @@
"identifier": {
"anyOf": [
{
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n",
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n",
"type": "string",
"const": "fs:default"
},
@@ -984,6 +984,11 @@
"type": "string",
"const": "fs:allow-seek"
},
{
"description": "Enables the size command without any pre-configured scope.",
"type": "string",
"const": "fs:allow-size"
},
{
"description": "Enables the stat command without any pre-configured scope.",
"type": "string",
@@ -1109,6 +1114,11 @@
"type": "string",
"const": "fs:deny-seek"
},
{
"description": "Denies the size command without any pre-configured scope.",
"type": "string",
"const": "fs:deny-size"
},
{
"description": "Denies the stat command without any pre-configured scope.",
"type": "string",
@@ -1581,7 +1591,7 @@
"description": "FS scope entry.",
"anyOf": [
{
"description": "FS scope path.",
"description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
"type": "string"
},
{
@@ -1591,7 +1601,7 @@
],
"properties": {
"path": {
"description": "FS scope path.",
"description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
"type": "string"
}
}
@@ -1605,7 +1615,7 @@
"description": "FS scope entry.",
"anyOf": [
{
"description": "FS scope path.",
"description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
"type": "string"
},
{
@@ -1615,7 +1625,7 @@
],
"properties": {
"path": {
"description": "FS scope path.",
"description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
"type": "string"
}
}
@@ -3478,7 +3488,7 @@
"const": "dialog:deny-save"
},
{
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n",
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n",
"type": "string",
"const": "fs:default"
},
@@ -4322,6 +4332,11 @@
"type": "string",
"const": "fs:allow-seek"
},
{
"description": "Enables the size command without any pre-configured scope.",
"type": "string",
"const": "fs:allow-size"
},
{
"description": "Enables the stat command without any pre-configured scope.",
"type": "string",
@@ -4447,6 +4462,11 @@
"type": "string",
"const": "fs:deny-seek"
},
{
"description": "Denies the size command without any pre-configured scope.",
"type": "string",
"const": "fs:deny-size"
},
{
"description": "Denies the stat command without any pre-configured scope.",
"type": "string",
@@ -140,7 +140,7 @@
"identifier": {
"anyOf": [
{
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n",
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n",
"type": "string",
"const": "fs:default"
},
@@ -984,6 +984,11 @@
"type": "string",
"const": "fs:allow-seek"
},
{
"description": "Enables the size command without any pre-configured scope.",
"type": "string",
"const": "fs:allow-size"
},
{
"description": "Enables the stat command without any pre-configured scope.",
"type": "string",
@@ -1109,6 +1114,11 @@
"type": "string",
"const": "fs:deny-seek"
},
{
"description": "Denies the size command without any pre-configured scope.",
"type": "string",
"const": "fs:deny-size"
},
{
"description": "Denies the stat command without any pre-configured scope.",
"type": "string",
@@ -1581,7 +1591,7 @@
"description": "FS scope entry.",
"anyOf": [
{
"description": "FS scope path.",
"description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
"type": "string"
},
{
@@ -1591,7 +1601,7 @@
],
"properties": {
"path": {
"description": "FS scope path.",
"description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
"type": "string"
}
}
@@ -1605,7 +1615,7 @@
"description": "FS scope entry.",
"anyOf": [
{
"description": "FS scope path.",
"description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
"type": "string"
},
{
@@ -1615,7 +1625,7 @@
],
"properties": {
"path": {
"description": "FS scope path.",
"description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
"type": "string"
}
}
@@ -3478,7 +3488,7 @@
"const": "dialog:deny-save"
},
{
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n",
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n",
"type": "string",
"const": "fs:default"
},
@@ -4322,6 +4332,11 @@
"type": "string",
"const": "fs:allow-seek"
},
{
"description": "Enables the size command without any pre-configured scope.",
"type": "string",
"const": "fs:allow-size"
},
{
"description": "Enables the stat command without any pre-configured scope.",
"type": "string",
@@ -4447,6 +4462,11 @@
"type": "string",
"const": "fs:deny-seek"
},
{
"description": "Denies the size command without any pre-configured scope.",
"type": "string",
"const": "fs:deny-size"
},
{
"description": "Denies the stat command without any pre-configured scope.",
"type": "string",
@@ -92,7 +92,7 @@ pub fn collect_envs<'a>() -> Result<EnvInfo<'a>, std::io::Error> {
.trim()
.to_owned(),
),
arch: Cow::Owned(System::cpu_arch().unwrap_or("".to_string())),
arch: Cow::Owned(System::cpu_arch()),
core,
device,
build_info: Cow::Borrowed(&BUILD_INFO),
@@ -14,10 +14,10 @@
"@tauri-apps/api": "2.1.1",
"ahooks": "3.8.4",
"ofetch": "1.4.1",
"react": "rc",
"react": "19.0.0",
"swr": "2.2.5"
},
"devDependencies": {
"@types/react": "18.3.16"
"@types/react": "19.0.1"
}
}
+15 -15
View File
@@ -11,14 +11,14 @@
},
"dependencies": {
"@dnd-kit/core": "6.3.1",
"@dnd-kit/sortable": "9.0.0",
"@dnd-kit/sortable": "10.0.0",
"@dnd-kit/utilities": "3.2.2",
"@emotion/styled": "11.13.5",
"@juggle/resize-observer": "3.4.0",
"@material/material-color-utilities": "0.3.0",
"@mui/icons-material": "6.1.10",
"@mui/lab": "6.0.0-beta.18",
"@mui/material": "6.1.10",
"@mui/icons-material": "6.2.0",
"@mui/lab": "6.0.0-beta.19",
"@mui/material": "6.2.0",
"@nyanpasu/interface": "workspace:^",
"@nyanpasu/ui": "workspace:^",
"@tanstack/router-zod-adapter": "1.81.5",
@@ -32,11 +32,11 @@
"i18next": "24.0.5",
"jotai": "2.10.3",
"json-schema": "0.4.0",
"material-react-table": "3.0.2",
"material-react-table": "3.0.3",
"monaco-editor": "0.52.2",
"mui-color-input": "5.0.1",
"react": "rc",
"react-dom": "rc",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-error-boundary": "4.1.2",
"react-fast-marquee": "1.6.5",
"react-hook-form-mui": "7.4.1",
@@ -45,7 +45,7 @@
"react-split-grid": "1.0.4",
"react-use": "17.5.1",
"swr": "2.2.5",
"virtua": "0.36.3",
"virtua": "0.39.2",
"vite-bundle-visualizer": "1.2.1"
},
"devDependencies": {
@@ -54,8 +54,8 @@
"@emotion/react": "11.13.5",
"@iconify/json": "2.2.282",
"@monaco-editor/react": "4.6.0",
"@tanstack/react-router": "1.87.12",
"@tanstack/router-devtools": "1.87.12",
"@tanstack/react-router": "1.89.0",
"@tanstack/router-devtools": "1.89.0",
"@tanstack/router-plugin": "1.87.13",
"@tauri-apps/plugin-clipboard-manager": "2.2.0",
"@tauri-apps/plugin-dialog": "2.2.0",
@@ -65,8 +65,8 @@
"@tauri-apps/plugin-process": "2.2.0",
"@tauri-apps/plugin-shell": "2.2.0",
"@tauri-apps/plugin-updater": "2.3.0",
"@types/react": "18.3.16",
"@types/react-dom": "18.3.5",
"@types/react": "19.0.1",
"@types/react-dom": "19.0.2",
"@types/validator": "13.12.2",
"@vitejs/plugin-legacy": "6.0.0",
"@vitejs/plugin-react": "4.3.4",
@@ -78,16 +78,16 @@
"meta-json-schema": "1.18.10",
"monaco-yaml": "5.2.3",
"nanoid": "5.0.9",
"sass": "1.82.0",
"sass": "1.83.0",
"shiki": "1.24.2",
"tailwindcss-textshadow": "2.1.3",
"unplugin-auto-import": "0.18.6",
"unplugin-auto-import": "0.19.0",
"unplugin-icons": "0.21.0",
"validator": "13.12.0",
"vite": "6.0.3",
"vite-plugin-sass-dts": "1.3.29",
"vite-plugin-svgr": "4.3.0",
"vite-tsconfig-paths": "5.1.4",
"zod": "3.23.8"
"zod": "3.24.1"
}
}
@@ -2,7 +2,7 @@ import { useDebounceEffect } from "ahooks";
import { useAtomValue } from "jotai";
import { RefObject, useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
import { Virtualizer, VListHandle } from "virtua";
import { Virtualizer, VirtualizerHandle } from "virtua";
import ContentDisplay from "../base/content-display";
import LogItem from "./log-item";
import { atomLogLevel, atomLogList } from "./modules/store";
@@ -16,21 +16,21 @@ export const LogList = ({
const logData = useAtomValue(atomLogList);
const virtualizerRef = useRef<VListHandle>(null);
const virtualizerRef = useRef<VirtualizerHandle>(null);
const shouldStickToBottom = useRef(true);
const isFristScroll = useRef(true);
const isFirstScroll = useRef(true);
useDebounceEffect(
() => {
if (shouldStickToBottom && logData.length) {
virtualizerRef.current?.scrollToIndex(logData.length - 1, {
align: "end",
smooth: !isFristScroll.current,
smooth: !isFirstScroll.current,
});
isFristScroll.current = false;
isFirstScroll.current = false;
}
},
[logData],
@@ -40,10 +40,11 @@ export const LogList = ({
const logLevel = useAtomValue(atomLogLevel);
useEffect(() => {
isFristScroll.current = true;
isFirstScroll.current = true;
}, [logLevel]);
const handleRangeChange = (_start: number, end: number) => {
const handleScroll = (_offset: number) => {
const end = virtualizerRef.current?.findEndIndex() || 0;
if (end + 1 === logData.length) {
shouldStickToBottom.current = true;
} else {
@@ -55,7 +56,7 @@ export const LogList = ({
<Virtualizer
ref={virtualizerRef}
scrollRef={scrollRef}
onRangeChange={handleRangeChange}
onScroll={handleScroll}
>
{logData.map((item, index) => {
return <LogItem key={index} value={item} />;
+7 -7
View File
@@ -17,20 +17,20 @@
},
"dependencies": {
"@material/material-color-utilities": "0.3.0",
"@mui/icons-material": "6.1.10",
"@mui/lab": "6.0.0-beta.18",
"@mui/material": "6.1.10",
"@mui/icons-material": "6.2.0",
"@mui/lab": "6.0.0-beta.19",
"@mui/material": "6.2.0",
"@radix-ui/react-portal": "1.1.3",
"@radix-ui/react-scroll-area": "1.2.2",
"@tauri-apps/api": "2.1.1",
"@types/d3": "7.4.3",
"@types/react": "18.3.16",
"@types/react": "19.0.1",
"@vitejs/plugin-react": "4.3.4",
"ahooks": "3.8.4",
"d3": "7.9.0",
"framer-motion": "12.0.0-alpha.2",
"react": "rc",
"react-dom": "rc",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-error-boundary": "4.1.2",
"react-i18next": "15.1.4",
"react-use": "17.5.1",
@@ -42,7 +42,7 @@
"@types/d3-interpolate-path": "2.0.3",
"clsx": "2.1.1",
"d3-interpolate-path": "2.3.0",
"sass": "1.82.0",
"sass": "1.83.0",
"tailwind-merge": "2.5.5",
"typescript-plugin-css-modules": "5.1.0",
"vite-plugin-dts": "4.3.0"
+5 -7
View File
@@ -64,8 +64,8 @@
"@types/fs-extra": "11.0.4",
"@types/lodash-es": "4.17.12",
"@types/node": "22.10.2",
"@typescript-eslint/eslint-plugin": "8.17.0",
"@typescript-eslint/parser": "8.17.0",
"@typescript-eslint/eslint-plugin": "8.18.0",
"@typescript-eslint/parser": "8.18.0",
"autoprefixer": "10.4.20",
"conventional-changelog-conventionalcommits": "8.0.0",
"cross-env": "7.0.3",
@@ -76,14 +76,14 @@
"eslint-import-resolver-alias": "1.1.2",
"eslint-plugin-html": "8.1.2",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-n": "17.14.0",
"eslint-plugin-n": "17.15.0",
"eslint-plugin-prettier": "5.2.1",
"eslint-plugin-promise": "7.2.1",
"eslint-plugin-react": "7.37.2",
"eslint-plugin-react-compiler": "0.0.0-experimental-fcabbc1-20241106",
"eslint-plugin-react-hooks": "4.6.2",
"knip": "5.40.0",
"lint-staged": "15.2.10",
"lint-staged": "15.2.11",
"npm-run-all2": "7.0.1",
"postcss": "8.4.49",
"postcss-html": "1.7.0",
@@ -110,9 +110,7 @@
},
"pnpm": {
"overrides": {
"vite-plugin-monaco-editor": "npm:vite-plugin-monaco-editor-new@1.1.3",
"@types/react": "npm:types-react@rc",
"@types/react-dom": "npm:types-react-dom@rc"
"vite-plugin-monaco-editor": "npm:vite-plugin-monaco-editor-new@1.1.3"
}
}
}
+625 -606
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,146 @@
From 49c8e854869d673df8452f24dfa8989cd0f615a8 Mon Sep 17 00:00:00 2001
From: Martin Kurbanov <mmkurbanov@salutedevices.com>
Date: Mon, 2 Oct 2023 17:04:58 +0300
Subject: [PATCH] mtd: spinand: add support for FORESEE F35SQA002G
Add support for FORESEE F35SQA002G SPI NAND.
Datasheet:
https://www.longsys.com/uploads/LM-00006FORESEEF35SQA002GDatasheet_1650183701.pdf
Signed-off-by: Martin Kurbanov <mmkurbanov@salutedevices.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20231002140458.147605-1-mmkurbanov@salutedevices.com
---
drivers/mtd/nand/spi/Makefile | 2 +-
drivers/mtd/nand/spi/core.c | 1 +
drivers/mtd/nand/spi/foresee.c | 95 ++++++++++++++++++++++++++++++++++
include/linux/mtd/spinand.h | 1 +
4 files changed, 98 insertions(+), 1 deletion(-)
create mode 100644 drivers/mtd/nand/spi/foresee.c
--- a/drivers/mtd/nand/spi/Makefile
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-spinand-objs := core.o alliancememory.o ato.o esmt.o gigadevice.o macronix.o
+spinand-objs := core.o alliancememory.o ato.o esmt.o foresee.o gigadevice.o macronix.o
spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -940,6 +940,7 @@ static const struct spinand_manufacturer
&alliancememory_spinand_manufacturer,
&ato_spinand_manufacturer,
&esmt_c8_spinand_manufacturer,
+ &foresee_spinand_manufacturer,
&gigadevice_spinand_manufacturer,
&macronix_spinand_manufacturer,
&micron_spinand_manufacturer,
--- /dev/null
+++ b/drivers/mtd/nand/spi/foresee.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ *
+ * Author: Martin Kurbanov <mmkurbanov@salutedevices.com>
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/mtd/spinand.h>
+
+#define SPINAND_MFR_FORESEE 0xCD
+
+static SPINAND_OP_VARIANTS(read_cache_variants,
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
+static SPINAND_OP_VARIANTS(write_cache_variants,
+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
+
+static SPINAND_OP_VARIANTS(update_cache_variants,
+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
+static int f35sqa002g_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ return -ERANGE;
+}
+
+static int f35sqa002g_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section)
+ return -ERANGE;
+
+ /* Reserve 2 bytes for the BBM. */
+ region->offset = 2;
+ region->length = 62;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops f35sqa002g_ooblayout = {
+ .ecc = f35sqa002g_ooblayout_ecc,
+ .free = f35sqa002g_ooblayout_free,
+};
+
+static int f35sqa002g_ecc_get_status(struct spinand_device *spinand, u8 status)
+{
+ struct nand_device *nand = spinand_to_nand(spinand);
+
+ switch (status & STATUS_ECC_MASK) {
+ case STATUS_ECC_NO_BITFLIPS:
+ return 0;
+
+ case STATUS_ECC_HAS_BITFLIPS:
+ return nanddev_get_ecc_conf(nand)->strength;
+
+ default:
+ break;
+ }
+
+ /* More than 1-bit error was detected in one or more sectors and
+ * cannot be corrected.
+ */
+ return -EBADMSG;
+}
+
+static const struct spinand_info foresee_spinand_table[] = {
+ SPINAND_INFO("F35SQA002G",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x72, 0x72),
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(1, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&f35sqa002g_ooblayout,
+ f35sqa002g_ecc_get_status)),
+};
+
+static const struct spinand_manufacturer_ops foresee_spinand_manuf_ops = {
+};
+
+const struct spinand_manufacturer foresee_spinand_manufacturer = {
+ .id = SPINAND_MFR_FORESEE,
+ .name = "FORESEE",
+ .chips = foresee_spinand_table,
+ .nchips = ARRAY_SIZE(foresee_spinand_table),
+ .ops = &foresee_spinand_manuf_ops,
+};
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -263,6 +263,7 @@ struct spinand_manufacturer {
extern const struct spinand_manufacturer alliancememory_spinand_manufacturer;
extern const struct spinand_manufacturer ato_spinand_manufacturer;
extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer;
+extern const struct spinand_manufacturer foresee_spinand_manufacturer;
extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
extern const struct spinand_manufacturer micron_spinand_manufacturer;
@@ -0,0 +1,38 @@
From ae461cde5c559675fc4c0ba351c7c31ace705f56 Mon Sep 17 00:00:00 2001
From: Bohdan Chubuk <chbgdn@gmail.com>
Date: Sun, 10 Nov 2024 22:50:47 +0200
Subject: [PATCH] mtd: spinand: add support for FORESEE F35SQA001G
Add support for FORESEE F35SQA001G SPI NAND.
Similar to F35SQA002G, but differs in capacity.
Datasheet:
- https://cdn.ozdisan.com/ETicaret_Dosya/704795_871495.pdf
Tested on Xiaomi AX3000T flashed with OpenWRT.
Signed-off-by: Bohdan Chubuk <chbgdn@gmail.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
drivers/mtd/nand/spi/foresee.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/mtd/nand/spi/foresee.c
+++ b/drivers/mtd/nand/spi/foresee.c
@@ -81,6 +81,16 @@ static const struct spinand_info foresee
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&f35sqa002g_ooblayout,
f35sqa002g_ecc_get_status)),
+ SPINAND_INFO("F35SQA001G",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x71, 0x71),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(1, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&f35sqa002g_ooblayout,
+ f35sqa002g_ecc_get_status)),
};
static const struct spinand_manufacturer_ops foresee_spinand_manuf_ops = {
@@ -42,9 +42,9 @@ Submitted-by: Daniel Danzberger <daniel@dd-wrt.com>
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-spinand-objs := core.o alliancememory.o ato.o esmt.o gigadevice.o macronix.o
-spinand-objs := core.o alliancememory.o ato.o esmt.o foresee.o gigadevice.o macronix.o
-spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o
+spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o gigadevice.o
+spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o foresee.o gigadevice.o
+spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
--- a/drivers/mtd/nand/spi/core.c
@@ -54,9 +54,9 @@ Submitted-by: Daniel Danzberger <daniel@dd-wrt.com>
&ato_spinand_manufacturer,
&esmt_c8_spinand_manufacturer,
+ &etron_spinand_manufacturer,
&foresee_spinand_manufacturer,
&gigadevice_spinand_manufacturer,
&macronix_spinand_manufacturer,
&micron_spinand_manufacturer,
--- /dev/null
+++ b/drivers/mtd/nand/spi/etron.c
@@ -0,0 +1,98 @@
@@ -165,6 +165,6 @@ Submitted-by: Daniel Danzberger <daniel@dd-wrt.com>
extern const struct spinand_manufacturer ato_spinand_manufacturer;
extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer;
+extern const struct spinand_manufacturer etron_spinand_manufacturer;
extern const struct spinand_manufacturer foresee_spinand_manufacturer;
extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
extern const struct spinand_manufacturer micron_spinand_manufacturer;
@@ -18,18 +18,18 @@ Signed-off-by: Davide Fioravanti <pantanastyle@gmail.com>
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o gigadevice.o
+spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fidelix.o gigadevice.o
-spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o foresee.o gigadevice.o
+spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fidelix.o foresee.o gigadevice.o
spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -941,6 +941,7 @@ static const struct spinand_manufacturer
&alliancememory_spinand_manufacturer,
@@ -942,6 +942,7 @@ static const struct spinand_manufacturer
&ato_spinand_manufacturer,
&esmt_c8_spinand_manufacturer,
+ &fidelix_spinand_manufacturer,
&etron_spinand_manufacturer,
+ &fidelix_spinand_manufacturer,
&foresee_spinand_manufacturer,
&gigadevice_spinand_manufacturer,
&macronix_spinand_manufacturer,
--- /dev/null
@@ -118,6 +118,6 @@ Signed-off-by: Davide Fioravanti <pantanastyle@gmail.com>
extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer;
extern const struct spinand_manufacturer etron_spinand_manufacturer;
+extern const struct spinand_manufacturer fidelix_spinand_manufacturer;
extern const struct spinand_manufacturer foresee_spinand_manufacturer;
extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
extern const struct spinand_manufacturer micron_spinand_manufacturer;
@@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -979,6 +979,56 @@ static int spinand_manufacturer_match(st
@@ -980,6 +980,56 @@ static int spinand_manufacturer_match(st
return -ENOTSUPP;
}
@@ -68,7 +68,7 @@ Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
static int spinand_id_detect(struct spinand_device *spinand)
{
u8 *id = spinand->id.data;
@@ -1229,6 +1279,10 @@ static int spinand_init(struct spinand_d
@@ -1230,6 +1280,10 @@ static int spinand_init(struct spinand_d
if (!spinand->scratchbuf)
return -ENOMEM;
@@ -12,7 +12,7 @@ Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1020,7 +1020,10 @@ int spinand_cal_read(void *priv, u32 *ad
@@ -1021,7 +1021,10 @@ int spinand_cal_read(void *priv, u32 *ad
if (ret)
return ret;
+16 -16
View File
@@ -12,9 +12,9 @@ require (
github.com/go-chi/render v1.0.3
github.com/gobwas/ws v1.4.0
github.com/gofrs/uuid/v5 v5.3.0
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475
github.com/klauspost/compress v1.17.9
github.com/klauspost/cpuid/v2 v2.2.8
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef
github.com/klauspost/compress v1.17.9 // lastest version compatible with golang1.20
github.com/klauspost/cpuid/v2 v2.2.9
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
github.com/mdlayher/netlink v1.7.2
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab
@@ -35,28 +35,28 @@ require (
github.com/miekg/dns v1.1.62
github.com/mroth/weightedrand/v2 v2.1.0
github.com/openacid/low v0.1.21
github.com/oschwald/maxminddb-golang v1.12.0
github.com/oschwald/maxminddb-golang v1.12.0 // lastest version compatible with golang1.20
github.com/puzpuzpuz/xsync/v3 v3.4.0
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.1
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6
github.com/sagernet/sing-shadowtls v0.1.4
github.com/sagernet/sing-mux v0.2.1
github.com/sagernet/sing-shadowtls v0.1.5
github.com/samber/lo v1.47.0
github.com/shirou/gopsutil/v3 v3.24.5
github.com/shirou/gopsutil/v4 v4.24.11
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/stretchr/testify v1.10.0
github.com/vmihailenco/msgpack/v5 v5.4.1
github.com/wk8/go-ordered-map/v2 v2.1.8
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7
go.uber.org/automaxprocs v1.6.0
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.29.0
golang.org/x/crypto v0.31.0
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // lastest version compatible with golang1.20
golang.org/x/net v0.31.0
golang.org/x/sys v0.27.0
google.golang.org/protobuf v1.34.2
golang.org/x/net v0.32.0
golang.org/x/sys v0.28.0
google.golang.org/protobuf v1.34.2 // lastest version compatible with golang1.20
gopkg.in/yaml.v3 v3.0.1
lukechampine.com/blake3 v1.3.0
)
@@ -69,6 +69,7 @@ require (
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/ebitengine/purego v0.8.1 // indirect
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
@@ -82,7 +83,7 @@ require (
github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // 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/kr/text v0.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
@@ -98,7 +99,6 @@ require (
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
@@ -111,8 +111,8 @@ require (
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
go.uber.org/mock v0.4.0 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.24.0 // indirect
)
+27 -28
View File
@@ -27,6 +27,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/enfein/mieru/v3 v3.8.4 h1:PmBQykuEcl8yKcQ647pg8Qbjl433CRYgUbW6VLBgGn4=
github.com/enfein/mieru/v3 v3.8.4/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8=
@@ -70,19 +72,19 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 h1:hxST5pwMBEOWmxpkX20w9oZG+hXdhKmAIPQ3NGGAxas=
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef h1:NzQKDfd5ZOPnuZYf9MnRee8x2qecsVqzsnaLjEZiBko=
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
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/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
@@ -168,19 +170,16 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
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/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 h1:5bCAkvDDzSMITiHFjolBwpdqYsvycdTu71FsMEFXQ14=
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
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-mux v0.2.1 h1:N/3MHymfnFZRd29tE3TaXwPUVVgKvxhtOkiCMLp9HVo=
github.com/sagernet/sing-mux v0.2.1/go.mod h1:dm3BWL6NvES9pbib7llpylrq7Gq+LjlzG+0RacdxcyE=
github.com/sagernet/sing-shadowtls v0.1.5 h1:uXxmq/HXh8DIiBGLzpMjCbWnzIAFs+lIxiTOjdgG5qo=
github.com/sagernet/sing-shadowtls v0.1.5/go.mod h1:tvrDPTGLrSM46Wnf7mSr+L8NHvgvF8M4YnJF790rZX4=
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/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shirou/gopsutil/v4 v4.24.11 h1:WaU9xqGFKvFfsUv94SXcUPD7rCkU0vr/asVdQOBZNj8=
github.com/shirou/gopsutil/v4 v4.24.11/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b h1:rXHg9GrUEtWZhEkrykicdND3VPjlVbYiLdX9J7gimS8=
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b/go.mod h1:X7qrxNQViEaAN9LNZOPl9PfvQtp3V3c7LTo0dvGi0fM=
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c h1:DjKMC30y6yjG3IxDaeAj3PCoRr+IsO+bzyT+Se2m2Hk=
@@ -199,8 +198,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
@@ -232,8 +232,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
@@ -242,11 +242,11 @@ 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.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -258,17 +258,16 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
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-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"github.com/metacubex/mihomo/common/atomic"
"github.com/puzpuzpuz/xsync/v3"
"github.com/shirou/gopsutil/v3/process"
"github.com/shirou/gopsutil/v4/process"
)
var DefaultManager *Manager
@@ -1,11 +1,7 @@
package io.nekohasekai.sagernet.fmt
import android.widget.Toast
import io.nekohasekai.sagernet.IPv6Mode
import io.nekohasekai.sagernet.Key
import io.nekohasekai.sagernet.R
import io.nekohasekai.sagernet.SagerNet
import io.nekohasekai.sagernet.TunImplementation
import io.nekohasekai.sagernet.*
import io.nekohasekai.sagernet.bg.VpnService
import io.nekohasekai.sagernet.database.DataStore
import io.nekohasekai.sagernet.database.ProxyEntity
@@ -27,32 +23,11 @@ import io.nekohasekai.sagernet.fmt.v2ray.StandardV2RayBean
import io.nekohasekai.sagernet.fmt.v2ray.buildSingBoxOutboundStandardV2RayBean
import io.nekohasekai.sagernet.fmt.wireguard.WireGuardBean
import io.nekohasekai.sagernet.fmt.wireguard.buildSingBoxOutboundWireguardBean
import io.nekohasekai.sagernet.ktx.isIpAddress
import io.nekohasekai.sagernet.ktx.mkPort
import io.nekohasekai.sagernet.utils.PackageCache
import moe.matsuri.nb4a.Protocols
import moe.matsuri.nb4a.SingBoxOptions.CacheFile
import moe.matsuri.nb4a.SingBoxOptions.ClashAPIOptions
import moe.matsuri.nb4a.SingBoxOptions.DNSFakeIPOptions
import moe.matsuri.nb4a.SingBoxOptions.DNSOptions
import moe.matsuri.nb4a.SingBoxOptions.DNSRule_DefaultOptions
import moe.matsuri.nb4a.SingBoxOptions.DNSServerOptions
import moe.matsuri.nb4a.SingBoxOptions.ExperimentalOptions
import moe.matsuri.nb4a.SingBoxOptions.Inbound_DirectOptions
import moe.matsuri.nb4a.SingBoxOptions.Inbound_MixedOptions
import moe.matsuri.nb4a.SingBoxOptions.Inbound_TunOptions
import moe.matsuri.nb4a.SingBoxOptions.LogOptions
import moe.matsuri.nb4a.SingBoxOptions.MultiplexOptions
import moe.matsuri.nb4a.SingBoxOptions.MyOptions
import moe.matsuri.nb4a.SingBoxOptions.Outbound
import moe.matsuri.nb4a.SingBoxOptions.Outbound_SelectorOptions
import moe.matsuri.nb4a.SingBoxOptions.Outbound_SocksOptions
import moe.matsuri.nb4a.SingBoxOptions.RouteOptions
import moe.matsuri.nb4a.SingBoxOptions.RuleSet
import moe.matsuri.nb4a.SingBoxOptions.Rule_DefaultOptions
import moe.matsuri.nb4a.SingBoxOptionsUtil
import moe.matsuri.nb4a.checkEmpty
import moe.matsuri.nb4a.generateRuleSet
import moe.matsuri.nb4a.makeSingBoxRule
import moe.matsuri.nb4a.*
import moe.matsuri.nb4a.SingBoxOptions.*
import moe.matsuri.nb4a.plugin.Plugins
import moe.matsuri.nb4a.proxy.config.ConfigBean
import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSBean
@@ -60,6 +35,7 @@ import moe.matsuri.nb4a.proxy.shadowtls.buildSingBoxOutboundShadowTLSBean
import moe.matsuri.nb4a.utils.JavaUtil.gson
import moe.matsuri.nb4a.utils.Util
import moe.matsuri.nb4a.utils.listByLineOrComma
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
const val TAG_MIXED = "mixed-in"
@@ -156,6 +132,7 @@ fun buildConfig(
}.toHashSet().toList()).associateBy { it.id }
val buildSelector = !forTest && group?.isSelector == true && !forExport
val userDNSRuleList = mutableListOf<DNSRule_DefaultOptions>()
val domainListDNSDirectForce = mutableListOf<String>()
val bypassDNSBeans = hashSetOf<AbstractBean>()
val isVPN = DataStore.serviceMode == Key.MODE_VPN
val bind = if (!forTest && DataStore.allowAccess) "0.0.0.0" else LOCALHOST
@@ -434,7 +411,12 @@ fun buildConfig(
}
// domain_strategy
pastEntity?.requireBean()?.apply {
// don't loopback
if (defaultServerDomainStrategy != "" && !serverAddress.isIpAddress()) {
domainListDNSDirectForce.add("full:$serverAddress")
}
}
currentOutbound["domain_strategy"] =
if (forTest) "" else defaultServerDomainStrategy
@@ -667,6 +649,35 @@ fun buildConfig(
}.asMap())
}
// Bypass Lookup for the first profile
bypassDNSBeans.forEach {
var serverAddr = it.serverAddress
if (it is ConfigBean) {
var config = mutableMapOf<String, Any>()
config = gson.fromJson(it.config, config.javaClass)
config["server"]?.apply {
serverAddr = toString()
}
}
if (!serverAddr.isIpAddress()) {
domainListDNSDirectForce.add("full:${serverAddr}")
}
}
remoteDns.forEach {
var address = it
if (address.contains("://")) {
address = address.substringAfter("://")
}
"https://$address".toHttpUrlOrNull()?.apply {
if (!host.isIpAddress()) {
domainListDNSDirectForce.add("full:$host")
}
}
}
// remote dns obj
remoteDns.firstOrNull().let {
dns.servers.add(DNSServerOptions().apply {
@@ -748,11 +759,18 @@ fun buildConfig(
disable_cache = true
})
}
// avoid loopback (always top DNS rule)
// avoid loopback
dns.rules.add(0, DNSRule_DefaultOptions().apply {
outbound = mutableListOf("any")
server = "dns-direct"
})
// force bypass (always top DNS rule)
if (domainListDNSDirectForce.isNotEmpty()) {
dns.rules.add(0, DNSRule_DefaultOptions().apply {
makeSingBoxRule(domainListDNSDirectForce.toHashSet().toList())
server = "dns-direct"
})
}
}
}.let {
ConfigBuildResult(
@@ -180,12 +180,12 @@ local version = {}
<div class="cbi-value">
<label class="cbi-value-title">Passwall <%:Version%></label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<!--div class="cbi-value-description"-->
<span><%=api.get_version()%> 】</span>
<input class="btn cbi-button cbi-button-apply" type="button" id="passwall-check_btn"
onclick="onBtnClick(this,'passwall');" value="<%:Check update%>" />
<span id="passwall-check_btn-detail"></span>
</div>
<!--/div-->
</div>
</div>
@@ -196,14 +196,14 @@ local version = {}
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<!--div class="cbi-value-description"-->
<span><%=version[k] ~="" and version[k] or translate("Null") %> 】</span>
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-check_btn"
onclick="onBtnClick(this,'<%=k%>');" value="<%:Check update%>" />
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-force_btn"
onclick="doUpdate(this,'<%=k%>');" value="<%:Force update%>" style="display:none"/>
<span id="_<%=k%>-check_btn-detail"></span>
</div>
<!--/div-->
</div>
</div>
<%end%>
@@ -52,6 +52,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
color:#8898aa!important;
line-height: 1.8em;
min-height: 48px;
border-radius: 12.375px;
}
.check {
@@ -26,7 +26,7 @@ table td, .table .td {
}
._now_use {
background: #94e1ff !important;
background: #5e72e445 !important;
}
.ping a:hover{
@@ -70,7 +70,7 @@ local geosite_update = api.uci_get_type("global_rules", "geosite_update", "1") =
<input class="cbi-input-checkbox" type="checkbox" name="geosite" value="1" <%=geosite_update%> />
geosite
</label>
<input class="btn cbi-button cbi-button-apply" type="button" id="update_rules_btn" onclick="update_rules(this)" value="<%:Manually update%>" />
<br><br><input class="btn cbi-button cbi-button-apply" type="button" id="update_rules_btn" onclick="update_rules(this)" value="<%:Manually update%>" />
</div>
</div>
</div>
@@ -1913,6 +1913,14 @@ start() {
[ "$(expr $dnsmasq_version \>= 2.90)" == 0 ] && echolog "Dnsmasq版本低于2.90,建议升级至2.90及以上版本以避免部分情况下Dnsmasq崩溃问题!"
}
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
[ "$(uci -q get dhcp.@dnsmasq[0].dns_redirect)" == "1" ] && {
uci -q set dhcp.@dnsmasq[0].dns_redirect='0' 2>/dev/null
uci commit dhcp 2>/dev/null
/etc/init.d/dnsmasq restart >/dev/null 2>&1
}
fi
[ "$ENABLED_DEFAULT_ACL" == 1 ] && {
mkdir -p ${GLOBAL_ACL_PATH}
start_redir TCP
@@ -11,8 +11,10 @@ copy_instance() {
sed -i "/conf-dir/d" $dnsmasq_conf
sed -i "/no-poll/d" $dnsmasq_conf
sed -i "/no-resolv/d" $dnsmasq_conf
sed -i "/server=/d" $dnsmasq_conf
}
echo "port=${listen_port}" >> $dnsmasq_conf
awk '!seen[$0]++' $dnsmasq_conf > /tmp/dnsmasq.tmp && mv /tmp/dnsmasq.tmp $dnsmasq_conf
}
DEFAULT_DNSMASQ_CFGID="$(uci -q show "dhcp.@dnsmasq[0]" | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')"
@@ -327,16 +327,16 @@ load_acl() {
$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
}
else
$ipt_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
fi
[ -n "$tcp_port" -o -n "$udp_port" ] && {
@@ -505,10 +505,10 @@ load_acl() {
$ip6t_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN 2>/dev/null
$ipt_m -A PSW $(comment "默认") -p tcp --dport 53 -j RETURN
$ip6t_m -A PSW $(comment "默认") -p tcp --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
$ipt_n -A PSW_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
$ipt_n -A PSW_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
$ipt_n -A PSW_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
}
fi
@@ -943,8 +943,8 @@ add_firewall_rule() {
[ "${USE_DIRECT_LIST}" = "1" ] && $ipt_n -A PSW_OUTPUT $(dst $IPSET_WHITELIST) -j RETURN
$ipt_n -A PSW_OUTPUT -m mark --mark 0xff -j RETURN
$ipt_n -N PSW_REDIRECT
$ipt_n -I PREROUTING 1 -j PSW_REDIRECT
$ipt_n -N PSW_DNS
$ipt_n -I PREROUTING 1 -j PSW_DNS
$ipt_m -N PSW_DIVERT
$ipt_m -A PSW_DIVERT -j MARK --set-mark 1
@@ -1011,8 +1011,8 @@ add_firewall_rule() {
$ip6t_n -A PSW_OUTPUT -m mark --mark 0xff -j RETURN
}
$ip6t_n -N PSW_REDIRECT
$ip6t_n -I PREROUTING 1 -j PSW_REDIRECT
$ip6t_n -N PSW_DNS
$ip6t_n -I PREROUTING 1 -j PSW_DNS
$ip6t_m -N PSW_DIVERT
$ip6t_m -A PSW_DIVERT -j MARK --set-mark 1
@@ -1316,7 +1316,7 @@ del_firewall_rule() {
$ipt -D $chain $index 2>/dev/null
done
done
for chain in "PSW" "PSW_OUTPUT" "PSW_DIVERT" "PSW_REDIRECT" "PSW_RULE"; do
for chain in "PSW" "PSW_OUTPUT" "PSW_DIVERT" "PSW_DNS" "PSW_RULE"; do
$ipt -F $chain 2>/dev/null
$ipt -X $chain 2>/dev/null
done
@@ -377,16 +377,16 @@ load_acl() {
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
}
else
nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
fi
[ -n "$tcp_port" -o -n "$udp_port" ] && {
@@ -558,10 +558,10 @@ load_acl() {
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp tcp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp tcp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
}
fi
@@ -999,9 +999,9 @@ add_firewall_rule() {
nft "flush chain $NFTABLE_NAME PSW_DIVERT"
nft "add rule $NFTABLE_NAME PSW_DIVERT meta l4proto tcp socket transparent 1 mark set 1 counter accept"
nft "add chain $NFTABLE_NAME PSW_REDIRECT"
nft "flush chain $NFTABLE_NAME PSW_REDIRECT"
nft "add rule $NFTABLE_NAME dstnat jump PSW_REDIRECT"
nft "add chain $NFTABLE_NAME PSW_DNS"
nft "flush chain $NFTABLE_NAME PSW_DNS"
nft "insert rule $NFTABLE_NAME dstnat jump PSW_DNS"
# for ipv4 ipv6 tproxy mark
nft "add chain $NFTABLE_NAME PSW_RULE"
@@ -184,6 +184,9 @@ jobs:
- platform: aarch64_cortex-a72
url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mvebu/cortexa72/openwrt-sdk-23.05.5-mvebu-cortexa72_gcc-12.3.0_musl.Linux-x86_64.tar.xz
- platform: arm_cortex-a5_vfpv4
url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/at91/sama5/openwrt-sdk-23.05.5-at91-sama5_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz
- platform: arm_cortex-a7
url_sdk: https://downloads.openwrt.org/releases/23.05.5/targets/mediatek/mt7629/openwrt-sdk-23.05.5-mediatek-mt7629_gcc-12.3.0_musl_eabi.Linux-x86_64.tar.xz
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
PKG_VERSION:=24.12.12
PKG_RELEASE:=2
PKG_VERSION:=24.12.14
PKG_RELEASE:=1
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
@@ -996,6 +996,7 @@ run_copy_dnsmasq() {
sed -i "/conf-dir/d" $dnsmasq_conf
sed -i "/no-poll/d" $dnsmasq_conf
sed -i "/no-resolv/d" $dnsmasq_conf
sed -i "/server=/d" $dnsmasq_conf
}
local set_type="ipset"
[ "${nftflag}" = "1" ] && {
@@ -1010,6 +1011,7 @@ run_copy_dnsmasq() {
no-poll
no-resolv
EOF
awk '!seen[$0]++' $dnsmasq_conf > /tmp/dnsmasq.tmp && mv /tmp/dnsmasq.tmp $dnsmasq_conf
node_servers=$(uci show "${CONFIG}" | grep -E "(.address=|.download_address=)" | cut -d "'" -f 2)
hosts_foreach "node_servers" host_from_url | grep '[a-zA-Z]$' | sort -u | grep -v "engage.cloudflareclient.com" | gen_dnsmasq_items settype="${set_type}" setnames="${setflag_4}passwall2_vpslist,${setflag_6}passwall2_vpslist6" dnss="${LOCAL_DNS:-${AUTO_DNS}}" outf="${dnsmasq_conf_path}/10-vpslist_host.conf" ipsetoutf="${dnsmasq_conf_path}/ipset.conf"
ln_run "$(first_type dnsmasq)" "dnsmasq_${flag}" "/dev/null" -C $dnsmasq_conf -x $TMP_ACL_PATH/$flag/dnsmasq.pid
@@ -1211,6 +1213,13 @@ start() {
[ "$(expr $dnsmasq_version \>= 2.90)" == 0 ] && echolog "Dnsmasq版本低于2.90,建议升级至2.90及以上版本以避免部分情况下Dnsmasq崩溃问题!"
}
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
[ "$(uci -q get dhcp.@dnsmasq[0].dns_redirect)" == "1" ] && {
uci -q set dhcp.@dnsmasq[0].dns_redirect='0' 2>/dev/null
uci commit dhcp 2>/dev/null
/etc/init.d/dnsmasq restart >/dev/null 2>&1
}
fi
[ "$ENABLED_DEFAULT_ACL" == 1 ] && run_global
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
@@ -387,16 +387,16 @@ load_acl() {
if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$redir_port" ]; then
[ -n "$dns_redirect_port" ] && {
$ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
}
else
$ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
fi
[ "$tcp_proxy_mode" != "disable" ] && [ -n "$redir_port" ] && {
@@ -492,10 +492,10 @@ load_acl() {
if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ "$NODE" != "nil" ]; then
[ -n "$DNS_REDIRECT_PORT" ] && {
$ipt_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
$ipt_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW2_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW2_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
}
fi
@@ -763,8 +763,8 @@ add_firewall_rule() {
$ipt_n -A PSW2_OUTPUT $(dst $IPSET_VPSLIST) -j RETURN
$ipt_n -A PSW2_OUTPUT -m mark --mark 0xff -j RETURN
$ipt_n -N PSW2_REDIRECT
$ipt_n -I PREROUTING 1 -j PSW2_REDIRECT
$ipt_n -N PSW2_DNS
$ipt_n -I PREROUTING 1 -j PSW2_DNS
$ipt_m -N PSW2_DIVERT
$ipt_m -A PSW2_DIVERT -j MARK --set-mark 1
@@ -815,8 +815,8 @@ add_firewall_rule() {
$ip6t_n -A PSW2_OUTPUT -m mark --mark 0xff -j RETURN
}
$ip6t_n -N PSW2_REDIRECT
$ip6t_n -I PREROUTING 1 -j PSW2_REDIRECT
$ip6t_n -N PSW2_DNS
$ip6t_n -I PREROUTING 1 -j PSW2_DNS
$ip6t_m -N PSW2_DIVERT
$ip6t_m -A PSW2_DIVERT -j MARK --set-mark 1
@@ -1007,7 +1007,7 @@ del_firewall_rule() {
$ipt -D $chain $index 2>/dev/null
done
done
for chain in "PSW2" "PSW2_OUTPUT" "PSW2_DIVERT" "PSW2_REDIRECT" "PSW2_RULE"; do
for chain in "PSW2" "PSW2_OUTPUT" "PSW2_DIVERT" "PSW2_DNS" "PSW2_RULE"; do
$ipt -F $chain 2>/dev/null
$ipt -X $chain 2>/dev/null
done
@@ -432,16 +432,16 @@ load_acl() {
if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$redir_port" ]; then
[ -n "$dns_redirect_port" ] && {
nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
}
else
nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
fi
[ "$tcp_proxy_mode" != "disable" ] && [ -n "$redir_port" ] && {
@@ -539,10 +539,10 @@ load_acl() {
if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ "$NODE" != "nil" ]; then
[ -n "$DNS_REDIRECT_PORT" ] && {
nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
}
fi
@@ -806,9 +806,9 @@ add_firewall_rule() {
nft "flush chain $NFTABLE_NAME PSW2_DIVERT"
nft "add rule $NFTABLE_NAME PSW2_DIVERT meta l4proto tcp socket transparent 1 mark set 1 counter accept"
nft "add chain $NFTABLE_NAME PSW2_REDIRECT"
nft "flush chain $NFTABLE_NAME PSW2_REDIRECT"
nft "add rule $NFTABLE_NAME dstnat jump PSW2_REDIRECT"
nft "add chain $NFTABLE_NAME PSW2_DNS"
nft "flush chain $NFTABLE_NAME PSW2_DNS"
nft "insert rule $NFTABLE_NAME dstnat jump PSW2_DNS"
# for ipv4 ipv6 tproxy mark
nft "add chain $NFTABLE_NAME PSW2_RULE"
+15 -15
View File
@@ -751,7 +751,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3"
dependencies = [
"thiserror 2.0.6",
"thiserror 2.0.7",
]
[[package]]
@@ -1348,7 +1348,7 @@ dependencies = [
"rustls",
"rustls-native-certs",
"serde",
"thiserror 2.0.6",
"thiserror 2.0.7",
"tinyvec",
"tokio",
"tokio-native-tls",
@@ -1378,7 +1378,7 @@ dependencies = [
"rustls-native-certs",
"serde",
"smallvec",
"thiserror 2.0.6",
"thiserror 2.0.7",
"tokio",
"tokio-native-tls",
"tokio-rustls",
@@ -2559,7 +2559,7 @@ dependencies = [
"rustc-hash",
"rustls",
"socket2",
"thiserror 2.0.6",
"thiserror 2.0.7",
"tokio",
"tracing",
]
@@ -2578,7 +2578,7 @@ dependencies = [
"rustls",
"rustls-pki-types",
"slab",
"thiserror 2.0.6",
"thiserror 2.0.7",
"tinyvec",
"tracing",
"web-time",
@@ -3175,7 +3175,7 @@ dependencies = [
"shadowsocks-crypto",
"socket2",
"spin",
"thiserror 2.0.6",
"thiserror 2.0.7",
"tokio",
"tokio-tfo",
"trait-variant",
@@ -3243,7 +3243,7 @@ dependencies = [
"snmalloc-rs",
"sysexits",
"tcmalloc",
"thiserror 2.0.6",
"thiserror 2.0.7",
"time",
"tokio",
"tracing",
@@ -3293,7 +3293,7 @@ dependencies = [
"smoltcp",
"socket2",
"spin",
"thiserror 2.0.6",
"thiserror 2.0.7",
"tokio",
"tokio-native-tls",
"tokio-rustls",
@@ -3593,11 +3593,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.6"
version = "2.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47"
checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767"
dependencies = [
"thiserror-impl 2.0.6",
"thiserror-impl 2.0.7",
]
[[package]]
@@ -3613,9 +3613,9 @@ dependencies = [
[[package]]
name = "thiserror-impl"
version = "2.0.6"
version = "2.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312"
checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36"
dependencies = [
"proc-macro2",
"quote",
@@ -3885,7 +3885,7 @@ dependencies = [
"libc",
"log",
"nix",
"thiserror 2.0.6",
"thiserror 2.0.7",
"tokio",
"tokio-util",
"windows-sys 0.59.0",
@@ -4386,7 +4386,7 @@ dependencies = [
"futures",
"libloading",
"log",
"thiserror 2.0.6",
"thiserror 2.0.7",
"windows-sys 0.59.0",
]
+2 -3
View File
@@ -397,8 +397,7 @@ jobs:
- name: Setup Xcode beta
if: matrix.if && github.ref == 'refs/heads/dev-next'
run: |-
sudo xcode-select -s /Applications/Xcode_16.2_Release_Candidate.app || \
sudo xcode-select -s /Applications/Xcode_16.1.app # TODO: remove after hosted runners update
sudo xcode-select -s /Applications/Xcode_16.2.app
- name: Set tag
if: matrix.if
run: |-
@@ -525,7 +524,7 @@ jobs:
path: 'dist'
upload:
name: Upload builds
if: always() && github.event_name == 'workflow_dispatch' && inputs.build != 'publish-android'
if: always() && github.event_name == 'workflow_dispatch' && (inputs.build == 'All' || inputs.build == 'Binary' || inputs.build == 'Android' || inputs.build == 'Apple' || inputs.build == 'macOS-standalone')
runs-on: ubuntu-latest
needs:
- calculate_version
+1 -1
View File
@@ -72,7 +72,7 @@ type InboundContext struct {
UDPConnect bool
UDPTimeout time.Duration
NetworkStrategy C.NetworkStrategy
NetworkStrategy *C.NetworkStrategy
NetworkType []C.InterfaceType
FallbackNetworkType []C.InterfaceType
FallbackDelay time.Duration
+1 -1
View File
@@ -28,7 +28,7 @@ type NetworkManager interface {
}
type NetworkOptions struct {
NetworkStrategy C.NetworkStrategy
NetworkStrategy *C.NetworkStrategy
NetworkType []C.InterfaceType
FallbackNetworkType []C.InterfaceType
FallbackDelay time.Duration
+12 -4
View File
@@ -14,6 +14,7 @@ import (
"github.com/sagernet/sing-box/adapter/outbound"
"github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/common/taskmonitor"
"github.com/sagernet/sing-box/common/tls"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/experimental"
"github.com/sagernet/sing-box/experimental/cachefile"
@@ -149,6 +150,14 @@ func New(options Options) (*Box, error) {
if err != nil {
return nil, E.Cause(err, "initialize router")
}
ntpOptions := common.PtrValueOrDefault(options.NTP)
var timeService *tls.TimeServiceWrapper
if ntpOptions.Enabled {
timeService = new(tls.TimeServiceWrapper)
service.MustRegister[ntp.TimeService](ctx, timeService)
}
for i, endpointOptions := range options.Endpoints {
var tag string
if endpointOptions.Tag != "" {
@@ -254,13 +263,12 @@ func New(options Options) (*Box, error) {
service.MustRegister[adapter.V2RayServer](ctx, v2rayServer)
}
}
ntpOptions := common.PtrValueOrDefault(options.NTP)
if ntpOptions.Enabled {
ntpDialer, err := dialer.New(ctx, ntpOptions.DialerOptions)
if err != nil {
return nil, E.Cause(err, "create NTP service")
}
timeService := ntp.NewService(ntp.Options{
ntpService := ntp.NewService(ntp.Options{
Context: ctx,
Dialer: ntpDialer,
Logger: logFactory.NewLogger("ntp"),
@@ -268,8 +276,8 @@ func New(options Options) (*Box, error) {
Interval: time.Duration(ntpOptions.Interval),
WriteToSystem: ntpOptions.WriteToSystem,
})
service.MustRegister[ntp.TimeService](ctx, timeService)
services = append(services, adapter.NewLifecycleService(timeService, "ntp service"))
timeService.TimeService = ntpService
services = append(services, adapter.NewLifecycleService(ntpService, "ntp service"))
}
return &Box{
network: networkManager,
@@ -11,11 +11,13 @@ import android.net.wifi.WifiManager
import android.os.PowerManager
import androidx.core.content.getSystemService
import go.Seq
import io.nekohasekai.libbox.Libbox
import io.nekohasekai.sfa.bg.AppChangeReceiver
import io.nekohasekai.sfa.bg.UpdateProfileWork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.Locale
import io.nekohasekai.sfa.Application as BoxApplication
class Application : Application() {
@@ -29,6 +31,7 @@ class Application : Application() {
super.onCreate()
Seq.setContext(this)
Libbox.setLocale(Locale.getDefault().toLanguageTag())
@Suppress("OPT_IN_USAGE")
GlobalScope.launch(Dispatchers.IO) {
@@ -77,7 +77,7 @@ class VPNService : VpnService(), PlatformInterfaceWrapper {
}
if (options.autoRoute) {
builder.addDnsServer(options.dnsServerAddress)
builder.addDnsServer(options.dnsServerAddress.value)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val inet4RouteAddress = options.inet4RouteAddress
@@ -1,11 +1,30 @@
package io.nekohasekai.sfa.constant
import android.content.Context
import io.nekohasekai.sfa.R
enum class EnabledType(val boolValue: Boolean) {
Enabled(true), Disabled(false);
fun getString(context: Context): String {
return when (this) {
Enabled -> context.getString(R.string.enabled)
Disabled -> context.getString(R.string.disabled)
}
}
companion object {
fun from(value: Boolean): EnabledType {
return if (value) Enabled else Disabled
}
fun valueOf(context: Context, value: String): EnabledType {
return when (value) {
context.getString(R.string.enabled) -> Enabled
context.getString(R.string.disabled) -> Disabled
else -> Disabled
}
}
}
}
@@ -1,5 +1,7 @@
package io.nekohasekai.sfa.constant
import android.content.Context
import io.nekohasekai.sfa.R
import io.nekohasekai.sfa.database.Settings
enum class PerAppProxyUpdateType {
@@ -11,6 +13,14 @@ enum class PerAppProxyUpdateType {
Deselect -> Settings.PER_APP_PROXY_EXCLUDE
}
fun getString(context: Context): String {
return when (this) {
Disabled -> context.getString(R.string.disabled)
Select -> context.getString(R.string.action_select)
Deselect -> context.getString(R.string.action_deselect)
}
}
companion object {
fun valueOf(value: Int): PerAppProxyUpdateType = when (value) {
Settings.PER_APP_PROXY_DISABLED -> Disabled
@@ -18,5 +28,14 @@ enum class PerAppProxyUpdateType {
Settings.PER_APP_PROXY_EXCLUDE -> Deselect
else -> throw IllegalArgumentException()
}
fun valueOf(context: Context, value: String): PerAppProxyUpdateType {
return when (value) {
context.getString(R.string.disabled) -> Disabled
context.getString(R.string.action_select) -> Select
context.getString(R.string.action_deselect) -> Deselect
else -> Disabled
}
}
}
}
@@ -1,8 +1,11 @@
package io.nekohasekai.sfa.database
import android.content.Context
import android.os.Parcel
import android.os.Parcelable
import androidx.room.TypeConverter
import io.nekohasekai.sfa.R
import io.nekohasekai.sfa.database.TypedProfile.Type.values
import io.nekohasekai.sfa.ktx.marshall
import io.nekohasekai.sfa.ktx.unmarshall
import java.util.Date
@@ -12,6 +15,13 @@ class TypedProfile() : Parcelable {
enum class Type {
Local, Remote;
fun getString(context: Context): String {
return when (this) {
Local -> context.getString(R.string.profile_type_local)
Remote -> context.getString(R.string.profile_type_remote)
}
}
companion object {
fun valueOf(value: Int): Type {
for (it in values()) {
@@ -69,7 +69,7 @@ class SettingsFragment : Fragment() {
}
binding.checkUpdateEnabled.addTextChangedListener {
lifecycleScope.launch(Dispatchers.IO) {
val newValue = EnabledType.valueOf(it).boolValue
val newValue = EnabledType.valueOf(requireContext(), it).boolValue
Settings.checkUpdateEnabled = newValue
}
}
@@ -81,13 +81,13 @@ class SettingsFragment : Fragment() {
}
binding.disableMemoryLimit.addTextChangedListener {
lifecycleScope.launch(Dispatchers.IO) {
val newValue = EnabledType.valueOf(it).boolValue
val newValue = EnabledType.valueOf(requireContext(), it).boolValue
Settings.disableMemoryLimit = !newValue
}
}
binding.dynamicNotificationEnabled.addTextChangedListener {
lifecycleScope.launch(Dispatchers.IO) {
val newValue = EnabledType.valueOf(it).boolValue
val newValue = EnabledType.valueOf(requireContext(), it).boolValue
Settings.dynamicNotification = newValue
}
}
@@ -136,12 +136,15 @@ class SettingsFragment : Fragment() {
val dynamicNotification = Settings.dynamicNotification
withContext(Dispatchers.Main) {
binding.dataSizeText.text = dataSize
binding.checkUpdateEnabled.text = EnabledType.from(checkUpdateEnabled).name
binding.checkUpdateEnabled.text =
EnabledType.from(checkUpdateEnabled).getString(requireContext())
binding.checkUpdateEnabled.setSimpleItems(R.array.enabled)
binding.disableMemoryLimit.text = EnabledType.from(!Settings.disableMemoryLimit).name
binding.disableMemoryLimit.text =
EnabledType.from(!Settings.disableMemoryLimit).getString(requireContext())
binding.disableMemoryLimit.setSimpleItems(R.array.enabled)
binding.backgroundPermissionCard.isGone = removeBackgroundPermissionPage
binding.dynamicNotificationEnabled.text = EnabledType.from(dynamicNotification).name
binding.dynamicNotificationEnabled.text =
EnabledType.from(dynamicNotification).getString(requireContext())
binding.dynamicNotificationEnabled.setSimpleItems(R.array.enabled)
}
}
@@ -67,7 +67,7 @@ class EditProfileActivity : AbstractActivity<ActivityEditProfileBinding>() {
}
}
}
binding.type.text = profile.typed.type.name
binding.type.text = profile.typed.type.getString(this@EditProfileActivity)
binding.editButton.setOnClickListener {
startActivity(
Intent(
@@ -89,7 +89,8 @@ class EditProfileActivity : AbstractActivity<ActivityEditProfileBinding>() {
binding.remoteURL.text = profile.typed.remoteURL
binding.lastUpdated.text =
DateFormat.getDateTimeInstance().format(profile.typed.lastUpdated)
binding.autoUpdate.text = EnabledType.from(profile.typed.autoUpdate).name
binding.autoUpdate.text = EnabledType.from(profile.typed.autoUpdate)
.getString(this@EditProfileActivity)
binding.autoUpdate.setSimpleItems(R.array.enabled)
binding.autoUpdateInterval.isVisible = profile.typed.autoUpdate
binding.autoUpdateInterval.text = profile.typed.autoUpdateInterval.toString()
@@ -111,7 +112,7 @@ class EditProfileActivity : AbstractActivity<ActivityEditProfileBinding>() {
}
private fun updateAutoUpdate(newValue: String) {
val boolValue = EnabledType.valueOf(newValue).boolValue
val boolValue = EnabledType.valueOf(this, newValue).boolValue
if (profile.typed.autoUpdate == boolValue) {
return
}
@@ -49,7 +49,7 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
intent.getStringExtra("importName")?.also { importName ->
intent.getStringExtra("importURL")?.also { importURL ->
binding.name.editText?.setText(importName)
binding.type.text = TypedProfile.Type.Remote.name
binding.type.text = TypedProfile.Type.Remote.getString(this)
binding.remoteURL.editText?.setText(importURL)
binding.localFields.isVisible = false
binding.remoteFields.isVisible = true
@@ -60,12 +60,12 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
binding.name.removeErrorIfNotEmpty()
binding.type.addTextChangedListener {
when (it) {
TypedProfile.Type.Local.name -> {
TypedProfile.Type.Local.getString(this) -> {
binding.localFields.isVisible = true
binding.remoteFields.isVisible = false
}
TypedProfile.Type.Remote.name -> {
TypedProfile.Type.Remote.getString(this) -> {
binding.localFields.isVisible = false
binding.remoteFields.isVisible = true
if (binding.autoUpdateInterval.text.toIntOrNull() == null) {
@@ -99,7 +99,7 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
return
}
when (binding.type.text) {
TypedProfile.Type.Local.name -> {
TypedProfile.Type.Local.getString(this) -> {
when (binding.fileSourceMenu.text) {
FileSource.Import.formatted -> {
if (binding.sourceURL.showErrorIfEmpty()) {
@@ -109,7 +109,7 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
}
}
TypedProfile.Type.Remote.name -> {
TypedProfile.Type.Remote.getString(this) -> {
if (binding.remoteURL.showErrorIfEmpty()) {
return
}
@@ -138,7 +138,7 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
typedProfile.path = configFile.path
when (binding.type.text) {
TypedProfile.Type.Local.name -> {
TypedProfile.Type.Local.getString(this) -> {
typedProfile.type = TypedProfile.Type.Local
when (binding.fileSourceMenu.text) {
@@ -165,7 +165,7 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
}
}
TypedProfile.Type.Remote.name -> {
TypedProfile.Type.Remote.getString(this) -> {
typedProfile.type = TypedProfile.Type.Remote
val remoteURL = binding.remoteURL.text
val content = HTTPClient().use { it.getString(remoteURL) }
@@ -173,7 +173,8 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
configFile.writeText(content)
typedProfile.remoteURL = remoteURL
typedProfile.lastUpdated = Date()
typedProfile.autoUpdate = EnabledType.valueOf(binding.autoUpdate.text).boolValue
typedProfile.autoUpdate =
EnabledType.valueOf(this, binding.autoUpdate.text).boolValue
binding.autoUpdateInterval.text.toIntOrNull()?.also {
typedProfile.autoUpdateInterval = it
}
@@ -304,7 +304,7 @@ class PerAppProxyActivity : AbstractActivity<ActivityPerAppProxyBinding>() {
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.per_app_menu0, menu)
menuInflater.inflate(R.menu.per_app_menu, menu)
if (menu != null) {
val searchView = menu.findItem(R.id.action_search).actionView as SearchView
@@ -33,7 +33,8 @@ class ProfileOverrideActivity :
binding.perAppProxyUpdateOnChange.addTextChangedListener {
lifecycleScope.launch(Dispatchers.IO) {
Settings.perAppProxyUpdateOnChange = PerAppProxyUpdateType.valueOf(it).value()
Settings.perAppProxyUpdateOnChange =
PerAppProxyUpdateType.valueOf(this@ProfileOverrideActivity, it).value()
}
}
@@ -49,7 +50,8 @@ class ProfileOverrideActivity :
val perAppUpdateOnChange = Settings.perAppProxyUpdateOnChange
withContext(Dispatchers.Main) {
binding.perAppProxyUpdateOnChange.text =
PerAppProxyUpdateType.valueOf(perAppUpdateOnChange).name
PerAppProxyUpdateType.valueOf(perAppUpdateOnChange)
.getString(this@ProfileOverrideActivity)
binding.perAppProxyUpdateOnChange.setSimpleItems(R.array.per_app_proxy_update_on_change_value)
}
}
@@ -32,18 +32,18 @@
android:id="@+id/statusContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="horizontal">
<com.google.android.material.card.MaterialCardView
@@ -61,6 +61,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:text="@string/status_status"
android:textAppearance="?attr/textAppearanceTitleSmall">
@@ -150,7 +151,9 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:text="@string/status_connections"
android:textAppearance="?attr/textAppearanceTitleSmall">
@@ -251,6 +254,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:text="@string/status_traffic"
android:textAppearance="?attr/textAppearanceTitleSmall">
@@ -341,6 +345,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:text="@string/status_traffic_total"
android:textAppearance="?attr/textAppearanceTitleSmall">
@@ -10,20 +10,90 @@
app:iconTint="?colorControlNormal"
app:showAsAction="collapseActionView|always" />
<item
android:id="@+id/action_hide_system"
android:title="@string/menu_hide_system" />
<item android:title="@string/per_app_proxy_mode">
<menu>
<group android:checkableBehavior="single">
<item
android:id="@+id/action_mode_include"
android:title="@string/per_app_proxy_mode_include" />
<item
android:id="@+id/action_mode_exclude"
android:title="@string/per_app_proxy_mode_exclude" />
</group>
</menu>
</item>
<item
android:id="@+id/action_scan_china_apps"
android:title="@string/menu_scan_china_apps" />
<item android:title="@string/per_app_proxy_sort_mode">
<menu>
<group android:checkableBehavior="single">
<item
android:id="@+id/action_sort_by_name"
android:title="@string/per_app_proxy_sort_mode_name" />
<item
android:id="@+id/action_sort_by_package_name"
android:title="@string/per_app_proxy_sort_mode_package_name" />
<item
android:id="@+id/action_sort_by_uid"
android:title="@string/per_app_proxy_sort_mode_uid" />
<item
android:id="@+id/action_sort_by_install_time"
android:title="@string/per_app_proxy_sort_mode_install_time" />
<item
android:id="@+id/action_sort_by_update_time"
android:title="@string/per_app_proxy_sort_mode_update_time" />
</group>
<item
android:id="@+id/action_sort_reverse"
android:checkable="true"
android:title="@string/per_app_proxy_sort_mode_reverse" />
</menu>
</item>
<item
android:id="@+id/action_import"
android:title="@string/per_app_proxy_import" />
<item android:title="@string/per_app_proxy_filter">
<menu>
<item
android:id="@+id/action_hide_system_apps"
android:checkable="true"
android:title="@string/per_app_proxy_hide_system_apps" />
<item
android:id="@+id/action_hide_offline_apps"
android:checkable="true"
android:title="@string/per_app_proxy_hide_offline_apps" />
<item
android:id="@+id/action_hide_disabled_apps"
android:checkable="true"
android:title="@string/per_app_proxy_hide_disabled_apps" />
</menu>
</item>
<item
android:id="@+id/action_export"
android:title="@string/per_app_proxy_export" />
<item android:title="@string/action_select">
<menu>
<item
android:id="@+id/action_select_all"
android:title="@string/per_app_proxy_select_all" />
<item
android:id="@+id/action_deselect_all"
android:title="@string/per_app_proxy_select_none" />
</menu>
</item>
<item android:title="@string/per_app_proxy_backup">
<menu>
<item
android:id="@+id/action_import"
android:title="@string/per_app_proxy_import" />
<item
android:id="@+id/action_export"
android:title="@string/per_app_proxy_export" />
</menu>
</item>
<item android:title="@string/per_app_proxy_scan">
<menu>
<item
android:id="@+id/action_scan_china_apps"
android:title="@string/per_app_proxy_scan_china_apps" />
</menu>
</item>
</menu>
@@ -1,99 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_find_in_page_24"
android:title="@string/search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:iconTint="?colorControlNormal"
app:showAsAction="collapseActionView|always" />
<item android:title="@string/per_app_proxy_mode">
<menu>
<group android:checkableBehavior="single">
<item
android:id="@+id/action_mode_include"
android:title="@string/per_app_proxy_mode_include" />
<item
android:id="@+id/action_mode_exclude"
android:title="@string/per_app_proxy_mode_exclude" />
</group>
</menu>
</item>
<item android:title="@string/per_app_proxy_sort_mode">
<menu>
<group android:checkableBehavior="single">
<item
android:id="@+id/action_sort_by_name"
android:title="@string/per_app_proxy_sort_mode_name" />
<item
android:id="@+id/action_sort_by_package_name"
android:title="@string/per_app_proxy_sort_mode_package_name" />
<item
android:id="@+id/action_sort_by_uid"
android:title="@string/per_app_proxy_sort_mode_uid" />
<item
android:id="@+id/action_sort_by_install_time"
android:title="@string/per_app_proxy_sort_mode_install_time" />
<item
android:id="@+id/action_sort_by_update_time"
android:title="@string/per_app_proxy_sort_mode_update_time" />
</group>
<item
android:id="@+id/action_sort_reverse"
android:checkable="true"
android:title="@string/per_app_proxy_sort_mode_reverse" />
</menu>
</item>
<item android:title="@string/per_app_proxy_filter">
<menu>
<item
android:id="@+id/action_hide_system_apps"
android:checkable="true"
android:title="@string/per_app_proxy_hide_system_apps" />
<item
android:id="@+id/action_hide_offline_apps"
android:checkable="true"
android:title="@string/per_app_proxy_hide_offline_apps" />
<item
android:id="@+id/action_hide_disabled_apps"
android:checkable="true"
android:title="@string/per_app_proxy_hide_disabled_apps" />
</menu>
</item>
<item android:title="@string/action_select">
<menu>
<item
android:id="@+id/action_select_all"
android:title="@string/per_app_proxy_select_all" />
<item
android:id="@+id/action_deselect_all"
android:title="@string/per_app_proxy_select_none" />
</menu>
</item>
<item android:title="@string/per_app_proxy_backup">
<menu>
<item
android:id="@+id/action_import"
android:title="@string/per_app_proxy_import" />
<item
android:id="@+id/action_export"
android:title="@string/per_app_proxy_export" />
</menu>
</item>
<item android:title="@string/per_app_proxy_scan">
<menu>
<item
android:id="@+id/action_scan_china_apps"
android:title="@string/per_app_proxy_scan_china_apps" />
</menu>
</item>
</menu>
@@ -1,3 +1,164 @@
<resources>
<string name="stop">停止</string>
<string name="ok"></string>
<string name="no_thanks">不,谢谢</string>
<string name="title_dashboard">仪表</string>
<string name="title_configuration">配置</string>
<string name="title_log">日志</string>
<string name="title_settings">设置</string>
<string name="title_new_profile">新建配置</string>
<string name="title_edit_profile">编辑配置</string>
<string name="title_edit_configuration">编辑配置</string>
<string name="title_overview">概述</string>
<string name="title_groups"></string>
<string name="title_debug">调试</string>
<string name="quick_toggle">切换</string>
<string name="profile_name">名称</string>
<string name="profile_type">类型</string>
<string name="profile_source"></string>
<string name="profile_import_file">导入文件</string>
<string name="profile_create">创建</string>
<string name="profile_edit_content">编辑内容</string>
<string name="profile_check">检查</string>
<string name="profile_share">分享</string>
<string name="profile_share_url">通过二维码分享 URL</string>
<string name="profile_input_required">必须</string>
<string name="profile_empty">无配置</string>
<string name="profile_item_last_updated">最后更新:%s</string>
<string name="profile_last_updated">最后更新</string>
<string name="profile_update">更新</string>
<string name="profile_auto_update">自动更新</string>
<string name="profile_auto_update_interval">自动更新间隔 (分)</string>
<string name="profile_auto_update_interval_minimum_hint">最低值为 15</string>
<string name="profile_type_local">本地</string>
<string name="profile_type_remote">远程</string>
<string name="profile_source_create_new">创建</string>
<string name="profile_source_import">导入</string>
<string name="profile_add_import_file">从文件导入</string>
<string name="profile_add_scan_qr_code">扫描二维码</string>
<string name="profile_add_scan_use_front_camera">前置摄像头</string>
<string name="profile_add_scan_use_vendor_analyzer">使用 MLKit 扫描</string>
<string name="profile_add_scan_enable_torch">灯光</string>
<string name="profile_add_create_manually">手动创建</string>
<string name="menu_undo">撤销</string>
<string name="menu_redo">重做</string>
<string name="menu_format">格式化</string>
<string name="menu_delete">删除</string>
<string name="menu_share">分享</string>
<string name="status_default">服务未启动</string>
<string name="status_starting">服务启动中...</string>
<string name="status_stopping">服务停止中...</string>
<string name="status_started">服务已启动</string>
<string name="enabled">启用</string>
<string name="disabled">禁用</string>
<string name="settings_clear_working_directory">清理工作目录</string>
<string name="error_title">错误</string>
<string name="file_manager_missing">您的设备缺少 Android 标准文件选择器,请安装一个,例如 Material Files。</string>
<string name="loading">加载中...</string>
<string name="service_error_missing_permission">缺少 VPN 权限</string>
<string name="service_error_missing_notification_permission">缺少通知权限</string>
<string name="service_error_empty_configuration">空配置</string>
<string name="service_error_title_start_command_server">启动命令服务器</string>
<string name="service_error_title_create_service">创建服务</string>
<string name="service_error_title_start_service">启动服务</string>
<string name="service_error_title_deprecated_warning">弃用警告</string>
<string name="service_error_deprecated_warning_documentation">文档</string>
<string name="status_status">状态</string>
<string name="status_memory">内存</string>
<string name="status_connections">连接</string>
<string name="status_connections_inbound">入站</string>
<string name="status_connections_outbound">出站</string>
<string name="status_uplink">上传</string>
<string name="status_downlink">下载</string>
<string name="status_traffic">速率</string>
<string name="status_traffic_total">流量</string>
<string name="group_selected_title">选中</string>
<string name="profile">配置</string>
<string name="core_version">版本</string>
<string name="core">核心</string>
<string name="dynamic_notification">在通知中显示实时速度</string>
<string name="core_data_size">数据大小</string>
<string name="check_update_automatic">自动检查更新</string>
<string name="check_update">检查更新</string>
<string name="privacy_policy">隐私政策</string>
<string name="title_app_settings">应用</string>
<string name="memory_limit">内存限制</string>
<string name="background_permission">后台权限</string>
<string name="background_permission_description">申请必要的权限以使 VPN 正常运行。 如果您使用的是中国公司生产的设备,则授予权限后该卡可能不会消失。</string>
<string name="read_more">阅读更多</string>
<string name="request_background_permission">忽略电池优化</string>
<string name="import_remote_profile">导入远程配置</string>
<string name="import_remote_profile_message">您确定要导入远程配置文件 %1$s 吗?您将连接到 %2$s 来下载配置。</string>
<string name="title_profile_override">配置覆盖</string>
<string name="profile_override_description">使用平台特定的值覆盖文件配置项。</string>
<string name="profile_override_configure">配置</string>
<string name="title_per_app_proxy">分应用代理</string>
<string name="per_app_proxy_description">覆盖配置中的 include_package 和 exclude_package。</string>
<string name="per_app_proxy_mode">代理模式</string>
<string name="per_app_proxy_mode_include">白名单</string>
<string name="per_app_proxy_mode_include_description">仅允许选定的应用程序通过 VPN</string>
<string name="per_app_proxy_mode_exclude">黑名单</string>
<string name="per_app_proxy_mode_exclude_description">选定的应用将从 VPN 中排除</string>
<string name="per_app_proxy_action_copy">复制</string>
<string name="per_app_proxy_action_copy_application_label">名称</string>
<string name="per_app_proxy_action_copy_package_name">包名</string>
<string name="per_app_proxy_action_copy_uid">UID</string>
<string name="per_app_proxy_sort_mode">排序</string>
<string name="per_app_proxy_sort_mode_name">名称</string>
<string name="per_app_proxy_sort_mode_package_name">包名</string>
<string name="per_app_proxy_sort_mode_uid">UID</string>
<string name="per_app_proxy_sort_mode_install_time">安装时间</string>
<string name="per_app_proxy_sort_mode_update_time">更新shijian</string>
<string name="per_app_proxy_sort_mode_reverse">反转</string>
<string name="per_app_proxy_filter">过滤</string>
<string name="per_app_proxy_hide_system_apps">隐藏系统应用</string>
<string name="per_app_proxy_hide_offline_apps">隐藏离线应用</string>
<string name="per_app_proxy_hide_disabled_apps">隐藏禁用应用</string>
<string name="per_app_proxy_select">选择</string>
<string name="per_app_proxy_select_all">全选</string>
<string name="per_app_proxy_select_none">全不选</string>
<string name="per_app_proxy_backup">备份</string>
<string name="per_app_proxy_import">从剪切板导入</string>
<string name="per_app_proxy_export">导出到剪切板</string>
<string name="per_app_proxy_scan">扫描</string>
<string name="per_app_proxy_scan_china_apps">中国应用</string>
<string name="content_description_app_icon">App 图标</string>
<string name="toast_clipboard_empty">剪切板为空</string>
<string name="toast_app_list_empty">应用列表为空</string>
<string name="toast_copied_to_clipboard">已导出到剪切板</string>
<string name="toast_imported_from_clipboard">已从剪贴板导入</string>
<string name="message_import_from_clipboard">从剪贴板导入应用列表将覆盖当前列表。您确定要继续吗?</string>
<string name="message_scanning">扫描中...</string>
<string name="message_scan_app_error">扫描应用程序时出错</string>
<string name="message_scan_app_no_apps_found">未找到匹配的应用</string>
<string name="message_scan_app_found">找到以下应用程序,请选择您想要的操作。</string>
<string name="title_scan_result">扫描结果</string>
<string name="action_select">选择</string>
<string name="action_deselect">取消选择</string>
<string name="per_app_proxy_update_on_change">新中国应用安装时更新</string>
<string name="import_profile">导入配置</string>
<string name="import_profile_message">您确定要导入配置文件 %s 吗?</string>
<string name="icloud_profile_unsupported">当前平台不支持 iCloud 配置文件</string>
<string name="search">搜索</string>
<string name="expand">展开</string>
<string name="http_proxy">HTTP 代理</string>
<string name="title_scan_vpn">扫描 VPN 应用</string>
<string name="message_scan_vpn">检查设备上安装的 VPN 及其内容</string>
<string name="action_scan_vpn">扫描</string>
<string name="message_debug_tools">一些调试工具</string>
<string name="action_open">打开</string>
<string name="vpn_app_type">应用类型</string>
<string name="vpn_core_type">核心类型</string>
<string name="vpn_core_path">发现路径</string>
<string name="vpn_golang_version">Go 版本</string>
<string name="vpn_app_type_other">其他</string>
<string name="vpn_core_type_unknown">未知</string>
<string name="no_updates_available">没有可用更新</string>
<string name="sponsor">赞助</string>
<string name="sponsor_message">支持我的工作</string>
<string name="action_start">启动</string>
<string name="location_permission_title">位置权限</string>
<string name="location_permission_description"><![CDATA[您的个人资料包含 <strong><tt>wifi_ssid</tt> 或 <tt>wifi_bssid</tt> 路由规则</strong>。为了使它们正常工作,sing-box 在<strong>后台</strong>使用 <strong>位置</strong> 权限来获取有关所连接 Wi-Fi 网络的信息。该信息将<strong>仅用于路由目的</strong>。]]></string>
<string name="location_permission_background_description"><![CDATA[在 Android 10 及更高版本中,需要<strong>后台位置</strong>权限。选择<strong>始终允许</strong>以授予权限。]]></string>
<string name="open_settings">打开设置</string>
</resources>
@@ -1,5 +1,5 @@
<resources>
<string name="app_name">sing-box</string>
<string name="app_name" translatable="false">sing-box</string>
<string name="stop">Stop</string>
<string name="ok">OK</string>
@@ -20,7 +20,7 @@
<string name="profile_name">Name</string>
<string name="profile_type">Type</string>
<string name="profile_source">Source</string>
<string name="profile_url">URL</string>
<string name="profile_url" translatable="false">URL</string>
<string name="profile_import_file">Import File</string>
<string name="profile_create">Create</string>
<string name="profile_edit_content">Edit Content</string>
@@ -69,8 +69,8 @@
<string name="file_manager_missing">Your device lacks an Android standard file selector, please install one, such as Material Files.</string>
<string name="loading">Loading…</string>
<string name="service_error_missing_permission">Failed to request VPN permission</string>
<string name="service_error_missing_notification_permission">Failed to request notification permission</string>
<string name="service_error_missing_permission">Missiong VPN permission</string>
<string name="service_error_missing_notification_permission">Missing notification permission</string>
<string name="service_error_empty_configuration">Empty configuration</string>
<string name="service_error_title_start_command_server">Start command server</string>
<string name="service_error_title_create_service">Create service</string>
@@ -80,7 +80,7 @@
<string name="status_status">Status</string>
<string name="status_memory">Memory</string>
<string name="status_goroutines">Goroutines</string>
<string name="status_goroutines" translatable="false">Goroutines</string>
<string name="status_connections">Connections</string>
<string name="status_connections_inbound">Inbound</string>
<string name="status_connections_outbound">Outbound</string>
@@ -124,7 +124,7 @@
<string name="per_app_proxy_action_copy_package_name">Package Name</string>
<string name="per_app_proxy_action_copy_uid">UID</string>
<string name="per_app_proxy_sort_mode">Sort Mode</string>
<string name="per_app_proxy_sort_mode">Sort By</string>
<string name="per_app_proxy_sort_mode_name">By name</string>
<string name="per_app_proxy_sort_mode_package_name">By package name</string>
<string name="per_app_proxy_sort_mode_uid">By UID</string>
@@ -149,9 +149,6 @@
<string name="per_app_proxy_scan_china_apps">China apps</string>
<string name="content_description_app_icon">App icon</string>
<string name="menu_hide_system">Hide system apps</string>
<string name="menu_show_system">Show system apps</string>
<string name="menu_scan_china_apps">Scan China apps</string>
<string name="toast_clipboard_empty">Clipboard is empty</string>
<string name="toast_app_list_empty">App list is empty</string>
<string name="toast_copied_to_clipboard">Exported to clipboard</string>
@@ -169,7 +166,7 @@
<string name="import_profile_message">Are you sure to import profile %s?</string>
<string name="icloud_profile_unsupported">iCloud profile is not support on current platform</string>
<string name="search">Search</string>
<string name="urltest">URLTest</string>
<string name="urltest" translatable="false">URLTest</string>
<string name="expand">Expand</string>
<string name="http_proxy">HTTP Proxy</string>
<string name="title_scan_vpn">Scan VPN apps</string>
@@ -185,9 +182,7 @@
<string name="vpn_core_type_unknown">Unknown</string>
<string name="no_updates_available">No updates available</string>
<string name="sponsor">Sponsor</string>
<string name="sponsor_play">Sponsor via Play Store</string>
<string name="sponsor_message">If I\'ve defended your modern life, please consider sponsoring me.</string>
<string name="other_methods">Other methods</string>
<string name="action_start">Start</string>
<string name="location_permission_title">Location permission</string>
<string name="location_permission_description"><![CDATA[Your profile contains <strong><tt>wifi_ssid</tt> or <tt>wifi_bssid</tt> routing rules</strong>. To make them work, sing-box uses the <strong>location</strong> permission <strong>in the background</strong> to get information about the connected Wi-Fi network. The information will be used <strong>for routing purposes only</strong>.]]></string>
@@ -0,0 +1,12 @@
import Foundation
import SwiftUI
public extension Bool {
func toString() -> String {
if self {
return String(localized: "true")
} else {
return String(localized: "false")
}
}
}
@@ -20,8 +20,8 @@ public struct ConnectionDetailsView: View {
if let closedAt = connection.closedAt {
FormTextItem("Closed At", closedAt.myFormat)
}
FormTextItem("Upload", LibboxFormatBytes(connection.uploadTotal))
FormTextItem("Download", LibboxFormatBytes(connection.downloadTotal))
FormTextItem("Uplink", LibboxFormatBytes(connection.uploadTotal))
FormTextItem("Downlink", LibboxFormatBytes(connection.downloadTotal))
Section("Metadata") {
FormTextItem("Inbound", connection.inbound)
FormTextItem("Inbound Type", connection.inboundType)
@@ -31,11 +31,11 @@ public extension DashboardPage {
var title: String {
switch self {
case .overview:
return NSLocalizedString("Overview", comment: "")
return String(localized: "Overview")
case .groups:
return NSLocalizedString("Groups", comment: "")
return String(localized: "Groups")
case .connections:
return NSLocalizedString("Connections", comment: "")
return String(localized: "Connections")
}
}
@@ -183,7 +183,7 @@ public struct DashboardView: View {
await MainActor.run {
alert = Alert(
title: Text("Full Disk Access permission is required"),
message: Text("Please grant the permission for SFMExtension, then we can continue."),
message: Text("Please grant the permission for **SFMExtension**, then we can continue."),
primaryButton: .default(Text("Authorize"), action: openFDASettings),
secondaryButton: .cancel()
)
@@ -27,49 +27,49 @@ public struct ExtensionStatusView: View {
VStack {
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: columnCount), alignment: .leading) {
if ApplicationLibrary.inPreview {
StatusItem("Status") {
StatusLine("Memory", "6.4 MB")
StatusLine("Goroutines", "89")
StatusItem(String(localized: "Status")) {
StatusLine(String(localized: "Memory"), "6.4 MB")
StatusLine(String(localized: "Goroutines"), "89")
}
StatusItem("Connections") {
StatusLine("Inbound", "34")
StatusLine("Outbound", "28")
StatusItem(String(localized: "Connections")) {
StatusLine(String(localized: "Inbound"), "34")
StatusLine(String(localized: "Outbound"), "28")
}
StatusItem("Traffic") {
StatusLine("Uplink", "38 B/s")
StatusLine("Downlink", "249 MB/s")
StatusItem(String(localized: "Traffic")) {
StatusLine(String(localized: "Uplink"), "38 B/s")
StatusLine(String(localized: "Downlink"), "249 MB/s")
}
StatusItem("TrafficTotal") {
StatusLine("Uplink", "52 MB")
StatusLine("Downlink", "5.6 GB")
StatusItem(String(localized: "Traffic Total")) {
StatusLine(String(localized: "Uplink"), "52 MB")
StatusLine(String(localized: "Downlink"), "5.6 GB")
}
} else if let message = commandClient.status {
StatusItem("Status") {
StatusLine("Memory", LibboxFormatMemoryBytes(message.memory))
StatusLine("Goroutines", "\(message.goroutines)")
StatusItem(String(localized: "Status")) {
StatusLine(String(localized: "Memory"), LibboxFormatMemoryBytes(message.memory))
StatusLine(String(localized: "Goroutines"), "\(message.goroutines)")
}
StatusItem("Connections") {
StatusLine("Inbound", "\(message.connectionsIn)")
StatusLine("Outbound", "\(message.connectionsOut)")
StatusItem(String(localized: "Connections")) {
StatusLine(String(localized: "Inbound"), "\(message.connectionsIn)")
StatusLine(String(localized: "Outbound"), "\(message.connectionsOut)")
}
if message.trafficAvailable {
StatusItem("Traffic") {
StatusLine("Uplink", "\(LibboxFormatBytes(message.uplink))/s")
StatusLine("Downlink", "\(LibboxFormatBytes(message.downlink))/s")
StatusItem(String(localized: "Traffic")) {
StatusLine(String(localized: "Uplink"), "\(LibboxFormatBytes(message.uplink))/s")
StatusLine(String(localized: "Downlink"), "\(LibboxFormatBytes(message.downlink))/s")
}
StatusItem("Traffic Total") {
StatusLine("Uplink", LibboxFormatBytes(message.uplinkTotal))
StatusLine("Downlink", LibboxFormatBytes(message.downlinkTotal))
StatusItem(String(localized: "Traffic Total")) {
StatusLine(String(localized: "Uplink"), LibboxFormatBytes(message.uplinkTotal))
StatusLine(String(localized: "Downlink"), LibboxFormatBytes(message.downlinkTotal))
}
}
} else {
StatusItem("Status") {
StatusLine("Memory", "...")
StatusLine("Goroutines", "...")
StatusItem(String(localized: "Status")) {
StatusLine(String(localized: "Memory"), "...")
StatusLine(String(localized: "Goroutines"), "...")
}
StatusItem("Connections") {
StatusLine("Inbound", "...")
StatusLine("Outbound", "...")
StatusItem(String(localized: "Connections")) {
StatusLine(String(localized: "Inbound"), "...")
StatusLine(String(localized: "Outbound"), "...")
}
}
}.background {
@@ -26,7 +26,7 @@
do {
if let result = try await SystemExtension.install() {
if result == .willCompleteAfterReboot {
alert = Alert(errorMessage: "Need Reboot")
alert = Alert(errorMessage: String(localized: "Need Reboot"))
}
}
await callback()
@@ -32,19 +32,19 @@ public extension NavigationPage {
var title: String {
switch self {
case .dashboard:
return NSLocalizedString("Dashboard", comment: "")
return String(localized: "Dashboard")
#if os(macOS)
case .groups:
return NSLocalizedString("Groups", comment: "")
return String(localized: "Groups")
case .connections:
return NSLocalizedString("Connections", comment: "")
#endif
case .logs:
return NSLocalizedString("Logs", comment: "")
return String(localized: "Logs")
case .profiles:
return NSLocalizedString("Profiles", comment: "")
return String(localized: "Profiles")
case .settings:
return NSLocalizedString("Settings", comment: "")
return String(localized: "Settings")
}
}
@@ -104,9 +104,9 @@
private var navigationTitle: String {
if readOnly {
return "View Content"
return String(localized: "View Content")
} else {
return "Edit Content"
return String(localized: "Edit Content")
}
}
@@ -17,7 +17,7 @@ public struct EditProfileView: View {
public init() {}
public var body: some View {
FormView {
FormItem("Name") {
FormItem(String(localized: "Name")) {
TextField("Name", text: $profile.name, prompt: Text("Required"))
.multilineTextAlignment(.trailing)
}
@@ -31,17 +31,17 @@ public struct EditProfileView: View {
}
.disabled(true)
if profile.type == .icloud {
FormItem("Path") {
FormItem(String(localized: "Path")) {
TextField("Path", text: $profile.path, prompt: Text("Required"))
.multilineTextAlignment(.trailing)
}
} else if profile.type == .remote {
FormItem("URL") {
FormItem(String(localized: "URL")) {
TextField("URL", text: $profile.remoteURL.unwrapped(""), prompt: Text("Required"))
.multilineTextAlignment(.trailing)
}
Toggle("Auto Update", isOn: $profile.autoUpdate)
FormItem("Auto Update Interval") {
FormItem(String(localized: "Auto Update Interval")) {
TextField("Auto Update Interval", text: $profile.autoUpdateInterval.stringBinding(defaultValue: 60), prompt: Text("In Minutes"))
.multilineTextAlignment(.trailing)
#if os(iOS)
@@ -34,7 +34,7 @@ public struct NewProfileView: View {
public var body: some View {
FormView {
FormItem("Name") {
FormItem(String(localized: "Name")) {
TextField("Name", text: $profileName, prompt: Text("Required"))
.multilineTextAlignment(.trailing)
}
@@ -76,17 +76,17 @@ public struct NewProfileView: View {
}
}
} else if profileType == .icloud {
FormItem("Path") {
FormItem(String(localized: "Path")) {
TextField("Path", text: $remotePath, prompt: Text("Required"))
.multilineTextAlignment(.trailing)
}
} else if profileType == .remote {
FormItem("URL") {
FormItem(String(localized: "URL")) {
TextField("URL", text: $remotePath, prompt: Text("Required"))
.multilineTextAlignment(.trailing)
}
Toggle("Auto Update", isOn: $autoUpdate)
FormItem("Auto Update Interval") {
FormItem(String(localized: "Auto Update Interval")) {
TextField("Auto Update Interval", text: $autoUpdateInterval.stringBinding(defaultValue: 60), prompt: Text("In Minutes"))
.multilineTextAlignment(.trailing)
#if os(iOS)
@@ -135,15 +135,15 @@ public struct NewProfileView: View {
isSaving = false
}
if profileName.isEmpty {
alert = Alert(errorMessage: "Missing profile name")
alert = Alert(errorMessage: String(localized: "Missing profile name"))
return
}
if remotePath.isEmpty {
if profileType == .icloud {
alert = Alert(errorMessage: "Missing path")
alert = Alert(errorMessage: String(localized: "Missing path"))
return
} else if profileType == .remote {
alert = Alert(errorMessage: "Missing URL")
alert = Alert(errorMessage: String(localized: "Missing URL"))
return
}
}
@@ -130,7 +130,7 @@ public struct ProfileView: View {
#if os(iOS)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton().disabled(profileList.isEmpty)
EditButton().disabled(profileList.isEmpty && !editMode.isEditing)
}
}
#elseif os(tvOS)
@@ -1,30 +1,33 @@
import Library
import SwiftUI
#if os(macOS)
import AppKit
import Library
import ServiceManagement
import SwiftUI
#endif
public struct MacAppView: View {
@State private var isLoading = true
public struct AppView: View {
@State private var isLoading = true
@State private var startAtLogin = false
@Environment(\.showMenuBarExtra) private var showMenuBarExtra
@State private var menuBarExtraInBackground = false
@State private var startAtLogin = false
@Environment(\.showMenuBarExtra) private var showMenuBarExtra
@State private var menuBarExtraInBackground = false
@State private var alert: Alert?
@State private var alert: Alert?
public init() {}
public var body: some View {
viewBuilder {
if isLoading {
ProgressView().onAppear {
Task {
await loadSettings()
}
public init() {}
public var body: some View {
viewBuilder {
if isLoading {
ProgressView().onAppear {
Task {
await loadSettings()
}
} else {
FormView {
}
} else {
FormView {
#if os(macOS)
FormToggle("Start At Login", "Launch the application when the system is logged in. If enabled at the same time as `Show in Menu Bar` and `Keep Menu Bar in Background`, the application interface will not be opened automatically.", $startAtLogin) { newValue in
updateLoginItems(newValue)
}
@@ -66,21 +69,26 @@
}
}
}
}
#endif
}
}
.alertBinding($alert)
.navigationTitle("App")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}
.alertBinding($alert)
.navigationTitle("App")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}
private func loadSettings() async {
private func loadSettings() async {
#if os(macOS)
startAtLogin = SMAppService.mainApp.status == .enabled
menuBarExtraInBackground = await SharedPreferences.menuBarExtraInBackground.get()
isLoading = false
}
#endif
isLoading = false
}
#if os(macOS)
private func updateLoginItems(_ startAtLogin: Bool) {
do {
@@ -143,6 +151,6 @@
alert = Alert(error)
}
}
}
#endif
#endif
}
@@ -87,11 +87,11 @@ public struct ServiceLogView: View {
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
var deviceInfo = "Machine: " + machineName + "\n"
var deviceInfo = String("Machine: ") + machineName + "\n"
#if os(iOS)
await deviceInfo += "System: " + (UIDevice.current.systemName) + " " + (UIDevice.current.systemVersion) + "\n"
await deviceInfo += String("System: ") + (UIDevice.current.systemName) + " " + (UIDevice.current.systemVersion) + "\n"
#elseif os(macOS)
deviceInfo += "System: macOS " + ProcessInfo().operatingSystemVersionString + "\n"
deviceInfo += String("System: ") + "macOS " + ProcessInfo().operatingSystemVersionString + "\n"
#endif
content = deviceInfo + "\n" + content
}
@@ -22,18 +22,18 @@ public struct SettingView: View {
switch self {
#if os(macOS)
case .app:
return NSLocalizedString("App", comment: "")
return String(localized: "App")
#endif
case .core:
return NSLocalizedString("Core", comment: "")
return String(localized: "Core")
case .packetTunnel:
return NSLocalizedString("Packet Tunnel", comment: "")
return String(localized: "Packet Tunnel")
case .onDemandRules:
return NSLocalizedString("On Demand Rules", comment: "")
return String(localized: "On Demand Rules")
case .profileOverride:
return NSLocalizedString("Profile Override", comment: "")
return String(localized: "Profile Override")
case .sponsors:
return NSLocalizedString("Sponsors", comment: "")
return String(localized: "Sponsors")
}
}
@@ -62,7 +62,7 @@ public struct SettingView: View {
switch self {
#if os(macOS)
case .app:
MacAppView()
AppView()
#endif
case .core:
CoreView()
@@ -106,11 +106,29 @@ public struct SettingView: View {
}
#if !os(tvOS)
Section("About") {
Link(destination: URL(string: "https://sing-box.sagernet.org/")!) {
Link(destination: URL(string: String(localized: "https://sing-box.sagernet.org/"))!) {
Label("Documentation", systemImage: "doc.on.doc.fill")
}
.buttonStyle(.plain)
.foregroundColor(.accentColor)
.contextMenu {
Link(destination: URL(string: String(localized: "https://sing-box.sagernet.org/changelog/"))!) {
Text("Changelog")
}
Link(destination: URL(string: String(localized: "https://sing-box.sagernet.org/configuration/"))!) {
Text("Configuration")
}
}
Link(destination: URL(string: String("https://github.com/SagerNet/sing-box"))!) {
Label("Source Code", systemImage: "pills.fill")
}
.buttonStyle(.plain)
.foregroundColor(.accentColor)
.contextMenu {
Link(destination: URL(string: String("https://github.com/SagerNet/sing-box/releases"))!) {
Text("Releases")
}
}
RequestReviewButton {
Label("Rate on the App Store", systemImage: "text.bubble.fill")
}
@@ -145,7 +163,7 @@ public struct SettingView: View {
}
}
} else {
Text(taiwanFlagAvailable.description)
Text(taiwanFlagAvailable.toString())
}
}
}
@@ -14,10 +14,10 @@ public struct SponsorsView: View {
.frame(maxWidth: .infinity, alignment: .leading)
}
FormButton("GitHub Sponsor (recommended)") {
FormButton(String(localized: "GitHub Sponsors (recommended)")) {
openURL(URL(string: "https://github.com/sponsors/nekohasekai")!)
}
FormButton("Other methods") {
FormButton(String(localized: "Other methods")) {
openURL(URL(string: "https://sekai.icu/sponsors/")!)
}
}
@@ -1,6 +1,8 @@
import Foundation
public enum SharedPreferences {
public static let language = Preference<String>("language", defaultValue: "")
public static let selectedProfileID = Preference<Int64>("selected_profile_id", defaultValue: -1)
#if os(macOS)
@@ -35,12 +35,8 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc
if options.getAutoRoute() {
settings.mtu = NSNumber(value: options.getMTU())
var error: NSError?
let dnsServer = options.getDNSServerAddress(&error)
if let error {
throw error
}
let dnsSettings = NEDNSSettings(servers: [dnsServer])
let dnsServer = try options.getDNSServerAddress()
let dnsSettings = NEDNSSettings(servers: [dnsServer.value])
dnsSettings.matchDomains = [""]
dnsSettings.matchDomainsNoSearch = true
settings.dnsSettings = dnsSettings
File diff suppressed because it is too large Load Diff
@@ -9,6 +9,7 @@ open class ApplicationDelegate: NSObject, NSApplicationDelegate, UNUserNotificat
public func applicationDidFinishLaunching(_: Notification) {
NSLog("Here I stand")
LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false)
LibboxSetLocale(Locale.current.identifier)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.setNotificationCategories([
UNNotificationCategory(
@@ -78,7 +78,7 @@ public struct MainView: View {
await importURLProfile(url)
}
} else {
alert = Alert(errorMessage: "Handled unknown URL \(url.absoluteString)")
alert = Alert(errorMessage: String(localized: "Handled unknown URL \(url.absoluteString)"))
}
}
@@ -105,7 +105,7 @@ public struct MainView: View {
if directoryName != "Applications" {
alert = Alert(
title: Text("Wrong application location"),
message: Text("This app needs to be placed under ~/Applications to work."),
message: Text("This app needs to be placed under the Applications folder to work."),
dismissButton: .default(Text("Ok")) {
NSWorkspace.shared.selectFile(Bundle.main.bundlePath, inFileViewerRootedAtPath: "")
NSApp.terminate(nil)
@@ -140,7 +140,7 @@ public struct MenuView: View {
if profileList.isEmpty {
Text("Empty profiles")
} else {
MenuSection("Profile")
MenuSection(String(localized: "Profile"))
Picker("", selection: selectedProfileIDLocal) {
ForEach(profileList, id: \.id) { profile in
Text(profile.name)
@@ -12,6 +12,7 @@ class ApplicationDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCe
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
NSLog("Here I stand")
LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false)
LibboxSetLocale(Locale.current.identifier)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.setNotificationCategories([
UNNotificationCategory(
+1 -1
View File
@@ -76,7 +76,7 @@ struct MainView: View {
selection = .profiles
}
} else {
alert = Alert(errorMessage: "Handled unknown URL \(url.absoluteString)")
alert = Alert(errorMessage: String(localized: "Handled unknown URL \(url.absoluteString)"))
}
}
}
@@ -8,6 +8,7 @@ class ApplicationDelegate: NSObject, UIApplicationDelegate {
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
NSLog("Here I stand")
LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, true)
LibboxSetLocale(Locale.current.identifier)
setup()
return true
}
@@ -84,6 +84,7 @@
3A7701702A4E6B34008F031F /* IntentsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A77016F2A4E6B34008F031F /* IntentsExtension.swift */; };
3A7701722A4E6B34008F031F /* Intents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7701712A4E6B34008F031F /* Intents.swift */; };
3A7904502B6E7BAC006C08D5 /* SponsorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A79044F2B6E7BAC006C08D5 /* SponsorsView.swift */; };
3A7C8B452D0C81E10070EE55 /* StringCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7C8B442D0C81DC0070EE55 /* StringCompat.swift */; };
3A7E90352A46756300D53052 /* SharedPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7E90342A46756300D53052 /* SharedPreferences.swift */; };
3A7E90382A46778E00D53052 /* BinaryCodable in Frameworks */ = {isa = PBXBuildFile; productRef = 3A7E90372A46778E00D53052 /* BinaryCodable */; };
3A8655142A4FA26600B7181F /* IntentsExtension.appex in Embed ExtensionKit Extensions */ = {isa = PBXBuildFile; fileRef = 3A77016D2A4E6B34008F031F /* IntentsExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@@ -164,6 +165,13 @@
3AF342A02A4A9916002B34AC /* ExtensionProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF3429F2A4A9916002B34AC /* ExtensionProfile.swift */; };
3AF3A3D22B2207F3001FD7C1 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF3A3D12B2207E1001FD7C1 /* libresolv.tbd */; };
3AF5E3E72B6F90640058B9E8 /* ProfileOverrideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF5E3E62B6F90640058B9E8 /* ProfileOverrideView.swift */; };
9C37F17D2C131100001B9FA8 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */; };
9C37F17E2C131100001B9FA8 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */; };
9C37F17F2C131100001B9FA8 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */; };
9C37F1812C131100001B9FA8 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */; };
9C37F1822C131100001B9FA8 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */; };
9C37F1832C131100001B9FA8 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */; };
9C37F1842C131100001B9FA8 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -521,6 +529,7 @@
3A7701732A4E6B34008F031F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3A7701802A4E71F5008F031F /* IntentsExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IntentsExtension.entitlements; sourceTree = "<group>"; };
3A79044F2B6E7BAC006C08D5 /* SponsorsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorsView.swift; sourceTree = "<group>"; };
3A7C8B442D0C81DC0070EE55 /* StringCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringCompat.swift; sourceTree = "<group>"; };
3A7E90302A46745A00D53052 /* ViewBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewBuilder.swift; sourceTree = "<group>"; };
3A7E90342A46756300D53052 /* SharedPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedPreferences.swift; sourceTree = "<group>"; };
3A9144D82A46AE370036E9AD /* ShadredPreferences+Database.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ShadredPreferences+Database.swift"; sourceTree = "<group>"; };
@@ -613,6 +622,7 @@
3AF342D32A4AADB2002B34AC /* FormItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormItem.swift; sourceTree = "<group>"; };
3AF3A3D12B2207E1001FD7C1 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS17.0.sdk/usr/lib/libresolv.tbd; sourceTree = DEVELOPER_DIR; };
3AF5E3E62B6F90640058B9E8 /* ProfileOverrideView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileOverrideView.swift; sourceTree = "<group>"; };
9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -886,6 +896,7 @@
3AEC20BC2A45991900A63465 = {
isa = PBXGroup;
children = (
9C37F17C2C131100001B9FA8 /* Localizable.xcstrings */,
3AEC20DB2A4599D000A63465 /* Libbox.xcframework */,
3AEC20F42A459AB400A63465 /* SFI */,
3AEC210A2A459B1900A63465 /* SFM */,
@@ -1094,6 +1105,7 @@
3AF342D22A4AADA5002B34AC /* Abstract */ = {
isa = PBXGroup;
children = (
3A7C8B442D0C81DC0070EE55 /* StringCompat.swift */,
3A7E90302A46745A00D53052 /* ViewBuilder.swift */,
3AF342D32A4AADB2002B34AC /* FormItem.swift */,
3ADF8E022A4B118700900CC8 /* Binding+Unwrap.swift */,
@@ -1487,6 +1499,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9C37F1832C131100001B9FA8 /* Localizable.xcstrings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1494,6 +1507,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9C37F1812C131100001B9FA8 /* Localizable.xcstrings in Resources */,
3AC03B9D2A72BF3500B7946F /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1519,6 +1533,7 @@
files = (
3A6CA5A92A713C420027933B /* AppIcon.icns in Resources */,
3AABFD432A9CC5A7005A24A4 /* Upload.plist in Resources */,
9C37F17D2C131100001B9FA8 /* Localizable.xcstrings in Resources */,
3AEC20FA2A459AB500A63465 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1529,6 +1544,7 @@
files = (
3A6CA5A72A713ABA0027933B /* AppIcon.icns in Resources */,
3A6CA5A32A713A580027933B /* Assets.xcassets in Resources */,
9C37F17E2C131100001B9FA8 /* Localizable.xcstrings in Resources */,
3A251C122A52D09700651082 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1537,6 +1553,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9C37F1822C131100001B9FA8 /* Localizable.xcstrings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1552,6 +1569,7 @@
buildActionMask = 2147483647;
files = (
3AABFD472A9CCC58005A24A4 /* Upload.plist in Resources */,
9C37F17F2C131100001B9FA8 /* Localizable.xcstrings in Resources */,
3A6CA5A82A713B340027933B /* AppIcon.icns in Resources */,
3AEC8A4F2A6E5E18003702E1 /* Assets.xcassets in Resources */,
3A2F29EB2C998A5D007E024C /* Export.plist in Resources */,
@@ -1563,6 +1581,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9C37F1842C131100001B9FA8 /* Localizable.xcstrings in Resources */,
3A6CA5A62A713AA10027933B /* AppIcon.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1626,6 +1645,7 @@
3ACE6DE32ACADF55009D9A8A /* Binding+Setter.swift in Sources */,
3A4EAD262A4FEB65005435B3 /* ExtensionStatusView.swift in Sources */,
3A63269E2C0DE12D0076E274 /* ConnectionListView.swift in Sources */,
3A7C8B452D0C81E10070EE55 /* StringCompat.swift in Sources */,
3A4EAD252A4FEB65005435B3 /* StartStopButton.swift in Sources */,
3A6326A02C0DE15C0076E274 /* Connection.swift in Sources */,
3A4EAD2B2A4FEB6D005435B3 /* ViewBuilder.swift in Sources */,
@@ -100,10 +100,11 @@ findVersion:
}
func publishTestflight(ctx context.Context) error {
tag, err := build_shared.ReadTag()
tagVersion, err := build_shared.ReadTagVersion()
if err != nil {
return err
}
tag := tagVersion.VersionString()
client := createClient()
buildIDsResponse, _, err := client.TestFlight.ListBuildIDsForBetaGroup(ctx, groupID, nil)
@@ -146,15 +147,29 @@ func publishTestflight(ctx context.Context) error {
return err
}
}
if common.Contains(buildIDS, builds.Data[0].ID) {
log.Info(string(platform), " ", tag, " already published")
continue
if !common.Contains(buildIDS, builds.Data[0].ID) {
log.Info(string(platform), " ", tag, " publish")
_, err = client.TestFlight.AddBuildsToBetaGroup(ctx, groupID, []string{builds.Data[0].ID})
if err != nil {
return err
}
}
log.Info(string(platform), " ", tag, " publish")
_, err = client.TestFlight.AddBuildsToBetaGroup(ctx, groupID, []string{builds.Data[0].ID})
log.Info(string(platform), " ", tag, " list submissions")
betaSubmissions, _, err := client.TestFlight.ListBetaAppReviewSubmissions(ctx, &asc.ListBetaAppReviewSubmissionsQuery{
FilterBuild: []string{builds.Data[0].ID},
})
if err != nil {
return err
}
if len(betaSubmissions.Data) == 0 {
log.Info(string(platform), " ", tag, " create submission")
_, _, err = client.TestFlight.CreateBetaAppReviewSubmission(ctx, builds.Data[0].ID)
if err != nil {
return err
}
continue
}
}
return nil
}
+65 -42
View File
@@ -9,6 +9,7 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/conntrack"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/experimental/libbox/platform"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/atomic"
@@ -16,6 +17,7 @@ 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/service"
)
var (
@@ -33,19 +35,22 @@ type DefaultDialer struct {
udpAddr6 string
isWireGuardListener bool
networkManager adapter.NetworkManager
networkStrategy C.NetworkStrategy
networkStrategy *C.NetworkStrategy
networkType []C.InterfaceType
fallbackNetworkType []C.InterfaceType
networkFallbackDelay time.Duration
networkLastFallback atomic.TypedValue[time.Time]
}
func NewDefault(networkManager adapter.NetworkManager, options option.DialerOptions) (*DefaultDialer, error) {
func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDialer, error) {
networkManager := service.FromContext[adapter.NetworkManager](ctx)
platformInterface := service.FromContext[platform.Interface](ctx)
var (
dialer net.Dialer
listener net.ListenConfig
interfaceFinder control.InterfaceFinder
networkStrategy C.NetworkStrategy
networkStrategy *C.NetworkStrategy
networkType []C.InterfaceType
fallbackNetworkType []C.InterfaceType
networkFallbackDelay time.Duration
@@ -74,40 +79,40 @@ func NewDefault(networkManager adapter.NetworkManager, options option.DialerOpti
listener.Control = control.Append(listener.Control, control.RoutingMark(autoRedirectOutputMark))
}
}
if C.NetworkStrategy(options.NetworkStrategy) != C.NetworkStrategyDefault {
if options.BindInterface != "" || options.Inet4BindAddress != nil || options.Inet6BindAddress != nil {
return nil, E.New("`network_strategy` is conflict with `bind_interface`, `inet4_bind_address` and `inet6_bind_address`")
}
networkStrategy = C.NetworkStrategy(options.NetworkStrategy)
networkType = common.Map(options.NetworkType, option.InterfaceType.Build)
fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build)
networkFallbackDelay = time.Duration(options.NetworkFallbackDelay)
if networkManager == nil || !networkManager.AutoDetectInterface() {
return nil, E.New("`route.auto_detect_interface` is require by `network_strategy`")
if options.BindInterface != "" || options.Inet4BindAddress != nil || options.Inet6BindAddress != nil || options.TCPFastOpen {
if options.NetworkStrategy != nil || len(options.NetworkType) > 0 && options.FallbackNetworkType == nil && options.FallbackDelay == 0 {
return nil, E.New("`network_strategy` is conflict with `bind_interface`, `inet4_bind_address`, `inet6_bind_address` and `tcp_fast_open`")
}
}
if networkManager != nil && options.BindInterface == "" && options.Inet4BindAddress == nil && options.Inet6BindAddress == nil {
if networkManager != nil {
defaultOptions := networkManager.DefaultOptions()
if options.BindInterface == "" {
if defaultOptions.BindInterface != "" {
bindFunc := control.BindToInterface(networkManager.InterfaceFinder(), defaultOptions.BindInterface, -1)
dialer.Control = control.Append(dialer.Control, bindFunc)
listener.Control = control.Append(listener.Control, bindFunc)
} else if networkManager.AutoDetectInterface() {
if defaultOptions.NetworkStrategy != C.NetworkStrategyDefault && C.NetworkStrategy(options.NetworkStrategy) == C.NetworkStrategyDefault {
if defaultOptions.BindInterface != "" {
bindFunc := control.BindToInterface(networkManager.InterfaceFinder(), defaultOptions.BindInterface, -1)
dialer.Control = control.Append(dialer.Control, bindFunc)
listener.Control = control.Append(listener.Control, bindFunc)
} else if networkManager.AutoDetectInterface() {
if platformInterface != nil {
println("ns create")
networkStrategy = (*C.NetworkStrategy)(options.NetworkStrategy)
if networkStrategy == nil {
networkStrategy = common.Ptr(C.NetworkStrategyDefault)
}
networkType = common.Map(options.NetworkType, option.InterfaceType.Build)
fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build)
if networkStrategy == nil && len(networkType) == 0 && len(fallbackNetworkType) == 0 {
networkStrategy = defaultOptions.NetworkStrategy
networkType = defaultOptions.NetworkType
fallbackNetworkType = defaultOptions.FallbackNetworkType
}
networkFallbackDelay = time.Duration(options.FallbackDelay)
if networkFallbackDelay == 0 && defaultOptions.FallbackDelay != 0 {
networkFallbackDelay = defaultOptions.FallbackDelay
bindFunc := networkManager.ProtectFunc()
dialer.Control = control.Append(dialer.Control, bindFunc)
listener.Control = control.Append(listener.Control, bindFunc)
} else {
bindFunc := networkManager.AutoDetectInterfaceFunc()
dialer.Control = control.Append(dialer.Control, bindFunc)
listener.Control = control.Append(listener.Control, bindFunc)
}
}
bindFunc := networkManager.ProtectFunc()
dialer.Control = control.Append(dialer.Control, bindFunc)
listener.Control = control.Append(listener.Control, bindFunc)
}
if options.RoutingMark == 0 && defaultOptions.RoutingMark != 0 {
dialer.Control = control.Append(dialer.Control, control.RoutingMark(defaultOptions.RoutingMark))
@@ -172,9 +177,6 @@ func NewDefault(networkManager adapter.NetworkManager, options option.DialerOpti
listener.Control = control.Append(listener.Control, controlFn)
}
}
if networkStrategy != C.NetworkStrategyDefault && options.TCPFastOpen {
return nil, E.New("`tcp_fast_open` is conflict with `network_strategy` or `route.default_network_strategy`")
}
tcpDialer4, err := newTCPDialer(dialer4, options.TCPFastOpen)
if err != nil {
return nil, err
@@ -204,7 +206,7 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address
if !address.IsValid() {
return nil, E.New("invalid address")
}
if d.networkStrategy == C.NetworkStrategyDefault {
if d.networkStrategy == nil {
switch N.NetworkName(network) {
case N.NetworkUDP:
if !address.IsIPv6() {
@@ -223,12 +225,21 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address
}
}
func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network string, address M.Socksaddr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
if strategy == C.NetworkStrategyDefault {
func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network string, address M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
if strategy == nil {
strategy = d.networkStrategy
}
if strategy == nil {
return d.DialContext(ctx, network, address)
}
if !d.networkManager.AutoDetectInterface() {
return nil, E.New("`route.auto_detect_interface` is require by `network_strategy`")
if len(interfaceType) == 0 {
interfaceType = d.networkType
}
if len(fallbackInterfaceType) == 0 {
fallbackInterfaceType = d.fallbackNetworkType
}
if fallbackDelay == 0 {
fallbackDelay = d.networkFallbackDelay
}
var dialer net.Dialer
if N.NetworkName(network) == N.NetworkTCP {
@@ -243,9 +254,9 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin
err error
)
if !fastFallback {
conn, isPrimary, err = d.dialParallelInterface(ctx, dialer, network, address.String(), strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
conn, isPrimary, err = d.dialParallelInterface(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
} else {
conn, isPrimary, err = d.dialParallelInterfaceFastFallback(ctx, dialer, network, address.String(), strategy, interfaceType, fallbackInterfaceType, fallbackDelay, d.networkLastFallback.Store)
conn, isPrimary, err = d.dialParallelInterfaceFastFallback(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay, d.networkLastFallback.Store)
}
if err != nil {
return nil, err
@@ -257,7 +268,7 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin
}
func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
if d.networkStrategy == C.NetworkStrategyDefault {
if d.networkStrategy == nil {
if destination.IsIPv6() {
return trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6))
} else if destination.IsIPv4() && !destination.Addr.IsUnspecified() {
@@ -270,10 +281,22 @@ func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksadd
}
}
func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error) {
if strategy == C.NetworkStrategyDefault {
func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error) {
if strategy == nil {
strategy = d.networkStrategy
}
if strategy == nil {
return d.ListenPacket(ctx, destination)
}
if len(interfaceType) == 0 {
interfaceType = d.networkType
}
if len(fallbackInterfaceType) == 0 {
fallbackInterfaceType = d.fallbackNetworkType
}
if fallbackDelay == 0 {
fallbackDelay = d.networkFallbackDelay
}
if !d.networkManager.AutoDetectInterface() {
return nil, E.New("`route.auto_detect_interface` is require by `network_strategy`")
}
@@ -281,7 +304,7 @@ func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destina
if destination.IsIPv4() && !destination.Addr.IsUnspecified() {
network += "4"
}
return trackPacketConn(d.listenSerialInterfacePacket(ctx, d.udpListener, network, "", strategy, interfaceType, fallbackInterfaceType, fallbackDelay))
return trackPacketConn(d.listenSerialInterfacePacket(ctx, d.udpListener, network, "", *strategy, interfaceType, fallbackInterfaceType, fallbackDelay))
}
func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) {
@@ -180,21 +180,19 @@ func selectInterfaces(networkManager adapter.NetworkManager, strategy C.NetworkS
for _, iif := range interfaces {
if iif.Index == defaultIf.Index {
primaryInterfaces = append(primaryInterfaces, iif)
} else {
fallbackInterfaces = append(fallbackInterfaces, iif)
}
}
} else {
primaryInterfaces = common.Filter(interfaces, func(iif adapter.NetworkInterface) bool {
return common.Contains(interfaceType, iif.Type)
primaryInterfaces = common.Filter(interfaces, func(it adapter.NetworkInterface) bool {
return common.Contains(interfaceType, it.Type)
})
}
case C.NetworkStrategyHybrid:
if len(interfaceType) == 0 {
primaryInterfaces = interfaces
} else {
primaryInterfaces = common.Filter(interfaces, func(iif adapter.NetworkInterface) bool {
return common.Contains(interfaceType, iif.Type)
primaryInterfaces = common.Filter(interfaces, func(it adapter.NetworkInterface) bool {
return common.Contains(interfaceType, it.Type)
})
}
case C.NetworkStrategyFallback:
@@ -203,18 +201,25 @@ func selectInterfaces(networkManager adapter.NetworkManager, strategy C.NetworkS
for _, iif := range interfaces {
if iif.Index == defaultIf.Index {
primaryInterfaces = append(primaryInterfaces, iif)
} else {
fallbackInterfaces = append(fallbackInterfaces, iif)
break
}
}
} else {
primaryInterfaces = common.Filter(interfaces, func(iif adapter.NetworkInterface) bool {
return common.Contains(interfaceType, iif.Type)
primaryInterfaces = common.Filter(interfaces, func(it adapter.NetworkInterface) bool {
return common.Contains(interfaceType, it.Type)
})
}
if len(fallbackInterfaceType) == 0 {
fallbackInterfaces = common.Filter(interfaces, func(it adapter.NetworkInterface) bool {
return !common.Any(primaryInterfaces, func(iif adapter.NetworkInterface) bool {
return it.Index == iif.Index
})
})
} else {
fallbackInterfaces = common.Filter(interfaces, func(iif adapter.NetworkInterface) bool {
return common.Contains(fallbackInterfaceType, iif.Type)
})
}
fallbackInterfaces = common.Filter(interfaces, func(iif adapter.NetworkInterface) bool {
return common.Contains(fallbackInterfaceType, iif.Type)
})
}
return primaryInterfaces, fallbackInterfaces
}
@@ -13,7 +13,13 @@ import (
N "github.com/sagernet/sing/common/network"
)
func DialSerialNetwork(ctx context.Context, dialer N.Dialer, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
func DialSerialNetwork(ctx context.Context, dialer N.Dialer, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
if len(destinationAddresses) == 0 {
if !destination.IsIP() {
panic("invalid usage")
}
destinationAddresses = []netip.Addr{destination.Addr}
}
if parallelDialer, isParallel := dialer.(ParallelNetworkDialer); isParallel {
return parallelDialer.DialParallelNetwork(ctx, network, destination, destinationAddresses, strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
}
@@ -38,7 +44,14 @@ func DialSerialNetwork(ctx context.Context, dialer N.Dialer, network string, des
return nil, E.Errors(errors...)
}
func DialParallelNetwork(ctx context.Context, dialer ParallelInterfaceDialer, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, preferIPv6 bool, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
func DialParallelNetwork(ctx context.Context, dialer ParallelInterfaceDialer, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, preferIPv6 bool, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
if len(destinationAddresses) == 0 {
if !destination.IsIP() {
panic("invalid usage")
}
destinationAddresses = []netip.Addr{destination.Addr}
}
if fallbackDelay == 0 {
fallbackDelay = N.DefaultFallbackDelay
}
@@ -116,7 +129,13 @@ func DialParallelNetwork(ctx context.Context, dialer ParallelInterfaceDialer, ne
}
}
func ListenSerialNetworkPacket(ctx context.Context, dialer N.Dialer, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error) {
func ListenSerialNetworkPacket(ctx context.Context, dialer N.Dialer, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error) {
if len(destinationAddresses) == 0 {
if !destination.IsIP() {
panic("invalid usage")
}
destinationAddresses = []netip.Addr{destination.Addr}
}
if parallelDialer, isParallel := dialer.(ParallelNetworkDialer); isParallel {
return parallelDialer.ListenSerialNetworkPacket(ctx, destination, destinationAddresses, strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
}
+8 -13
View File
@@ -17,16 +17,15 @@ import (
)
func New(ctx context.Context, options option.DialerOptions) (N.Dialer, error) {
networkManager := service.FromContext[adapter.NetworkManager](ctx)
if options.IsWireGuardListener {
return NewDefault(networkManager, options)
return NewDefault(ctx, options)
}
var (
dialer N.Dialer
err error
)
if options.Detour == "" {
dialer, err = NewDefault(networkManager, options)
dialer, err = NewDefault(ctx, options)
if err != nil {
return nil, err
}
@@ -37,9 +36,6 @@ func New(ctx context.Context, options option.DialerOptions) (N.Dialer, error) {
}
dialer = NewDetour(outboundManager, options.Detour)
}
if networkManager == nil {
return NewDefault(networkManager, options)
}
if options.Detour == "" {
router := service.FromContext[adapter.Router](ctx)
if router != nil {
@@ -58,11 +54,10 @@ func NewDirect(ctx context.Context, options option.DialerOptions) (ParallelInter
if options.Detour != "" {
return nil, E.New("`detour` is not supported in direct context")
}
networkManager := service.FromContext[adapter.NetworkManager](ctx)
if options.IsWireGuardListener {
return NewDefault(networkManager, options)
return NewDefault(ctx, options)
}
dialer, err := NewDefault(networkManager, options)
dialer, err := NewDefault(ctx, options)
if err != nil {
return nil, err
}
@@ -77,11 +72,11 @@ func NewDirect(ctx context.Context, options option.DialerOptions) (ParallelInter
type ParallelInterfaceDialer interface {
N.Dialer
DialParallelInterface(ctx context.Context, network string, destination M.Socksaddr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error)
DialParallelInterface(ctx context.Context, network string, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error)
}
type ParallelNetworkDialer interface {
DialParallelNetwork(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
ListenSerialNetworkPacket(ctx context.Context, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error)
DialParallelNetwork(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
ListenSerialNetworkPacket(ctx context.Context, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error)
}
+2 -2
View File
@@ -106,7 +106,7 @@ func (d *resolveDialer) ListenPacket(ctx context.Context, destination M.Socksadd
return bufio.NewNATPacketConn(bufio.NewPacketConn(conn), M.SocksaddrFrom(destinationAddress, destination.Port), destination), nil
}
func (d *resolveParallelNetworkDialer) DialParallelInterface(ctx context.Context, network string, destination M.Socksaddr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
func (d *resolveParallelNetworkDialer) DialParallelInterface(ctx context.Context, network string, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
if !destination.IsFqdn() {
return d.dialer.DialContext(ctx, network, destination)
}
@@ -134,7 +134,7 @@ func (d *resolveParallelNetworkDialer) DialParallelInterface(ctx context.Context
}
}
func (d *resolveParallelNetworkDialer) ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error) {
func (d *resolveParallelNetworkDialer) ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error) {
if !destination.IsFqdn() {
return d.dialer.ListenPacket(ctx, destination)
}
+22
View File
@@ -0,0 +1,22 @@
package tls
import (
"time"
"github.com/sagernet/sing/common/ntp"
)
type TimeServiceWrapper struct {
ntp.TimeService
}
func (w *TimeServiceWrapper) TimeFunc() func() time.Time {
if w.TimeService == nil {
return nil
}
return w.TimeService.TimeFunc()
}
func (w *TimeServiceWrapper) Upstream() any {
return w.TimeService
}
+1 -1
View File
@@ -2,7 +2,7 @@
icon: material/alert-decagram
---
#### 1.11.0-beta.9
#### 1.11.0-beta.10
* Fixes and improvements

Some files were not shown because too many files have changed in this diff Show More